/*
 * ===========================
 * VDK Visual Development Kit
 * Version 0.6
 * Jan 1999
 * ===========================
 *
 * Copyright (C) 1999, Salmaso Raffaele
 * Developed by Salmaso Raffaele <r.salmaso@flashnet.it>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library 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 VDKTHREAD_H
#define VDKTHREAD_H

#include <pthread.h>

enum VDKMutexEnum {
    VDKMUTEX_OK = 0,
    VDKMUTEX_ERROR
};
/*!
  VDHThread states
 */
enum VDKThreadEnum {
    VDKTHREAD_IDLE = 1,
    VDKTHREAD_RUNNING,
    VDKTHREAD_STOPPED,
    VDKTHREAD_EXITED,
    VDKTHREAD_CANNOT_CREATE,
    VDKTHREAD_IS_YET_RUNNING
};

class VDKMutex {
private:
    pthread_mutex_t mutex;
public:
    VDKMutex ();
    ~VDKMutex ();
    VDKMutexEnum Wait (long time = 0);
    VDKMutexEnum Release ();
    VDKMutexEnum Lock ();
};

/*!
  \class VDKThread
  \brief 
  This class provides a simple thread implementation Actually is supported only POSIX THREAD.
  
  It is possible to use a VDKThread in two way:
  \par via subclassing: if you derive a new class from VDKThread, you have to override the
  virtual method "virtual void Execute ();" to do what you want

  \code
  class NewClass : public VDKThread {
  protected:
    void Execute () {
      // my code
    }
  public:
    NewClass ();
    ~NewsClass ();
  }
  //...
  NewClass thread;
  thread.Start();
  \endcode

  \par passing a pointer to function when calling "Start ( (void *) func);"

  \code
  void * func () {}
  ...
  VDKThread thread;
  thread.Start ((void *) func);
  \endcode
 */
class VDKThread {
protected:
    pthread_t id;
    /*!
      Exit from the thread
     */
    void Exit (void * status = 0);
    static void * EntryPoint (void * arg);
    virtual void Execute ();
public:
    VDKThread ();
    virtual ~VDKThread ();
    /*!
      Start the thread.
     */
    VDKThreadEnum Start (void * = NULL);
    /*!
      Stops executing thread (command from other threads).
     */
    VDKThreadEnum Stop ();
    /*!
      Wait until the thread is terminated (it is used from other threads).
     */
    void * Wait ();
    /*!
      Store thread status.
     */
    VDKThreadEnum state;
    /*!
      Return the thread ID.
     */
    unsigned int GetID () {return (unsigned long) id;};
};

#endif
