The following are the requirements for the mBrane framework. They are explained in detail below. See the initial list at the bottom of the page.
There are a few rules to decide whether or not a feature belongs to the scope of mBrane. A feature is within the scope of mBrane if one of the following propositions is true:
A it impacts transmission
B it impacts contextualization
C a significant performance increase is foreseen if the feature is implemented in mBrane AND such an implementation impacts significantly the mBrane code base.
D it requires specific low-level support from mBrane (ex: notifications of internal events)
This features comes mainly from the requirement of running more modules than there are threads. This implies that mBrane schedules user code.
We propose the following solution: mBrane is run by the OS and the OS is tweaked so that mBranes receives most of the CPU time. Within that time, user code can be scheduled deterministically with very low overhead and latencies. On a stripped down, patched (latency & kernel preemption) Linux developers would be able to target soft real time response schemes (if they code correctly their cranks).
mBrane is not intended to compete on the embedded market, its goal being more about allowing researchers to approach the soft real time domain without having to learn how to code rigorously on expensive platforms for which no interesting off the shelf software really exist (RTOSes).
Whiteboards are modules, they implement particular functions to support whiteboard-based architectures. Whiteboards do not affect neither transmission nor contextualization. As such they go beyond the scope of mBrane and are not part of the requirements. Idem for time-to-live in messages. This data can be encoded in specific message subclasses, handled by modules dealing with history / long term memory (i.e. whiteboards).
This is a functionality which does not address neither transmission nor contextualization. Can be easily implemented with user-defined module classes able to understand internal state relocation. Message history to be implemented by whiteboards. Playing-control messages fall in the category of general purpose messages. More over no performance improvement can be expected in burying this feature in mBrane.
It is an improvement of contextualization, and performance increases can be expected from integrating that feature in mBrane. However, no performance degradation will occur if we add pregnances later in a given version of mBrane.
Reason: pregnance-driven computing is subscription-free, and shall be implemented as a particular activation / routing process, at the node level. This can be done without changing anything in the existing node code, excepted minor code configuration changes.
mBrane offers already messages that reflects entirely its activity: control messages. Extended levels of reflectivity are therefore application dependent and their notification falls in the category of general purpose messages.
Support for module instance migration is offered. Migration algorithms are to be designed on a case-by-case basis, depending on the needs of the applications.
Reason: we do not believe that a general and optimal solution exists.
Can be achieved by having modules wait on specific - but regular - synchronization messages. This feature does not require specific support from mBrane.
Simulation means running a module from hypothetical inputs and getting hypothetical results. This describes applying a particular semantic to the execution of modules. mBrane supports the execution of modules, the application interprets the setup and the results.
If pattern matching is to save bandwidth (content-based subscription), it must be performed at the emission location. This implies making the destination module's code (which supplies the pattern matching algorithm and resources - like internal data and states) available everywhere. Initial studies reveal that this adds a lot of complexity that will eventually lead to noticeable performance hits, for minimal gain. The solution would then consist of running pattern-matchers on the receiving side, as part of the user-supplied module code, which is in line with mBrane capabilities: no specific support is required.
Can be achieved by supplying various versions of the same shared object. No specific support is required.
Can be handled on the receiving side by filtering incoming messages against module-specific code. No specific support is required.
The code may need to be executed by a superuser to support proper thread prioritisation and scheduling.
High-end processors sporting big caches. 64 bits.
A module instance is identified by its class (MID), instance identifier (MIID), and entity identifier.
A crank is identified by its module instance identifier and crank identifier (TID).
This means inverted control flow: the host thread calls the cranks (no polling). The host thread schedules the execution of its cranks. In that respect, cranks are fibers: they explicitly contain preemption points. More over to avoid generic context switching overhead, cranks take care of their own working set.
It reflects the thread priority. Every module embedded in a given thread gets the priority of the highest priority module. A thread is assigned the highest priority amongst those defined by the modules it embeds.
An entity defines an organization of modules and represents a sub-system. An entity E defines the module instances to build when an instance of E is built.
When an entity is destroyed, so are its module instances.
An entity instance is identified by its class (EID) and instance identifier (EIID).
An entity is a blueprint, not code.
Many instances of the same module can belong to the same entity.
In that case they will be reassigned to the root entity.
A group defines a particular membership relationship. Entities do not belong to groups, entities and groups are orthogonal.
A group is defined system-wide, i.e. module instances can belong to any group, regardless of its location in the system.
A group instance is identified by its class (GID) and instance identifier (GIID).
A group instance is active if (1) at least one of its parents is active, and (2) if itself is active. A group instance admits a dynamic parameter specifying if group individual activation is triggered automatically by parent group activation or if explicit activation is required.
When a group is deactivated, its children are considered inactive. When it is reactivated, its children return to their previous activation state.
A module instance is active if (1) at least one of the groups it belongs to is active, (2) if itself is active and (3) the entity it belongs to is active. A module instance admits a dynamic parameter specifying if module individual activation is triggered automatically by group activation or if explicit activation is required.
Activating an entity is a condition for module instance activation. In other words, an active module instance will be considered inactive if the entity it belongs to is inactive. It does not mean that the module is deactivated, i.e. when the entity is reactivated, its module instances regain their previous activation state.
An entity instance is active if (1) its parent is active, and (2) if itself is active. An entity instance admits a dynamic parameter specifying if entity individual activation is triggered automatically by parent activation or if explicit activation is required.
Activation thresholds are defined by groups. Thresholds and activation values are defined dynamically. Thresholds are in [0,1].
A message instance is identified by its class (MCID) and type (mcid, instance-based). A message class derives from a serializable class (provided by the CoreLibrary).
By default, derived from a class-based priority, which can be overridden.
A stream instance is identified by its class (SCID) and content identifier (scid, instance-based).
Stream priority is instance-based. The messages of a given stream instance share the stream instance priority.
It implements the functionalities of building stream messages and handling the associated I/O device.
I.e. frame number.
It also handles the class registration (unique contiguous class identifiers), instance identification, and the mapping of names on identifiers (and vice-versa).
The CommonLibrary is built from the CoreLibrary; it is to be replicated on every node of the system. Actually a hierarchy of more or less application-dependent libraries can be derived from the CoreLibrary.
The libraries are written in C++.
Subscriptions are accumulated when a module is a member of several groups (including group hierarchies).
One node is chosen (automatically) to be the time reference. Shall it leave the system, the global system operation is suspended, another one is chosen automatically and the operation resumed.
Set as a parameter, shall not exceed 2^16-1. A node is identified by a number (NID) in that range.
For example, a module or a message have the same priority anywhere in the system at a given time; the grouping and subscriptions are consistent system-wide at any time. etc.
On which they can offload traffic. NB: that does not mean channel bonding.
General scheme: control messages in broadcast mode on the first network, application data on the rest.
Some of the remaining networks can be statically allocated to heavy streaming.
Application data are directed dynamically to the least busy network.
New Entity Class: sub entity classes|module configurations
Delete Entity Class: EID
New Entity: EID
Delete Entity: EIID
New Group: GID|parent GIID (if relevant)
Delete Group: GIID
New Module: MID
Delete Module: NMIID
Subscribe to Message: NMTID|GIID|array<MCID|mcid>
Unsubscribe to Message: NMTID|GIID|array<MCID>
Subscribe to Stream: NMTID|GIID|array<SCID|scid|sending pattern>
Unsubscribe to Stream: NMTID|GIID|array<SCID|scid>
Add Membership: GIID|NMTID
Remove Membership: GIID|NMTID
Crank Priority: NMTID|priority
Message Priority: MCID|priority
Stream Priority: SCID|scid|priority
Activate Group: GIID
Deactivate Group: GIID
Activate Entity: EIID
Deactivate Entity: EIID
Activate Module: MIID
Deactivate Module: MIID
Join Entity: MIID|EIID
Leave Entity: MIID|EIID
Entity Class Created: EID
Entity Class deleted: EID
Entity Created: EIID
Entity Deleted: EIID
Group Created: GIID
Group Deleted: GIID
Module Created: NMIID
Module Deleted: MIID
Subscription to Message: NMTID|GIID|array<MCID|mcid>
Unsubscription to Message: NMTID|GIID|array<MCID>
Subscription to Stream: NMTID|GIID|array<SCID|scid>
Unsubscription to Stream: NMTID|GIID|array<SCID>
Membership Created: GIID|NMTID
Membership Deleted: GIID|NMTID
Crank priority Changed: NMTID|priority
Message priority Changed: MCID|priority
Stream priority Changed: SCID|scid|priority
Group Activated: GIID
Group Dectivated: GIID
Entity Activated: EIID
Entity Dectivated: EIID
Module Activated: MIID
Module Dectivated: MIID
Joined Entity: MIID|EIID
Left Entity: MIID|EIID
Node joined: NID
Node left: NID
As a train of messages (carrying the same time stamp).
Destinations are node and / or module identifiers. By default no destination has to be specified.
If the message is in an output queue for more than the specified TTL, the node will discard it. By default, TTL is infinite.
Internal structures are updated before regular messages for T>T0 can be processed.
Configuration denotes the specification of setup and initialization procedures.
Documentation and comments are handled in the standard XML way.
I.e. a configuration can #include others.
Names of the entry points in the shared object.
Initial subscriptions
Indicates the initial node location. The sticky bit indicates whether or not the module is allowed (or has the ability) to migrate.
It is the developer's responsibility to ensure that node identifiers are unique, are within the node identification range, with no gaps.
Names given in the various configurations are translated into identifiers. To allow so, names must match C++ identifiers (macros), aggregated in a standard file.
The state and internal data of a module can be transmitted to a target node. On the target node a new instance of the module class is created and initialized with the transmitted data. On the source side, the instance is destroyed. Subscriptions, group membership and entity membership do not change.
This requires that transmissible modules derive from serializable module base classes (provided by the CoreLibrary).
Allows to customize mBrane with low-level functionalities, like encryption, RDMA, or customized networking protocols (ex: reliable multicast).
Allows to customize mBrane with specific message transmission policies, like message aggregation.
To take advantage of / adapt to the specifics introduced by plug-ins A and B.
i.e. what to do with a sending command / receiving event at the node level.
To take advantage of / adapt to the specifics introduced by plug-ins A and B.
i.e. broadcast vs point to point. This is especially important for control messages.
Generally, nodes shall issue periodically network status messages: this would allow the application (or the programmer) to relocate modules.
On their machines; issue work load notification messages. Allows the application to trigger module migration.
This allows modules to tune their output rate and generally, adapt their computation. Ex: streaming modules can decide to drop frames and therefore not to (re)compress them.
All Network Nodes are updated in near-realtime with subscription routing tables.
A Module registers with its local Network Node and all future communication goes through this Node. A Module will always be registered with one and only one Node, but can be moved to another Node at any point in time.
A Module can change its own subscription or the subscription of another Module. A Module can be subscribed by another module even before it registers. This subscription will not be active until the Module registers and will be deactivated when a Module unregisters.
A Module can post messages via its Network Node. This message can either be treated as a message or as a stream, depending on the module subscription.
Modules can be grouped into named groups and acted upon as a single entity.
There will generally be one Network Node per computer in the system. All Modules connect to its local Network Node using direct memory communication (shared memory, etc.).
A Module will have one or more cranks and zero, one or more cranks can be active or activated at the same time.
(See Module Posting)
Ability to activate/deactivate modules by thresholding 2 values (intensity and activation levels), in addition to group-based activation - very easy, big impact. A Module can voluntarily act on a number of control signals, such as Reset, Start, Stop, etc. If a control signal is not handled the default response will be to reply with Control Signal Not Handled.
Ability to run many modules simultaneously in one single thread - hard, big impact. Similar to running multiple active cranks within a module at the same time.
Ability to migrate modules (maybe not every kind of modules, but at least the light modules that run together in a thread) - not so hard, big impact. A Module should be able to be moved between Network Nodes easily and with minimal impact. Could be done by asking the module to handle the Control Signals Pause, Save State, Load State, Start.
Reflectivity (internal inputs) - very easy, small impact
Pregnances / contextualization (optional) of the system operation (as described in mastermind), controlled with an alternate method (instead of neural nets as proposed in mastermind) - hard, small impact
A crank in a Module should run at a provided priority level. This level can be changed by changing the module subscription.
Authorisation, Compression, Encryption
To allow for global synchronisation in time, ie for simulations with atomic global timesteps, or for a number of Modules to agree to wait for a specific signal. These signals can be triggered by time or by some other conditions and will not be programmed in mBrane - mBrane should just allow for the waiting for a named control signal.