YANE-Framework Tutorial 1.1.0

Tutorial page of the Class yane::Utils::Semaphore

This demo shows the use of Semaphores. Semaphores are used if a resource is limited. In this example the semaphores are used to solve the produce consume problem, i.e. a thread produces resources and another thread requires an amount of resources. To be more specific, one thread produces between 1 and 4 resources and the other one consumes (if available) 10 resources.

Introduction

In this example we use an unusual way to work with semaphores (for the usual look at the semaphore documentation). One thread only produces resources, i.e. it releases resources into the semaphore with semaphore->release(amount) and the other one only consumes a constant amount of resources, i.e. it acquires resources from the semaphore with semaphore->acquire(10). The main function, or better the main thread, starts the threads and waits until they are finished.

Libraries

The first thing to do is to define the libraries which we require. These libraries form the head of our main program:

#include <iostream>
#include <cstdlib>

#include <yane/utils.h>

#include "pcthread.h"

Namespaces

Having defined the libraries which we are going to use, we now have to define the namespaces in which the classes of these libraries operate:

using namespace yane::Utils;
using namespace std;

Main Program

First we need to create a Debugmaster and a semphore the threads are using.

int main()
{
        ProduceConsumeThread * produce_thread, * consume_thread;

        yane::Utils::RTClock * clock = new yane::Utils::RTClock();
        yane::Utils::DebugMasterConsole * dm = new yane::Utils::DebugMasterConsole ( clock, 90 );
        yane::Utils::DebugClient * debug_client = dm->newClient ( "Main" );
        dm->setLevel ( 6 );

        yane::Utils::Semaphore * semaphore = new yane::Utils::Semaphore(0);

Now we create the threads and start them.

        produce_thread = new ProduceConsumeThread ( "Producethread", dm , semaphore, true);
        consume_thread = new ProduceConsumeThread ( "Consumethread", dm , semaphore, false);

        produce_thread->start();
        consume_thread->start();

The threads are working. The produce thread finishes after he has produce some units, therefore a wait() is enough. The consume thread on the other hand doesn't know how many resources the produce thread is producing, therefore we need an infinite loop. By setting _abort (via calling stop()) and releasing the units, the thread starts another loop and finishes after checking _abort. With wait() we wait until the thread is finished.

        produce_thread->wait();
        consume_thread->stop();
        semaphore->release(10);
        consume_thread->wait();

Once the threads are finished, we delete all allocated objects and the main program is finished.

        debug_client->sendDebugInfo ( "Threads finished.", "", 0, 0, 0, 3 );

        delete produce_thread;
        delete consume_thread;

        delete semaphore;

Tutorial page of the Class yane::Utils::Thread

The following we display the code of the produce thread. The produce thread releases resources and waits for some time (otherwise, the produce thread is finished before the consume thread is even started) and after some loops it terminates itself.

        debugMessage ( "Produce thread started", 6 );

        for ( ... )
{
                tmp = rand() % 3 + 1;
                stringstream ss;
                ss << tmp << " resources produced" ;
                _semaphore->release ( tmp );
                debugMessage ( ss.str(), 6 );
                usleep(100000);
}
        debugMessage ( "Produce thread finished", 6 );

Next, we discuss the code of the consume thread. The thread has an infinite loop which is stopped if stop() is called. In the loop we acquire resources.

        debugMessage ( "Consume thread started", 6 );

        while(!_abort)
{
                _semaphore->acquire(10);
                debugMessage ( "10 resources acquired!", 6 );
}

        debugMessage ( "Consume thread finished", 6 );
Author:
Michael Schamel <michael.schamel@uni-bayreuth.de>