Real-Time Container Examples

What is a RT Container?

RT Containers are one of the three modelling concepts offered by the FW Profile. State Machines and Procedures (Activity Diagrams) allow the functional aspects of a software application to be modelled. RT Containers complement them by offering the means to capture the time-related behaviour of an application. The acronym "RT" stands for "Real-Time".

RT Containers provide a way to encapsulate the activation logic for a functional behaviour. A RT Container can be seen as a representation of a thread which controls the execution of some functional behaviour. The RT Container allows the conditions under which the thread is released to be specified.

The C1 Implementation represents a RT Container through a RT Container Descriptor (RTD). An RTD is a data structure which holds all the information required to describe a RT Container. It is defined as an instance of type struct FwRtDesc. Applications manipulate a RT Container by passing its RTD to the functions defined by the C1 Implementation. Thus, for instance, an application sends a notification to a RT Container through the following function call: FwRtNotify(rtDesc). Here, rtDesc is the pointer to the RTD of the RT Container to be notified.

RT Containers are built upon POSIX threads but they add logic around them to endow them with certain functional properties. Thus, for instance, the RT Container ensures that notifications are never lost or that, when a container is stopped, its finalization actions are executed.

Simple RT Container

The remainder of this page presents an example of how the functions provided by the C1 Implementation can be used to create, configure and use a RT Container. This example considers a very simple RT Container which, every time it receives a notification, writes a message to standard output. The full code for the example is available here.

RT Container Creation

A RT Container is created by creating its descriptor. A RT Container Descriptor (RTD) is a variable of type struct FwRtDesc. The container instance is therefore created as follows:

    // Create and initialize the RTD
    struct FwRtDesc rtDesc;

RT Container Configuration

After the RTD has been created, it must be configured. The next pseudo-code example illustrates the following configuration steps: (a) the internal data structures of the RTD are reset; (b) the functional behaviour encapsulated by the container is attached to the container; (c) the internal data structures of the RTD are initialized:

   // Reset the RT Container 
   FwRtReset(&rtDesc);

   // Attach functional behaviour to RT Container
   FwRtSetExecFuncBehaviour(&rtDesc,&UserFunctionalBehaviour);

   // Initialize the RT Container 
   FwRtInit(&rtDesc);

The variable UserFunctionalBehaviour is the function which implements the functional behaviour executed by the container when it is notified. In the case of this example, this function is defined as follows:

   FwRtOutcome_t UserFunctionalBehaviour(FwRtDesc_t rtDesc) {
          static int i = 1;
          printf("Activation Thread: Notification %i has been received!\n",i);
          i++;
          return 0;
   }

This function must conform to the prototype FwRtAction_t which is provided by the C1 Implementation.

In this example, only one user-defined function is associated to the RT Container. In a more realistic example, other functions might be associated to the RT Container representing, for instance, the initialization and finalization behaviour for the container; the behaviour which filters incoming notifications; the behaviour which sets up notification requests; etc. In all cases, however, the container behaviour must be provided by the user in functions conforming to the ::FwRtAction_t stereotype which are loaded into the container at configuration time using functions defined in FwRtConfig.h.

RT Container Notification

The following example shows a short commanding sequence for the example RT Container. In the pseudo-code, the container is sent a sequence of 10 notifications separated by a wait time of 10 ms. Note that, before being sent notifications, the container must be started.

  // Start the RT Container and send a few notifications to it 
  FwRtStart(&rtDesc);
  for (i=0; i<10; i++) {
         printf("Sending notification %i to container ...\n",i+1);
         nanosleep(&ten_ms,NULL);       // wait ten ms 
  }
  // Stop the RT Container 
  FwRtStopt(&rtDesc);

After the container has been stopped, it will no longer process notification requests. After being stopped, the container can be re-started.

RT Container Shutdown

When the container is no longer needed, it should be shut down. The Shutdown operation ensures that any memory which was allocated during the initialization of the POSIX objects used by the container is released. When the container is stopped, its Activation Thread terminates. This may take some time. Hence, before shutting down the container, the program should wait until the thread has terminated:

  // To ensure orderly shutdown: wait until container thread has terminated
  FwRtWaitForTermination(&rtDesc);

  // Shutdown the RT Container 
  FwRtShutdown(&rtDesc);

results matching ""

    No results matching ""