// This may look like C code, but it is really -*- C++ -*-
// Interface C++ aux Thread POSIX  -   R. Ansari 02/2001
// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA

#ifndef ZTHREAD_SEEN
#define ZTHREAD_SEEN

#include "machdefs.h"
#include <pthread.h>
#include "pexceptions.h"


namespace SOPHYA {

typedef void (* ZThreadAction) (void *);
  
class ZThreadExc : public PException {
public:
  explicit ZThreadExc(const string& m, int id=0) : PException(m,id) {}
};

class ZThread {
public:
  explicit	ZThread(size_t stacksize=0);
  virtual	~ZThread();
  void		start();
  void		cancel();
  inline void   stop() { cancel(); }

  void          join();
  virtual void  run();

  inline void   setRC(int rc) { _rc = rc; }
  inline int    getRC(int rc) { return(_rc);
 }
  inline void	setAction(ZThreadAction act, void * usp=NULL)
       {  _act = act;  _usp = usp; }


  static inline void setCancelState(int st= PTHREAD_CANCEL_ENABLE) 
       { int ocs; pthread_setcancelstate(st, &ocs); }
  // PTHREAD_CANCEL_ENABLE  ou PTHREAD_CANCEL_DISABLE
  static inline void setCancelType(int ct= PTHREAD_CANCEL_DEFERRED) 
       { int oct; pthread_setcanceltype(ct, &oct); }
  // PTHREAD_CANCEL_DEFERRED  ou  PTHREAD_CANCEL_ASYNCHRONOUS


  // ---- Attribute variables ----
  pthread_t _thr;
  size_t _ssize;
  int _rc;
  bool _initok;

  ZThreadAction _act;
  void * _usp;
};


class ZMutex {
public:
  explicit	ZMutex();
  virtual	~ZMutex();
  inline void	lock()
    { pthread_mutex_lock(_mutx); } 
  inline void	unlock()
    { pthread_mutex_unlock(_mutx); } 
  inline void	wait()
    { pthread_cond_wait(_condv, _mutx); }
  inline void	signal()
  { pthread_cond_signal(_condv); }
  inline void	broadcast()
  { pthread_cond_broadcast(_condv); }

  // Attributes
  pthread_mutex_t * _mutx;
  pthread_cond_t * _condv;
};


class ZSync {
public:
  explicit inline  ZSync(ZMutex & mtx) {_mtx = &mtx; mtx.lock(); }
  inline	   ~ZSync() { _mtx->unlock(); }

private:
  ZMutex * _mtx;
  inline	ZSync() {_mtx = NULL; }

};

} // namespace SOPHYA

#endif
