Protothreads : Removing the State from State machine

Symbian's introductory training covers Active Objects. Active Objects are a Symbian specific method of providing co-operative multitasking. During the introduction to Active Objects we are all told about how inefficient and bloated multi threaded applications can be. Each thread requires heap and stack space, it requires kernel resources to provide for the context switching, and time slicing. All of this is an overhead on a device with limited resources. Instead Symbian provide Active Objects. We can have many Active Objects within a single process all waiting on different events. This means that we do not need as many threads, and hence we consume less resources.

To make good use of an Active Object most developers produce a state machine. With a given Active Object a number of differing states may be defined. For instance consider the following requirement:
Request signal strength, then display it on the screen. Wait for a second before requesting the signal strength again, continue endlessly.

Typically we'd write a state machine within the CActive child class. We would maintain this state and within our RunL we would use a large switch statement to jump to the correct state. While this method of tackling the problem works it does result in a lot of code. Additionally code maintenance becomes more of a chore – generally requirements change and extra states are added, over time reading the state machine becomes a complex task of tracing through the code trying to spot where the state variable is changed.

The code for such a task could like like this:
void CMyClass::RunL()
   {
   switch(iState)
       {
       case EGetSignalStrength:
       iTelephony->GetSignalStrength(iStatus, iSignalStrengthPckg);
       SetActive();
       iState = EWaitForTimer;
       break;
      
       case EWaitForTimer:
       iObserver.Tick(iSignalStrength.iSignalStrength);
       iTimer.After(iStatus, 100000);
       SetActive();
       iState = EGetSignalStrength;
       break;
       };
   }

I recently discovered a really excellent paper on Protothreads here [1]. This paper describes how Protothreads can simplify such code, by removing the need to maintain the state information. Instead the Protothread structure described in the paper allows the developer to write code which more closely matches their original intention.  Protothreads provide a stack-less light weight thread-like structure. It allows a developer to create code which looks and acts as if it's thread, although with a much reduced overhead.

As I read the paper I realised that Protothreads were similar in aim to Symbian's Active Object architecture. Both structures aim to deal with waiting for events, reducing the footprint of any solution by removing multiple threads and enabling a single thread to wait for more than one event at a time. In Symbian waiting for more than one event at a time is accomplished by having multiple CActive classes all waiting for events. With the Protothread solution it would have more than one Protothread, each one waiting for an event to complete. From what I've seen it appears as if the Protothread function is repeatedly called, each time the Protothread checks to see if the event it's waiting on has completed. Symbian's solution is slightly more elegant, when you invoke an asynchronous function the CActive::RunL function will only ever be called again when the event you've requested has arrived.

If only there was some way of combining both solutions.  There is a stock C implementation of Protothreads available [2], however because of the differing nature of handling events it would not work with the Symbian CActive structure. Indeed the stock C implementation had it's draw backs too, one of which is that it was impossible to use a switch statement within the Protothread.

So I spent a few days looking at how Protothreads work, and set about producing a version that would work with an Active Object. I am pleased to announce that my investigation has born fruit. I present my proof of concept implementation of a Symbian Protothread. The code for the state machine presented above can now be expressed in the following format:

void CPtTimer::ProtoRunL()
   {
   PROTO_THREAD_START;
   while (1) // a forever loop! in a RunL!!
       {
       PROTO_WAIT( A, iTelephony->GetSignalStrength(iStatus, iSignalStrengthPckg) );      
       iObserver.Tick(iSignalStrength.iSignalStrength);
       PROTO_WAIT( B, iTimer.After(iStatus, 100000) );
       }
   PROTO_THREAD_STOP;
   }

I've attached the necessary header files with the posting. Please feel free to download this code and use it within your own projects. It's published with a BSD like license.

Here is a modified S60 HelloWorld application which provides the working frame work for this example ( HelloWorldBasic.Zip ).

And here is a zip file just containing the necessary header files to create your own Protothread ( protothread_only.zip ).

References

[1] Protothreads: Simplifying Event-Driven Programming of Memory-Constrained Embedded Systems, by Adam Dunkels. Oliver Schmidt, Thiemo Voigt, Muneeb Ali :  http://www.sics.se/~adam/dunkels06protothreads.pdf
[2] Protothread implementation (Stock C) : http://www.sics.se/~adam/pt/download.html
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s