// CS 509 - Advanced Programming II
// Spring 2002
//
// Thread iterator example.

#include <algorithm>
#include <iterator>
#include <vector>
#include <iostream>
#include <pthread.h>
#include <errno.h>
#include <cassert>


class thread_iterator 

  : public std::iterator <
      std::input_iterator_tag,	// iterator_category
      pthread_t,		// value_type
      std::ptrdiff_t,		// difference_type
      pthread_t *,		// pointer
      pthread_t & > {		// reference

  public:

    thread_iterator(unsigned i, void * (* f)(void *)) 
      : cnt(i), tmain(f), tid(0) {
      assert(f);
      }


    thread_iterator() 
      : cnt(0), tmain(0), tid(0) {
      }


    thread_iterator(const thread_iterator & ti) 
      : cnt(ti.cnt), tmain(ti.tmain), tid(ti.tid) {
      }


    pthread_t operator * () {
      if (tid == 0)
	ptc(tid, cnt);
      return tid;
      }


    thread_iterator operator ++ () {
      ptc(tid, cnt);
      return *this;
      }


    thread_iterator operator ++ (int) {
      thread_iterator old(*this);
      ptc(tid, cnt);
      return old;
      }


    bool operator == (const thread_iterator & ti) const {
      return cnt == ti.cnt;
      }


    bool operator != (const thread_iterator & ti) const {
      return not this->operator == (ti);
      }


  private:

    void ptc(pthread_t & id, unsigned & arg) { 
      if (arg > 0) {
	errno = pthread_create(
	  &id, NULL, tmain, reinterpret_cast<void *>(arg--));
	if (errno) {
	  perror("pthread_create() failed");
	  exit(1);
	  }
	}
      }

    unsigned cnt;
    void * (* tmain)(void *);
    pthread_t tid;
  };


static void
join_waiter(pthread_t tid) {
  if (pthread_join(tid, NULL)) {
    perror("pthread_join() failed");
    exit(1);
    }
  }


static void *
f(void * arg) { 
  std::cout << "thread " << reinterpret_cast<unsigned>(arg) << " is alive.\n";
  return 0;
  }


int main() {
  const unsigned max_threads = 10;
  std::vector<pthread_t> tids;

  std::copy(thread_iterator(max_threads, f),
	    thread_iterator(),
	    std::back_inserter(tids));
  std::for_each(tids.begin(), tids.end(), join_waiter);
  }


// g++ -o ti -ansi -pedantic thread-iterator.cc -lpthread

// $Log: thread-iterator.cc,v $
// Revision 1.2  2004/03/05 18:04:09  rclayton
// Factor common code into ptc().
//
// Revision 1.1  2004/03/05 03:55:54  rclayton
// Initial revision
//


syntax highlighted by Code2HTML, v. 0.9