Logo Search packages:      
Sourcecode: u++ version File versions

PThread.cc

//                              -*- Mode: C++ -*- 
// 
// uC++ Version 5.0.1, Copyright (C) Peter A. Buhr 2002
// 
// PThread.cc -- 
// 
// Author           : Peter A. Buhr
// Created On       : Thu Jan 17 17:06:03 2002
// Last Modified By : Peter A. Buhr
// Last Modified On : Thu Aug 26 15:33:02 2004
// Update Count     : 42
// 

#ifdef __U_CPLUSPLUS__
#include <uC++.h>
#define exit uExit
#endif

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>                                                           // prototype: rand
#include <limits.h>
#include <errno.h>


class MutexMem {
      pthread_mutex_t &mutex;
  public:
      MutexMem( pthread_mutex_t &mutex ) : mutex( mutex ) {
            pthread_mutex_lock( &mutex );
      }
      ~MutexMem() {
            pthread_mutex_unlock( &mutex );
      }
};

template <class ELEMTYPE> class BoundedBuffer {
      pthread_mutex_t mutex;
      int front, back, count;
      ELEMTYPE Elements[20];
      pthread_cond_t Full, Empty;                                       // waiting consumers & producers
  public:
      BoundedBuffer() {
            front = back = count = 0;
            pthread_mutex_init( &mutex, NULL );
            pthread_cond_init( &Full, NULL );
            pthread_cond_init( &Empty, NULL );
      }
      ~BoundedBuffer() {
            pthread_mutex_lock( &mutex );
            pthread_cond_destroy( &Empty );
            pthread_cond_destroy( &Full );
            pthread_mutex_destroy( &mutex );
      }
      int query() { return count; }

      void insert( ELEMTYPE elem ) {
            MutexMem lock( mutex );
            while ( count == 20 ) pthread_cond_wait( &Empty, &mutex ); // block producer
            Elements[back] = elem;
            back = ( back + 1 ) % 20;
            count += 1;
            pthread_cond_signal( &Full );                         // unblock consumer
      }
      ELEMTYPE remove() {
            MutexMem lock( mutex );
            while ( count == 0 ) pthread_cond_wait( &Full, &mutex ); // block consumer
            ELEMTYPE elem = Elements[front];
            front = ( front + 1 ) % 20;
            count -= 1;
            pthread_cond_signal( &Empty );                              // unblock producer
            return elem;
      }
};

void *producer( void *arg ) {
      BoundedBuffer<int> &buf = *(BoundedBuffer<int> *)arg;
      const int NoOfItems = rand() % 40;
      int item;

      for ( int i = 1; i <= NoOfItems; i += 1 ) {                 // produce a bunch of items
            item = rand() % 100 + 1;                                    // produce a random number
            printf( "Producer:0x%x, value:%d\n", pthread_self(), item );
            buf.insert( item );                                               // insert element into queue
      } // for
      printf( "Producer:0x%x is finished\n", pthread_self() );
      return (void *)1;
} // producer

void *consumer( void *arg ) {
      BoundedBuffer<int> &buf = *(BoundedBuffer<int> *)arg;
      int item;

      for ( ;; ) {                                                            // consume until a negative element appears
            item = buf.remove();                                        // remove from front of queue
            printf( "Consumer:0x%x, value:%d\n", pthread_self(), item );
        if ( item == -1 ) break;
      } // for
      printf( "Consumer:0x%x is finished\n", pthread_self() );
      return (void *)0;
} // consumer

void *Worker1( void *arg ) {
#ifdef __U_CPLUSPLUS__
      int stacksize = uThisTask().uStackSize();
      printf( "Worker1, stacksize:%d\n", stacksize );
#endif
      for ( int i = 0; i < 100000; i += 1 ) {}
      printf( "Worker1, ending\n" );
      return (void *)0;
} // Worker1

void *Worker2( void *arg ) {
    pthread_key_t key[PTHREAD_KEYS_MAX];
    unsigned int i;
    for ( i = 0; i < 60; i += 1 ) {
            if ( pthread_key_create( &key[i], NULL ) != 0 ) {
                  printf( "Create key\n" );
                  exit( -1 );
            } // if
            printf( "0x%d, i:%u key:%d\n", pthread_self(), i, key[i] );
    } // for
    for ( i = 0; i < 60; i += 1 ) {
            if ( pthread_setspecific( key[i], (const void *)i ) != 0 ) {
                  printf( "Set key\n" );
                  exit( -1 );
            } // if
    } // for
    for ( i = 0; i < 60; i += 1 ) {
            if ( (unsigned long int)pthread_getspecific( key[i] ) != i ) {
                  printf( "Get key\n" );
                  exit( -1 );
            } // if
    } // for
    pthread_exit( NULL );
      return (void *)0;
} // Worker2

#ifdef __U_CPLUSPLUS__
void uMain::main() {
#else
int main() {
#endif
      const int NoOfCons = 20, NoOfProds = 30;
      BoundedBuffer<int> buf;                                           // create a buffer monitor
      pthread_t cons[NoOfCons];                                         // pointer to an array of consumers
      pthread_t prods[NoOfProds];                                       // pointer to an array of producers

      // create/join and mutex/condition test

      printf( "create/join and mutex/condition test\n\n" );

      for ( int i = 0; i < NoOfCons; i += 1 ) {             // create consumers
            if ( pthread_create( &cons[i], NULL, consumer, &buf ) != 0 ) {
                  printf( "create thread failure, errno:%d\n", errno );
                  exit( -1 );
            } // if
      } // for
      for ( int i = 0; i < NoOfProds; i += 1 ) {                  //    create producers
            if ( pthread_create( &prods[i], NULL, producer, &buf ) != 0 ) {
                  printf( "create thread failure\n" );
                  exit( -1 );
            } // if
      } // for

      void *result;
      for ( int i = 0; i < NoOfProds; i += 1 ) {                  // wait for producers to end
            if ( pthread_join( prods[i], &result ) != 0 ) {
                  printf( "join thread failure\n" );
                  exit( -1 );
            } // if
            if ( result != (void *)1 ) {
                  printf( "bad return value\n" );
                  exit( -1 );
            } // if
            printf( "join prods[%d]:0x%u result:0x%p\n", i, prods[i], result );
      } // for

      for ( int i = 0; i < NoOfCons; i += 1 ) {             // terminate each consumer
            buf.insert( -1 );
      } // for

      for ( int i = 0; i < NoOfCons; i += 1 ) {             // wait for consumer to end
            if ( pthread_join( cons[i], &result ) != 0 ) {
                  printf( "join thread failure\n" );
                  exit( -1 );
            } // if
            if ( result != (void *)0 ) {
                  printf( "bad return value\n" );
                  exit( -1 );
            } // if
            printf( "join cons[%d]:0x%u result:0x%p\n", i, cons[i], result );
      } // for

      // thread attribute test

      printf( "\n\nthread attribute test\n\n" );

      pthread_attr_t attr;
      pthread_attr_init( &attr );
      pthread_attr_setstacksize( &attr, 64 * 1000 );
      pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED );
      size_t stacksize;
      pthread_attr_getstacksize( &attr, &stacksize );

      pthread_t worker1, worker2;

      if ( pthread_create( &worker1, &attr, Worker1, NULL ) != 0 ) {
            printf( "create thread failure\n" );
            exit( -1 );
      } // if

      pthread_attr_destroy( &attr );

      // thread specific data test

      printf( "\n\nthread specific data test\n\n" );

    if ( pthread_create( &worker1, NULL, Worker2, NULL ) != 0 ) {
            printf( "create thread failure\n" );
            exit( -1 );
      } // if
    if ( pthread_create( &worker2, NULL, Worker2, NULL ) != 0 ) {
            printf( "create thread failure\n" );
            exit( -1 );
      } // if
    if ( pthread_join( worker1, NULL ) != 0 ) {
            printf( "join thread failure\n" );
            exit( -1 );
      } // if
    if ( pthread_join( worker2, NULL ) != 0 ) {
            printf( "join thread failure\n" );
            exit( -1 );
      } // if

      printf( "successful completion\n" );
} // main


// Local Variables: //
// compile-command: "g++ -g PThread.cc -lpthread" //
// tab-width: 4 //
// End: //

Generated by  Doxygen 1.6.0   Back to index