Main Page | Namespace List | Class List | File List | Namespace Members | Class Members | File Members

dvthread Documentation

Author:
dvermeir@vub.ac.be
Download

Installation

Standard. See the INSTALL file in the top directory.

Description

This package provides two main classes: Dv::Thread::Thread, representing threads, and Dv::Thread::Monitor, to represent monitors. In addition, there is a trivial convenience class Dv::Thread::Lock that can be used to conveniently ensure exclusive access for member functions to *this (where *this is an instance of (a subclass of) Dv::Thread::Monitor.

Example program

The following class implements a buffer for concurrent access. Note the use of the SYNCHRONIZED macro which ensures that the get() and put() member functions have exclusive access to the Buffer object. Conditions are used to signal threads waiting to put or get items into (from) the buffer.
// $Id: buffer.h,v 1.6 2006/06/24 09:39:28 dvermeir Exp $
#ifndef DV_THREAD_BUFFER_H
#define DV_THREAD_BUFFER_H

#include <dvthread/lock.h>

#define TRACE std::cerr << pthread_self() << ":" << __FILE__ << "." << __LINE__ << std::endl;

// This class represents a buffer with synchronized access.
class Buffer: public Dv::Thread::Monitor {
  public:       
    Buffer() throw (std::runtime_error): Dv::Thread::Monitor("buffer",2), // &std::cerr),
      n_items_(0) {}
    // Add an item to a buffer.
    void put(int i) throw (std::runtime_error) {
      Dv::Thread::Lock lock(*this, "put", 0); //  &std::cerr); // Get exclusive access to *this.
      while (n_items_==MAX)
        if (!wait(OK_TO_PUT,2000)) // Wait at most 2 secs.
          throw std::runtime_error("Buffer::put() timed out");
      std::cerr << "put " << i << " ";
      data_[n_items_++] = i; // Actually put the item.
      signal(OK_TO_GET);
    }
  
     // Obtain and remove the last item in the buffer.
    int get() throw (std::runtime_error) {
      Dv::Thread::Lock lock(*this, "get"); // , &std::cerr); // Get exclusive access to *this.
      while (n_items_ == 0) {
        if (!wait(OK_TO_GET, 2000)) 
          throw std::runtime_error("Buffer::get() timed out");
      }
      int tmp = data_[--n_items_];
      std::cerr << "get " << tmp << " ";
      signal(OK_TO_PUT);
      return tmp;
    }

  private:
    // Buffer capacity.
    enum { MAX = 3 };
    // Names for conditions.
    enum { OK_TO_GET = 0, OK_TO_PUT = 1 }; /// conditions 
    // Number of items in the buffer.
    int n_items_;
    // Actual store for items.
    int data_[MAX];
};
#endif

The example below shows the implementation of a reader thread class for the above buffer. Each thread should implement a Thread::main() member function that describes the work to be done by the thread.

#ifndef DV_THREAD_READER_H
#define DV_THREAD_READER_H

#include <unistd.h>
#include <dvthread/thread.h>
#include "buffer.h"


// Reader thread class. A reader simply retrieves items from a buffer.
class Reader: public Dv::Thread::Thread {
  public:
    // Constructor; n is the number of items to retrieve.
    Reader(Buffer& buf, unsigned int n): Thread(), buffer_(buf), n_(n) {}
    // The function executed by this tread.
    virtual int main() {
      try {
        std::cerr << "reader main, id = " << id() << std::endl;
        for (unsigned int i=0;(i<n_);++i)
          buffer_.get();
      }
      catch (std::exception& e) {
        std::cerr << "reader exception: " << e.what() << std::endl;
        return 1;
      }
      return 0;
    }
    // Destructor. Wait for this thread to finish before we detroy it.
    virtual ~Reader() { std::cerr << "~Reader" << std::endl; } 
  private:
    // Buffer from where items will be retrieved.
    Buffer&     buffer_;
    // Number of items to retrieve.
    unsigned int  n_;
};
#endif

This example shows the implementation of a writer thread class. Each thread should implement a Thread::main() member function that describes the work to be done by the thread.

#ifndef DV_THREAD_WRITER_H
#define DV_THREAD_WRITER_H
// $Id: writer.h,v 1.6 2006/06/24 09:39:28 dvermeir Exp $
#include <dvthread/thread.h>
#include <unistd.h>
#include "buffer.h"

// A Thread class that writes 100 items to a buffer.
class Writer: public Dv::Thread::Thread {
  public:       
     // Constructor; n is the number of items to put.
    Writer(Buffer& buf, unsigned int n): Thread(), buffer_(buf), n_(n) {}
    // Main function of a Writer thread.
    int main() {
      std::cerr << "writer main, id = " << id() << std::endl;
      try {
        for (unsigned int i=0; (i<n_);++i)
          buffer_.put(i);
      }
      catch (std::exception& e) {
        std::cerr << e.what() << std::endl;
        return 1;
      }
      return 0;
    }
    // Destructor, join this thread first.
    virtual ~Writer() { std::cerr << "Writer::~Writer" << std::endl; }
  private:
     // Buffer to which items will be written.
    Buffer& buffer_;
    // Number of items to write.
    unsigned int n_;
};
#endif

The main program creates a Buffer object, a Reader and a Writer thread. Note that the writer wants to put more items than will be read. Consequently, it will throw an exception (from within Buffer::put()).

// $Id: test-thread.C,v 1.5 2006/06/24 09:39:28 dvermeir Exp $

#include <iostream>
#include "./buffer.h"
#include "./reader.h"
#include "./writer.h"

// Test thread program. The test consists of a reader and a writer
// thread that read/write items to a buffer.
int
main(int,char**) {
  try {
    // Dv::Thread::Thread::log = &std::cerr;
    Buffer buf; // buffer containing items
    Reader r(buf,10); // takes items from buffer
    Writer w(buf,15); // writes items to buffer
  
    r.start();
    std::cerr << "reader started.." << std::endl;
    w.start();
    std::cerr << "writer started.." << std::endl;
  
    r.join();
    if (r.status() != 0)
      throw std::runtime_error("reader has unexpected status");
    w.join();
    if (w.status() != 1)
      throw std::runtime_error("reader has unexpected status");
  }
  catch (std::exception& e) {
    std::cerr << e.what() << std::endl;
    return 1;
  }
return 0;
}

dvthread-0.5.0 [22 June, 2006]