Notes on using RTPointer

Category |  Purpose |  Intended Audience |  Applicable to |  Description |  Limitations |  See also


Category:

Top

C++


Purpose:

Top

To clarify RTPointer usage


Intended Audience:

Top

ObjecTime Developer users


Applicable to:

Top

All Versions


Description:

Top

A common design mistake is to treat RTPointer as a pointer.

RTPointer is a class, not a pointer or an address. It is a subclass of RTByteBlock.

Definition of RTPointer

For a definition of RTPointer see:

Because RTPointer is a class, the following two constructs are invalid:

RTPointer ptrWrapper = &someData;           //Wrong

RTPointer ptrWrapper = (RTPointer)&someData //Wrong*
//This is the old c-struct cast form. It is bad form
//and may not work with all compilers. See below for
//the correct, less ambiguous form.

An instance of the RTPointer class is an object which provides a wrapper around the address of some data. The RTPointer constructor takes a pointer as an arguement.

The correct usage of RTPointer is:

  RTPointer ptrWrapper = RTPointer(&someData);//Correct

There is a POINTER_OF(type) macro, (the definition is missing from the current documentation set). It looks like:

  #define POINTER_OF( type ) (type *)(void *)*(RTPointer *)

The ObjecTime recommended technique for retrieving a pointer from an RTPointer is:

  MyData* myDataPtr = POINTER_OF(ptrWrapper);//Correct

This is equivalent to, but less error prone than, using the RTPointer void* interface:

  MyData* myDataPtr = (MyData *) (void *) ptrWraper;

ObjecTime recommends that you do not take advantage of the RTPointer instance variable "Contents" which holds the pointer. For example, although the following construct will work:

  MyData* myDataPtr = (MyData *) ptrWrapper.Contents;

"Contents" is not part of the published interface and could change in a future ObjecTime release.

Sending Pointers in Messages

When sending an RTPointer object in a message, ObjecTime recommends that you use the provided SEND_PTR and RECEIVE_PTR macros (see pg. 26 of the ObjecTime4.3 C++ User Guide, or pg. 278 of the ObjecTime5.0 C++ User Guide).

By using these macros you will ensure compatability between the SimulationRTS and the TargetRTS and thereby avoid transition problems.

Here is an example of using the SEND_PTR macro:

  MyStruct *myPtr = ...;
  outPort.send( aSignal, SEND_PTR( myPtr ) );

and here is an example of using the RECEIVE_PTR macro:

  MyStruct *strptr = RECEIVE_PTR( MyStruct );

Sending Functions Pointers

Sending pointers to functions is also relatively straightforward. Given a global function:

  int myFnc(char*);

to send a function pointer using RTPointer, use:

  aPort.send(aSignal, SEND_PTR((void *) &myFnc) );

On the receiving side, to access the function, use:

  int (*foo) (char *) = (int (*) (char *)) RECEIVE_PTR(void);

The function could then be called with:

  (*foo)(&aCharacter);

This techique will not work for member functions which need to access member data.For an example of sending member function pointers, see page 186-187 of the ObjecTime5.0 C++ guide.

Care must be exercised when sending function pointers. Both the sender and the receiver must share the same address space. When sending function pointers across thread boundaries, like with access to global data, static member data, etc., you may need mechanisms to safely protect shared memory.

Sending Pointers to Local Data

Actor transitions have run-to-completion semantics. Local variables will go out of scope at transition completion. If you send a pointer of a local variable, it will be out of scope by the time the receiver gets it (i.e., the pointer will be invalid!). There are two possible exceptions to this rule:

  1. When the sender's thread is of lower priority than the receiver's thread
  2. When an invoke is used.

Keep in mind that by taking advantage of either of these exceptions your application will be less robust. It will likely be broken by future application modifications or ObjecTime releases.

Sending a pointer of a locally scoped variable is never recommended.

Important Notes:

When using sharing memory (i.e., sending pointers) extra attention is required to avoid introducing difficult to track bugs. Here are some things to consider:

  1. If an actor sends a pointer to an actor on another thread you are responsible for protecting from being accessed while it is being modified.
  2. If an actor sends a pointer outside its memory space, the receiver will not be able to use it to reference an object in its local memory space.
  3. If there are multiple pointers to the same memory location (e.g., more than one actor has a pointer to the same memory location), you need to ensure that the memory is deleted (returned to the heap), that it is deleted only once, and that once deleted, no further attempt is made to access it.

In practice it is safer to only send pointers to: extended state variables; global data; or memory allocated off the heap. Be aware that by sending pointers you are coupling the implementation of one part of the system to another part of the system. This coupling, is architecturally significant, but will not be visible in the structure of your system. It is a likely source of bugs and is potentially the beginning of architectural "erosion".

Consider other strategies for optimizing performance such as reallocating actor responsibilities so that only one actor requires the data.


Limitations:

Top

None


See also:

Top

ObjecTime C++ guide


 

Copyright © 1999, ObjecTime Limited.