/* $Id: Thread.h,v 1.2 1999/11/01 19:15:46 v2kea318 Exp $

$Log: Thread.h,v $
 * Revision 1.2  1999/11/01  19:15:46  v2kea318
 * Added cancel() and os_cancel().
 *
 * Revision 1.1  1999/10/22  19:52:28  v2kea318
 * Initial revision
 *
***************************************************************************

Define an abstract interface to simple thread routines.

***************************************************************************/

#ifndef MLIBSPP_THREADPP_H
#define MLIBSPP_THREADPP_H

#ifdef _WIN32
#include <windows.h>
#else
#include "Pthread.h"
#endif

#include "pointer.h"
#include <stdexcept>
#include <string>

class Thread {
public:
  // define some type according to operating system
#ifdef _WIN32  // Windows, untested.
  typedef HANDLE thread_id_t;
  typedef DWORD thread_return_value;

#else // use POSIX.
  typedef pthread_t thread_id_t;
  typedef void* thread_return_value;
#endif
 
  // Define a type for a pointer to the initial routine.
  typedef thread_return_value (*ThreadInitialRoutine)(void*);

  // constructors.
  Thread();
protected:
  Thread(thread_id_t);
public:
  // destructor.
  virtual ~Thread();

  // start the thread.
  void start(ThreadInitialRoutine init, void* args);

  // kill the thread
  void kill(int ecode);

  // cancel the thread.
  void cancel();

  // get a descriptor for the current thread.
  static Pointer<Thread> self();

  // wait for a thread to complete and return the exit value.
  static thread_return_value join(const Thread&);

  // factory method, to create a new Thread object.
  static Pointer<Thread> create();

  // exceptions.
  class ThreadException : public runtime_error {
  public:
    ThreadException(const string& d) : runtime_error(d) {}
  };
  class StartThreadFailure : public ThreadException {
  public:
    StartThreadFailure();
  };

  // get the OS specific identifier
  thread_id_t ident() const { return id; }

protected:
  // do the OS specific operations.
  virtual thread_id_t os_start(ThreadInitialRoutine init, void* args) = 0;
  virtual void os_kill(int ecode) = 0;
  virtual thread_return_value os_join(const Thread&) = 0;
  virtual Pointer<Thread> os_self() = 0;
  virtual void os_cancel() = 0;

private:
  // data
  thread_id_t id;
};
  
#endif
