One of the most common uses of threads in embedded systems is to serialize usage of shared resource such as data, I/O ports, sockets, or files. A typical implementation is to use a queue and a thread. Threads accessing the shared resource place requests or operations on the queue. A thread waits on the queue, dequeuing requests and performing the operations on the shared resource. Structurally, it looks something like this:

Usually it’s best to hide all of this complexity from the resource users. I usually place the thread, the queue and their related components in a single class. The resource user sees only one public function; queueRequest(Request&). This helps insure that users only access the resource through the access queue/thread. The name of the function reminds the user that the request may not be executed immediately. Now let’s look at an implementation in C++ using POSIX threads:
First the class declaration:
class SharedResource
{
public:
SharedReasouce(Resource& resource);
~SharedResource();
queueRequest(Request&);
private:
static void* accessThread(void* params);
Resource& _resource;
std::queue<request&> _requestQueue;
pthread_t _accessThreadId;
pthread_cond_t _queueSignal;
pthread_mutex_t _queueMutex; // Required to use pthread condition code
};
We pass a reference to the resource to the constructor. This way if we have several resources of the same type, we can create an object using this class for each of the resources.
The thread function must be static in order to use it with the POSIX create_thread function. Thread functions take a single parameter, a void pointer. We will use this pointer to pass the this pointer to the thread.
The queueSignal condition code is used to signal accessThread when a request has been placed on the queue. Pthreads requires that you use a mutex to signal a condition code and this is what queueMutex is used for.
Now let’s look at the constructor:
SharedResource::SharedResource(Resource& resource)
{
_resource = resource;
pthread_mutex_init(&_queueMutex, 0);
pthread_cond_init(&_queueSignal, 0);
pthread_create(&_accessThreadId, 0, SharedResource::accessThread, this);
}
The constructor makes a copy of the resource reference and creates the pthread condition code and mutex. Then the access thread is created. This starts execution of the function SharedResources::accessThread. A pointer of this instance of class SharedResource, the this pointer, is passed to the thread function as a parameter.
The queueRequest function is streight-forward. It simply places a request reference in the queue then signals the accessThread that a request is in the queue:
void SharedResource::queueRequest(Request& request)
{
_commandQueue.push(request);
pthread_cond_signal(&_queueSignal);
}
Finally let’s take a look at the thread itself:
void* SharedResource::accessThread(void* param)
{
// Convert the void* parameter back to a SharedResource reference
SharedResource& sharedResource = reinterpret_cast<SharedResource&>(param);
while(1)
{
// Wait on the request queue
pthread_mutex_lock(&sharedResource._queueMutex);
pthread_cond_wait(&sharedResource._queueSignal,
&sharedResource._queueMutex);
// Dequeue any requests and process them
while(sharedResource._requestQueue.size() > 0)
{
request = sharedResource._requestQueue.front();
sharedResource._requestQueue.pop();
// process the request on resource
}
}
}
A couple of things to note. In an actual program, you would check the return codes of each of the function calls in the constructor that allocate resources. If one of these functions fails you need to clean up any allocated resources and probably throw an exception.