Rebel Science News
Jeff Hawkins Is Close to Something Big
The Myth of the Bayesian Brain
The Second Great AI Red Herring Chase
Rebel Speech Recognition Theory
Rebel Speech Update

Software Composition in COSA

Components and Connectors



Rebel Science Home
Why Software Is Bad
Project COSA
Operating System
Software Composition
Parallel QuickSort
The Devil's Advocate
COSA Discussion Forum
Not Associated with V.S. Merlot, Inc.
Contact Me


Visual Software Construction
Two Types of Components
"While Loop" Component
Data Sharing
  Construction and Destruction
  Message Connectors
  Unique IDs
Data Types and Structures
Component Repository

Abstract: This page describes the COSA software composition environment. COSA is an alternative software construction and execution system designed to improve reliability and productivity by several orders of magnitude. COSA is based on the premise that the primary reason that computer programs are unreliable is the age-old practice of using the algorithm as the basis of software construction. Switch to a synchronous, signal-based model and the problem will disappear. Please refer to the previous articles (The Silver Bullet, Project COSA and The COSA Operating System) in the series for important background information.

Note: This page is still under construction. The information that follows is not complete and may not accurately reflect the COSA model. Please read COSA: A New Kind of Programming and The COSA Control Hierarchy for the latest in COSA software composition.

Visual Software Construction

The COSA software construction environment is designed to make software development as painless and easy to understand as possible. There is no cryptic language to learn and no syntax to worry about. A developer can quickly put an application together by dragging in a few objects into the work area and connecting them together. Once the structural design is in place, the designer can then go in and specify the underlying details. Visual software tools have been around for some time but they usually come with some sort of algorithmic scripting language and that is their main flaw. Another major flaw is the proliferation of icons. In COSA, there are only seven icons: cells (effectors and sensors), synapses, components, connectors, data and signal pathways.

One of the nicer things about a component-based visual development environment is that it affords the software composer with a quick and easy way to identify and navigate through dependencies. If two objects are connected, they obviously share a dependency. Double click on an object and instantly access its specifications. Double click on a connector to modify its message or type. Pre-built components can be stored in a keyword-searchable and browsable repository or can be downloaded from the web. Drop a component into an application under development and, whenever possible, it will automatically and flawlessly connect itself to other compatible components.

Note that COSA does not prohibit the use of sequential steps to solve any problem for which one would normally use an algorithm. The main difference is that COSA is 100% change-driven. Comparison operators thus become change sensors. That is, they are self-activating as opposed to being explicitly invoked, as is the case in conventional software. A COSA development system automatically couples every sensor (comparison operators) with any effector (operation) that may potentially affect the sensor. The result is that blind code is completely eliminated, thus enabling the creation of extremely robust software. The whole thing is, of course, completely transparent to the developer.


A component is a container for cells, connectors, data, or other components. It is important to understand that components exist primarily for the benefit of the software designer and the end user. Their main function is to serve as an organizing mechanism for saving and loading, and for grouping cells together into plug-compatible ensembles. The COSA execution kernel does not handle components and connectors directly. Indeed, the kernel only “sees” cells, their synapses and their data. Nothing else. Internally, a component is a collection of pointers to cells, connectors, synapses, data and/or other components.

The left figure above shows a component with three female and three male connectors. Double clicking on a component opens it up to reveal its contents. The picture on the right shows a component that has been clicked open to reveal several other components. In this case, the designer chose eight internal connectors to be externally accessible. Note that three of the externally accessible connectors are grouped into a single male multi-connector on the left side of the component. The actual layout of objects inside a component enclosure is arbitrary and is left to the discretion of the designer. The naming labels are omitted in the figures due to the reduced size. User-created labels (such as ‘Save Document’, ‘count++’, ‘A = B + C’ or ‘width != 60’) make it easy to figure out what is actually going on. The developer has the option of showing or hiding the labels. In the case of elementary cells, labels can be automatically created by the development tool.

Two Types of Components

There are two types of components, low-level and high-level. A low-level component contains one or more elementary cells, at least one connector (for input) and associated data. A high-level component consists of one or more other components. Cells are not allowed to exist at the same containment level as components. A component can be thought of as an inheritance mechanism. Drop a component into another and the target component automatically inherits the functionality of the other.

The figures below show examples of what a designer may see after double clicking on a component icon. The left figure is a high-level component and the right figure is low-level component. The color scheme is as follows: all components are painted dark green; effectors are light green and sensors are yellow. The small red circles are male connectors or synapses. Female synapses can be either white (positive) or black (negative).

The "While Loop" Component

New: The Parallel QuickSort Example offers more details on software composition in COSA.

The "while loop" component (above right) is a low-level component because it contains only cells. The one-shot assignment effector (1=) initializes the loop upon receipt of a start signal and then activates the two “loop” effectors (100+ and 100=). The effectors repeatedly increments an internal counter variable while adding (the 100+ cell) and storing data (the 100= cell) in memory until either the not-equal (!=) comparison sensor is satisfied or the effectors have run their course. The dashed-line bracket joining the 100+ and the != cells indicates a sensor-effector association. When the comparison is satisfied, the comparison sensor (!=) outputs a signal that stops both effectors simultaneously. It also sends a signal to the OR detector to indicate that the loop has terminated. The cell fires if it receives a signal from either the comparison sensor or the 100= effector. This means that there are two ways in which the loop can terminate: either the comparison is satisfied or the effector has run its course. The equivalent algorithmic code might look something like this in C++:

A = 0;               // the 1= cell
x = 0;               // internal loop counter
do {
   A = A + 1;        // the 100+ cell
   Buffer1[x] = Buffer2[x];    // the 100= cell
   x = x + 1;        // increment internal counter
while (x != 100 && Buffer1[x] != 0) // comparisons

Note. Even though I use the word 'loop' in this discussion, there really is no looping going on in the given example. No signal is fed from the output side of any of the cells back to the input side. This is because every effector is self-activating, that is to say, upon receiving a start signal, an effector will repeat its operation up to a prescribed number of cycles unless it receives a stop signal beforehand. Additionally, if a sensor is associated with an effector, effecting and sensing take place concurrently during the same cycle. This is not to say that actual signal looping cannot be done in COSA. Indeed, at times, it cannot be avoided. For example, it may be necessary to send a message to another component at every iteration of the loop and wait for a return message. 

Constructing the loop component consists of using the mouse to drag the desired cells and connectors into a new component enclosure, and then connecting them together. Each connector is automatically given a unique ID. It is up to the designer to accept the default or use an existing ID. Click on the data structure to define the operands and constants for the component. Click on the effectors to open up a property box. This will allow you to specify the operator and operand types for each effector. Use the mouse to connect the cells to each other as desired. Finally connect the cells to the connectors. Of course, if you already have a loop component in the repository (which is very likely), it is easier to just copy the existing component and modify it to suit your requirements. Most low-level development in COSA will consist of reusing existing components.


The reentrancy problems that sometimes plague conventional algorithmic software are nonexistent in COSA. The loop component provides a perfect example of how potential timing conflicts are resolved. What would happen if the component receives a second start signal while the loop is still running? During development, COSA enforces the Principle of Motor Coordination or PMC which states that a start signal must not follow another start signal and a stop signal must not follow another stop signal. The PMC enforcer alerts the designer whenever there is a timing conflict. In the loop component, a conflict would be flagged if either of the two loop effectors receive a start signal before they are finished.

If two or more components require the services of another component simultaneously, they must use a message server. The latter places all request messages in a queue to be processed one at a time. If necessary, especially in time-critical environments, multiple instances of a loop component may be used simultaneously.

Note: The above does not mean that a recurrent process cannot be implemented within a component or with the use of two or more components. Reentrance is not the same as recurrence.

Data Sharing

High-level components do not have data at their level. They are just containers for other components. Most low-level components will have a data structure, the properties of which can be accessed by its cells. Components cannot directly access each other's data. That is to say, a component's internal data is always private. The only way a component may access another component's data is through an explicit request message. For example, a quick sort component may receive a request from another component to sort an array of integers. After completing the request, the sorter sends a 'service completed' signal back to the service requester.

The only data that may be shared directly between two components is message data. Even then, the destination component only has read permission. This is because two communicating components share a single message structure. The primary reason for the strict rule against data sharing is to prevent misuse. It would be too easy for one component to modify a property in another component without the knowledge of the other. This can potentially lead to incorrect assumptions and ultimately to catastrophic failure. In multi-threaded architectures, it is customary to use semaphores and other techniques to prevent two threads from simultaneously accessing a data structure. These techniques are not used in COSA because data sharing is forbidden.


A connector is a mechanism used by the designer to link two components together. Internally, however, only cells can be connected to one another, as explained below. Connectors exist mainly for the benefit of the application developer. The same can be said of components. Connectors do nothing, in and of themselves. Their purpose is to enforce compatibility between connected components. There are two types of connectors: uni-connectors and multi-connectors.


A uni-connector is a mechanism that serves as a one-way signal conduit between two components. Every uni-connector must have a unique ID number and a gender (male or female). Males can only be connected to females and vice versa. Signal direction is always from male (plug) to female (socket). A male uni-connector and its female counterpart share the same unique ID.

Although uni-connectors are said to connect components together, internally however, only cells are connected to each other. A pair of uni-connectors is used to connect a sender cell from a source component to a receiving cell in a destination component.

Uni-connectors are normally used for one-to-one or one-to-many connections. Many-to-one communication is possible in COSA but it is managed with the help of a special component called the message server. Multiple messages arriving asynchronously must be placed in a queue and wait their turn to be processed. It follows that, while a male uni-connector may be connected to multiple female uni-connectors, the reverse is not true. That is to say, a female uni-connector cannot not be connected to more than one male connector. However, a female connector may be attached to more than one cell residing in the component it is attached to.


A multi-connector is a set of uni-connectors. It too has a unique ID, a visibility level and can be either male or female. A multi-connector can have an unlimited number of male and/or female uni-connectors. A male multi-connector is the complement of a female multi-connector. For every uni-connector in a male multi-connector there must be a counterpart in the female complement. The gender of a multi-connector is used only as a way to ensure compatibility between complementary connectors. It is not as an indicator of signal direction. Indeed, a multi-connector can be either uni-directional or bi-directional depending on its constituents.

Multi-connectors are convenient composition aids because, more often than not, a component must make multiple connections with another, usually in the form of bi-drectional two-pin connectors. The component designer may want to constrain a connection so as to require that all the connectors in an MC be connected simultaneously. If any of the uni-connectors fails to connect, the connection manager will not complete the connection. Multi-connectors add compatibility constraints and thus eliminate opportunities for errors. Unlike uni-connectors which are one-to-many, a multi-connector is a one-to-one connector.


All connectors are created with an initial visibility level. A connector is visible only to other connectors residing at the same containment level. In other words, if component A is placed inside component B, A's connectors are visible to all components inside B but invisible to all components outside of B. It is up to the software designer to decide whether or not to increase a connector's visibility level so as to make it visible to components above its current level. Visibility levels are somewhat analogous to the public and protected keywords in C++.

Message Connectors

A message connector is a special uni-connector used for passing messages from one source component to one or more destination components. It is up to the receiver to act on the message as quickly as possible and acknowledge receipt so as to free the structure for future messages. This is normally done with a two-way connection between sender and receiver, one for sending and one for acknowledgement. If a receiving component expects to receive multiple messages of a given type from several senders or if the sender cannot afford to wait for delayed acknowledgement, then it is best to use the services of a message server. Normally it is best to use messages for asynchronous communication. Since components can share data, they can communicate synchronously using signals.

However, effector-sensor associations are forbidden across components. That is to say, an effector in one component cannot be associated with a sensor in another. The COSA development environment will not allow it because, for organizational and security purposes, no component is allowed to have direct sensory access to what is happening in another. 


A message is a structure with various fields of data, the content and format of which is only accessible to compatible sender and receiver components. A message structure is an integral part of its parent uni-connector. In fact, they share a unique ID together. All messages must contain at least two fields, one to hold the length of the message and another to hold the ID proper. Some messages, such as the ones used with the message router component, must have two additional fields: one to hold the address of the sender cell and the other for the destination cell.

Sending a message is no different than sending a signal. Of course, the sending component should fill the message structure with pertinent data before signaling the destination component. Note that the data structure that represents the message never moves in memory. This makes for rapid message communication. A component must have either read or write permission to access or modify a message. This is enforced by the development tool.

Unique IDs

Both messages and connectors are assigned unique 16-byte ID numbers on creation. Each ID number represents a unique message or connector type. IDs are universally unique, meaning that no two signal or message types can share a given ID. It does not mean that there is only one connector per ID. An ID registry has to be maintained as part of the component repository for easy access to all developers within an organization. Public IDs and their definitions may have to be kept in a registry maintained by a non-profit organization. There are other issues related to IDs that will have to be resolved. For example, a component designer may decide, for security reasons, to keep some of his or her IDs private by not publishing their meanings or the specifications of their associated messages. Or even the ID itself. This way, the ID essentially serves as an unbreakable 16-byte password.

Construction and Destruction

Every component that requires initialization must use a special female uni-connector for construction and a special male uni-connector to signal when it is ready. The component manager sends a special "construct" signal after loading a component into memory. The component designer should use construction connectors to string components together so as to achieve the desired order of initialization.

Destruction also requires special male and female uni-connectors. Again, it is up to the component designer to make sure that components are destructed in the desired order. After destruction, the component manager deletes the component from memory.


I am toying with the idea of adding password protection to the connectors themselves. That would be in addition to type ID. Of course, if a component publisher declines to publish the unique IDs of a component's connectors, no one can connect to them. However, sometimes a software designer may want to use a known public component while finding it necessary to restrict access to a few chosen clients. Having the ability to add password protection to individual connectors would solve this problem.

One of the nice things about not allowing new executable code into the system is that it eliminates a lot of  security problems. This is especially true in the age of the internet with thousands of machines connected to one another.

Data Types and Structures

Data typing in COSA follows the same principles as data typing in algorithmic languages such as C and C++. In other words, types will include integer, long integer, floating point, character, etc... In addition, the software developer will have the option of creating custom data types from any combination of the basic types. Typing enforcement is maintained automatically at the connector level. It is impossible to create two matched (male/female) connectors with incompatible message types.


Every application is a COSA component and, as such, is an extension of the operating system. However, COSA comes with a suite of service components that form the core of a minimum operating system. Examples are message servers (stack-based and queue-based), file I/O server, memory manager, connection manager, component constructors and destructors, component and cell containers (lists, arrays, etc...), print manager, graphics manager, RAD development tools, etc... Of special importance is the connection manager (CM) which can be used by an application/component for self-modification. The CM can be directed to create new connections on the fly or to sever one or more existing connections if necessary. This can happen either at the component level or the cell/synapse level.

Note: I am preparing a page on Service Components.  To be continued...

Component Repository

The component repository is a browsable and keyword searchable SQL database. Its job is to facilitate and encourage reuse during application development. After a component has been tested and documented, it should be dropped in the repository for future reuse. The repository comes with tools that automatically searches a stored component's documentation for pertinent keywords. Software designers should make it a habit of searching the repository before creating a new component.



©2004-2006 Louis Savain

Copy and distribute freely