DataTime Processing Framework
Design Specification, Phase 1: Core Framework


Home
 |  Users
 |  Programmers  |  Project Developers
 |  SourceForge Project Page
 |  Resources


i. Contents

I.
Purpose
II. General Priorities
III. Design Outline
IV. Design Issues
V. Design Details


I. Purpose

    This document descrtibes the design of the first phase of the DTPF in accordance to the project requirements. The first phase will involve implementing the core framework for off-line (as opposed to real-time) processing. This phase will also not emphasize graphical user interface (GUI) aspects, though it will provide features for later GUI integration. For further background information and a listing of the requirements the reader is referred to the project requirements document.


II. General Priorities

The priorities guiding the design of this first phase of the DTPF project are focused on the the project implementors. In rough order of precedence these are:
  1. Maintainability: This project will continue to be developed for some time. After the first phase a certain ammount of application software will depend upon the DTPF and modifications will need to be made with minimal effect on this application software. New programmers may also become involved in the work. Modifications and enhancements are also likely to occur some time after the initial implementation when original implementors have moved on or are unavailable. It is also expected that the effective working knowledge of those familiar with the framework but not actively working on it will decline with time. The architecture and design need to be documented with these considerations in mind. See: Non-Functional Requirements, Section V.A.
  2. Usability: Here we are mainly concerned with usability regarding the API presented to application developers using the DTPF to create new software. Usability concerns for end-users will become more of a concern as this first phase nears completion and detailed planning of later phases begins. Regarding usability, the API must be complete enough to satisfy the requirements, allowing client program code access to framework services. The API must also allow for the creation of nodes implementing sensory model components with substantially less effort than developing custom application software as discussed in the requirements background information. See: Functional Requirements, all sections.
  3. Extensibility: Future plans for interacting with hardware (e.g., video capture, motor control) will require additions beyond this first phase. The design needs to take this into account and not be specialized to the offline situation. See: Non-Functional Requirements, Section V.E.
  4. Efficiency: As the first phase of the project is to support offline processing, free of real-time constraints, efficiency is of less concern. Reasonable care should be taken to not consume excessive resources for the framework itself to avoid starving the actual processing and to facilitate future application to more time-bound situations. See: Non-Functional Requirements, Section V.F.
  5. Portability: Portability is a lesser concern here. However the design should identify platform-dependent components and provide appropriate abstraction to shield the DTPF from platform dependencies. See: Non-Functional Requirements, Section V.D.


III. Design Outline

High-level description of the design and architecture.

DTPF architectural overview
Figure 1: A top-level view of the DTPF architectural model. Note that the connections shown between nodes are illustrative of a hypothetical situation. In general any node can be connected to any other.

    The architectural model adopted is roughly that of the BeOS MediaKit. Processing is organized into nodes which can be connected together to send data from one to another. Node execution is event based and multi-threaded (e.g., every node has an associated thread for event handling). Nodes can be implemented as application classes that are linked with a client application at compile-time, or nodes can be implemented as plug-ins that are be dynamically linked at run-time. A roster server application (provided with DTPF) maintains bookkeeping information and records of framework resources (e.g., available nodes, potential connection endpoints, connections between nodes), is responsible for creating and controlling certain resources (e.g., shared memory buffers available to separate operating system processes), and acts as a broker for client requests for framework services. A client interface allows program code (node implementations or client applications) to communicate with the roster. A plug-in loader application (provided with DTPF) loads nodes implemented as plug-ins in dynamically linked shared libraries.


IV. Design Issues

Important design issues that have been or need to be resolved.

IV.A:
Issue: Foundational code and system dependent functionality
  • The following set of functionality is needed:
    • Process and thread creation and control. Being able to spawn new process and threads of execution within processes allows multi-threaded programming utilizing possible hardware parallelism.
    • Synchronization primitives: counting semaphores, recursive and non-recursive mutexes, and condition variables. These allow controlled access to data, sequencing and synchronization of operations between multiple threads of control.
    • Interprocess message passing. Being able to send and receive messages between multiple threads of execution enables communicating arbitrary data in a flexible manner. For DTPF, packet-based (datagram-based) message queues which maintain ordering of messages and do not drop messages are desired.
    • Interprocess shared memory. Mapping memory between processes can reduce copying large amounts data between processes, reducing run time and dmands on message passing.
    •  Explicit dynamic linking. To support a plug-in architecture, dynamic linking of executable code from library files is needed.

  • What software will be used to handle platform specific interfaces: YARP, ACE, MUSCLE, SystemLayer? How are these interfaces presented to the framework implementors and application programmers?

Details:
  • YARP is not suitable for use in the core of DTPF as it does not fully support OSX at this time.
  • ACE provides a wide set of functionality for developing concurrent and networked applications. ACE supports OSX and other platforms (Linux, Windows) that may be targeted in the future. Further investigation into using ACE has cast doubt on its utility. The core ACE library itself is rather large, openly available documentation of the programming interface is incomplete, and some of the functionality desired for DTPF is platform dependent or requires conditionally included code using the C/C++ preprocessor #ifdef construct.
  • MUSCLE provides a level of platform independence but does not provide as much functionality as ACE. As discussed in the requirements background information, MUSCLE does provide a message class that is useful for DTPF. This class is a container for name/value pairs and supports operations to 'flatten' a message to an array of bytes.
  • The SystemLayer developed to support our earlier software projects (SoundStream, SenseStream) provides the needed functionality  and some degree of system independence, but has only been developed on BeOS and Linux. The most current SystemLayer has only been developed and tested under Linux. Porting the SystemLayer to OS X appears feasible with a small amount of effort on the order of one person-week.

Proposal:
  • ACE will not be used.
  • The SystemLayer will be ported to OS X and will be used to provide system abstraction and independence.
  • The muscle::Message class will be used as a container that can be converted to an array of bytes for transmission across IPC communication mechanisms (sockets) or storage to a file. Any components of MUSCLE used should be included with DTPF. This is possible due to the flexible licensing MUSCLE is distributed under and the relatively small footprint of the muscle::Message class and its dependencies.
  • Facade interfaces will be used to hide the framework implementation and API from direct references to components of MUSCLE. These facade interfaces will reduce the complexity of the presented API and decrease coupling to particular software packages. Reducing coupling in this manner helps reduce the risk of depending on one package, and allows for future optimizations for a specific platform.


IV.A.1
Issue: Management of operating system resources.

Details:
Using the SysV functionality on OS X appears to be the most direct route to a port of the SystemLayer message queues and shared memory. Managing the operating system level resources involved with these services requires some thought to avoid 'leaking' these system level resources. Since DTPF is intended to support development of additional software which may be going through a development process or otherwise have instabilities that result in crashing of a process, open resources need to be reclaimed properly. Not needing to explicitly close these resources on normal program shutdown it is also desireable.

Proposal:
The SystemLayer will be extended to support resource reclamation.
  • On launch a process will initialize the SystemLayer which will create and open a 'run-lock' file that will be unlink()'ed to be removed automatically by the OS upon termination of the process through normal or erroneous termination.
  • A shared memory segment will be created to contain record of the resources allocated by the process. This shared memory segment will be configured to remain present unless explicitly removed by the program on normal program shutdown.
  • An identifier for the shared memory segment will be written to a second file that is created so as to persist unless explicitly removed from disk.



IV.B: Issue:
  • How is synchronization of data communication from the start of a 'pipeline' of connected nodes to the end handled?

Details:
  • We plan to implement different processing modes, depending on timing requirements. This first phase of the framework will only directly support an off-line mode. A real-time mode will be included in a future stage of the framework.
  • In an off-line processing mode, the rate of processing is controlled by the throughput of the nodes involved, not by real-time data rates.
  • The framework needs to support feedback connections. If A is connected to B which is connected to C, it should be possible to make a connection from C to A. This is necessary to realize some of the sensory processing models envisioned.

Proposal:
  • In the off-line mode, transfer of buffers will be "pull" based. That is, a downstream node sends a request for the next buffer to its upstream connected node. The upstream node receives the request and sends the next buffer, when that buffer is ready. The downstream node will then receive that next buffer, and will be notified of receipt of that method through some kind of "buffer received" event method.
  • In the real-time situation, processing will be "push" based. An upstream node will send a buffer when the buffer is ready, to the downstream node. The downstream node will receive that buffer in a similar manner to the off-line case, except that the downstream node does not have to ask for the buffer. (Our initial implementation of real-time processing may be carried out in part by making the downstream node's request for the next buffer do nothing).



IV.C: Issue:
  • Modification rights to a buffer will be supported with the framework send buffer and receive buffer node methods. Nodes will gain access to a buffer through the framework. Reference counting of buffers will be used to help enforce this. Where is this handled? By nodes, buffer groups, the buffers themselves?

Details:

Proposal:



IV.D:
Issue:
  • How are 'broadcast' connections, in which one node sends the same data to multiple consumer nodes, handled?

Details:

Proposal:



IV.E: Issue:
  • Do plug-in nodes need to be loaded into a separate process? Should plug-ins be allowed to be loaded in the address space of the client application making the request to load?

Details:

Proposal:



IV.F:
Issue:
  • How exactly are specific formats handled in a manner that makes the core framework, specifically the roster, independent of specific format implementations. What are the ramifications of the solution to this? How can two format descriptions of the same type be considered to be compatible?

Details:

Proposal:
  • The formats are subclasses of parameter groups which hide the general hierarchy functionality of parameter groups.
  • This would allow generic UI specification of format attributes.
  • Compatibility between two specific format descriptions can be determined by examining allowed attribute values.


IV.G:
Issue:
  • How are client listeners handled? Does this impose requirements on the structure of client applications (i.e., requiring an event handling loop)?

Details:

Proposal:



IV.H:
Issue:
  • How is node event receiving and dispatching handled?

Details:
  • Need to allow for concurrent execution but not use too many threads.

Proposal:
  1. Nodes are controlled by events corresponding to the various actions that can be performed on a node.
  2. A framework provided event looper class handles running a thread which listens for event messages on a communication port.
  3. Each event looper has exactly one thread of execution. The event looper is responsible for starting and stopping that thread.
  4. Events are filtered as appropriate (some events may be targeted to the event looper) and dispatched by direct invocation of hook and slot methods on a node instance.
  5. A single event looper can dispatch events for multiple nodes in the same process address space. Events will indicate the target node to allow proper dispatching by an event looper handling more than one node. Nodes implementations themselves can start any number of internal worker threads as needed.
    Node and event loper multiplicity.
    Figure 2: Node and event looper multiplicity.

  6. Nodes in the unregistered nodes state can be added to an event looper provided the node and event looper instances are in the same process address space. After addition the node will be ready to be registered if the event looper thread is running, otherwise the node will not be able to be registered.
  7. An unregistered or stopped node can be removed from an event looper. After removal a stopped node will be unregistered.
  8. An event looper for an unregistered node can be created by the framework on behalf of the node implementation or other program code.
  9. An event looper has synchronization operations that allow code executing in other threads to safely use event looper and node methods.



Issue:

Details:

Proposal:



V. Design Details

Other details the reader will need to know that have not yet been mentioned will be added here.



Hosted on
SourceForge.net Logo

© 2005 Eric J. Mislivec, Last Modified: 12 July, 2005