// Interface C++ aux Thread POSIX  -   R. Ansari 02/2001
// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA

#include "zthread.h"
#include <stdlib.h>
#include <stdio.h>

#define CheckSt(st_, strg_)  if (st_ != 0)  perror(strg_); 

/*
extern "C" {
  void * zthr_run( void * xthr);
}
*/

static void * zthr_run(void * xthr)
{
  ZThread * thr = (ZThread *)xthr;
  thr->run();
  pthread_exit(NULL);
  return NULL;
}


/* ------ Classe ZThread  -------  */

ZThread::ZThread(size_t stacksize)
{
  _initok = false;
  _ssize = 0;
  _act = NULL;
  _usp = NULL;
  _rc = -99;
}

ZThread::~ZThread()
{
  // Que faut-il faire ?
}

void ZThread::start()
{
  if (_initok) throw ZThreadExc("ZThread::Start() - Already started thread !");
  int rc;
  pthread_attr_t tha;
  rc = pthread_attr_init(&tha);
  CheckSt(rc,"ZThread::start() - Pb creating tha attribute object");
  if (_ssize > 0) 
    rc = pthread_attr_setstacksize(&tha, _ssize);
  rc = pthread_create(&_thr, &tha, zthr_run, this);
  CheckSt(rc,"ZThread::start() - Pb creating the thread object");     
  _initok = true;
  setRC(rc);      
}


void ZThread::cancel()
{
  if (!_initok) throw ZThreadExc("ZThread::cancel() - thread not started !");
  int rc = pthread_cancel(_thr);
  CheckSt(rc,"ZThread::cancel() - Pb pthread_cancel() ");  
  setRC(-77);      
}


void ZThread::join()
{
  if (!_initok) throw ZThreadExc("ZThread::join() - thread not started !");
  void * x;
  int rc = pthread_join(_thr, &x);
  CheckSt(rc,"ZThread::Join() - Pb pthread_join() ");
  return;  
}

void ZThread::run()
{
  if (_act)  _act(_usp);
  setRC(0);      
  return;
}


/* ------ Classe ZMutex -------  */

ZMutex::ZMutex()
{
  _mutx = new pthread_mutex_t;
  _condv = new pthread_cond_t;
  int rc;
  rc = pthread_mutex_init(_mutx, NULL);
  CheckSt(rc,"ZMutex::ZMutex() Pb pthread_mutex_init");
  rc = pthread_cond_init(_condv, NULL);
  CheckSt(rc,"ZMutex::ZMutex() Pb pthread_cond_init");
}

ZMutex::~ZMutex()
{
  delete _mutx;
  delete _condv;
}

