barrier_increment.cc

Example # 14 - Barrier.
Test of barrier.
//
// $Id: barrier_increment.cc,v 1.5 2003/10/30 15:05:12 cholm Exp $ 
//  
//  Test of threads - C %example ex14.c
//  Copyright (C) 2002 Christian Holm Christensen <cholm@nbi.dk> 
//
//  This library is free software; you can redistribute it and/or 
//  modify it under the terms of the GNU Lesser General Public License 
//  as published by the Free Software Foundation; either version 2.1 
//  of the License, or (at your option) any later version. 
//
//  This library is distributed in the hope that it will be useful, 
//  but WITHOUT ANY WARRANTY; without even the implied warranty of 
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
//  Lesser General Public License for more details. 
// 
//  You should have received a copy of the GNU Lesser General Public 
//  License along with this library; if not, write to the Free 
//  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
//  02111-1307 USA 
//
#ifndef OPTION_HH
#include "option.hh"
#endif
#ifndef THREADMM_thread
#include <threadmm/thread.hh>
#endif
#ifndef THREADMM_barrier
#include <threadmm/barrier.hh>
#endif
#ifndef THREADMM_mutex
#include <threadmm/mutex.hh>
#endif
#ifndef __VECTOR__
#include <vector>
#endif
#ifndef __FUNCTIONAL__
#include <functional>
#endif
#ifndef __ALGORITHM__
#include <algorithm>
#endif
#ifndef __TYPEINFO__
#include <typeinfo>
#endif

using namespace std;

template <typename T> 
struct reset : public unary_function<T, void> 
{
  void operator()(T& x) { x = 0; }
};

template <typename T> 
struct print : public unary_function<T, void> 
{
  void operator()(T x) { cout << setw(2) << x << " "; }
};
       
namespace example 
{
  class meeting : public threadmm::thread
  {
  public:
    static threadmm::barrier** _barrier;
    static threadmm::mutex _lock;
    static int _iterations;
    static int _num;
    static vector<int> _counters;
    static vector<int> _serial;
    int _id;
  public:
    meeting(int id) : _id(id) {}
    void* operator()()  {
      int ret = 0;
      for (int i = 0; i < _iterations; i++) {
  if (_id == 0) {
    for_each(_counters.begin(), _counters.end(), reset<int>());
    for_each(_serial.begin(), _serial.end(), reset<int>());
  }
  
  // Wait at the last barrier. 
  _barrier[_num - 1]->wait();

  for (int j = _id; j < _num; j++) {
    _lock.lock();
    _counters[j]++;
    _lock.unlock();
    
    // wait at this barrier - wait for the rest. 
    bool flag = _barrier[j]->wait();

    if (_id == 0 && _counters[j] != j + 1) {
      cerr << "Barriers in round " << j 
     << " released, but count is " << _counters[j] << endl;
      ret = 1;
    }
    
    if (flag) {
      _lock.lock();
      _serial[j]++;
      _lock.unlock();
    }
  
    // and wait again. 
    _barrier[j]->wait();

    
    if (_id == 0) {
      cout << "After try " << j << " in iteration " << i << endl
     << " Counters: " << flush;
      for_each(_counters.begin(), _counters.end(), print<int>());
      cout << endl << " Serials:  " << flush;
      for_each(_serial.begin(), _serial.end(), print<int>());
      cout << endl;
      if (_serial[j] != 1) {
        cerr << "Not exactly one serial thread in round " << j << endl;
        ret = 1;
      }
    }
  } // _num
      } // _iterations 
      return reinterpret_cast<void*>(ret);
    }
  };
  threadmm::barrier** meeting::_barrier    = 0;
  threadmm::mutex     meeting::_lock;
  int               meeting::_iterations = 0;
  int               meeting::_num        = 0;
  vector<int>       meeting::_counters;
  vector<int>       meeting::_serial;
  

  class barrier_increment 
  {
  public:
    barrier_increment() {}
    int run() {
      ios::sync_with_stdio(true);
      cout.setf(ios::unitbuf);
      cerr.setf(ios::unitbuf);

      meeting::_iterations = 5;
      meeting::_num        = 5;
      meeting::_counters.resize(meeting::_num);
      meeting::_serial.resize(meeting::_num);
      try {
  meeting::_barrier  = new threadmm::barrier * [meeting::_num];
  for (int i = 0; i < meeting::_num; i++) 
    meeting::_barrier[i] = new threadmm::barrier(i+1);
  
  meeting** threads = new meeting * [meeting::_num];
  for (int i = 0; i < meeting::_num; i++) {
    threads[i] = new meeting(i);
    threads[i]->run();
  }
  
  for (int i = 0; i < meeting::_num; i++) 
    threads[i]->join();
      }
      catch(exception& e) {
  cerr << e.what() << endl;
  return 1;
      }
      cout << "Ok" << endl;
      return 0;
    }
  };
}

//_______________________________________________________________________
int main(int argc, char** argv)
{
  if (!example::options(argc, argv)) return 0;

  example::barrier_increment exa;
  return exa.run();
}

//_______________________________________________________________________
// 
// EOF
//



Top of page
Last update Tue Nov 9 12:40:50 2004
Christian Holm
Created by DoxyGen 1.3.9.1