// $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] |