next up previous contents index
Next: 3.6.2 Barriers mit Semaphoren Up: 3.6 Semaphore Previous: 3.6 Semaphore

3.6.1 Semaphoren Implementierung

  Es folgt ein Listing einer vollständigen Implementierung von Semaphoren mit Hilfe von Pthread Funktionen. Die Variablen der Klasse ``sema'' haben folgende Bedeutung.

Wenn sich signal darauf beschränkte, genau einen Pthread ``aufzuwecken'', währe das Statement IF s <= 0 THEN ... bereits ausreichend. So ist aber das Statement WHILE s <= 0 DO erforderlich um sicherzustellen, daß nicht ein anderer Thread den Wert von s in der Zwischenzeit verändert hat.

// semaphore class

#include <pthread.h>
#include "TYPES.h"
#include "ERROR.h"


//////////////////////////////////////////////////////////////////////////
// Interface class sema
//////////////////////////////////////////////////////////////////////////

class sema {
private:
    INTEGER init;
    INTEGER s;
    INTEGER del;
    pthread_mutex_t mux;
    pthread_cond_t pos;
public:
    sema();
    sema(INTEGER);
    ~sema();
    void P();
    void V();
};


//////////////////////////////////////////////////////////////////////////
//  Implementierung der Methoden class sem
//////////////////////////////////////////////////////////////////////////

sema::sema(INTEGER i = 0)
{
  if (pthread_mutex_init(&mux, pthread_mutexattr_default) < 0) {
    ERROR(fatal, "sema init: Cannot initialize sem.mux");
  }
  if (pthread_cond_init(&pos, pthread_condattr_default) < 0) {
    ERROR(fatal, "sema init: Cannot initialize sem.pos");
  }
  if (i >= 0) {
    s = i;
  } else {
    s = 0;
  }
  init = s;
  del = 0;
}

sema::~sema()
{
  if (s != init) { GWRITE( s-init ); 
    ERROR(fatal, "sema destruction: pending operations ");
  }
}

void
sema::P()
{
  if (pthread_mutex_lock(&mux) < 0) {
    ERROR(fatal, "P: Cannot lock sem.mux");
  }
  while (s <= 0) {
    del++;
    if (pthread_cond_wait(&pos, &mux) < 0) {
      ERROR(fatal, "P: Cannot wait on sem.pos");
    }
    del--;
  }
  s--;
  if (pthread_mutex_unlock(&mux) < 0) {
    ERROR(fatal, "seminit: Cannot unlock sem.mux");
  }
}

void
sema::V()
{
  if (pthread_mutex_lock(&mux) < 0) {
    ERROR(fatal, "P: Cannot lock sem.mux");
  }
  s++;
  if (del > 0) {
    if (pthread_cond_signal(&pos) < 0) {
      ERROR(fatal, "P: Cannot signal sem.pos"); 
    }
  }
  if (pthread_mutex_unlock(&mux) < 0) {
    ERROR(fatal, "seminit: Cannot unlock sem.mux");
  }
}



parallel@rz.uni-mannheim.de
Mon Okt 28 14:38:25 PST 1996