Listing 1: Defines thread and mutex classes

///////////////////////////////////////////////////////////////////
// Copyright (c) Panos Kougiouris, Marco Framba 1997
///////////////////////////////////////////////////////////////////

#ifndef __KFTHREAD_HH_
#define __KFTHREAD_HH_

#include <kfBase.h>
#include <kfReferenceCount.h>

class CKFMTRunnableImplementation;
class CKFMTThreadImplementation;
class CKFMTMutexImplementation;
class CKFMTRWMutexImplementation;
class CKFMTConditionImplementation;
class ostream;

class CKFEXPORT CKFMT {
  public:

    enum {Infinity = 0};
    enum RetValue {Timeout, Ok, Error, AlreadyLocked};

    // This is the main object. Users should subclass it.
    // It can be used with both threads and the scheduler
    class CKFEXPORT CRunnable : public CKFReferenceCount {
      public:
        CRunnable(const char* a_name = "Unnamed");

        virtual void run() = 0;

        const char* get_name();

        RetValue wait_for_completion(unsigned msecs = Infinity);

      protected:
        friend class CKFMTThreadImplementation;
        CKFMTRunnableImplementation *m_impl;

        // Reference counted objects are not deleted their
        // reference count is decremented
        virtual ~CRunnable();
    };

    //-------------------------------------------------------------

    // A thread class. Threads are created to run runnable objects.
    // Threads should always be created on the heap because when
    // they exit the runtime deletes the object
    class CKFEXPORT CThread {
      public:
        // A stack size of 0 gives a defualt stack size depending
        // on the architecture. The thread is constructed in a
        // suspended state. The make_runnable() method should be
        // called to get the thread into a runnable state. The
        // Runnable will be decremenented when the thread is done.
        // The thread will delete itself when it is done.
        CThread(CRunnable*, int stack_size = 0);
        CThread(const CThread&);
        CThread& operator= (const CThread&);
        ~CThread();

        void make_runnable();
        unsigned long get_thread_id();

        // Abnormally terminates a different thread.
        // Should be avoided

        void exit(int code);

        // Related to the current thread
        static unsigned long current_id();
        static void current_exit(int code); // Recommended exit
    
      protected:

        CKFMTThreadImplementation *m_impl;

        friend class CKFMTThreadImplementation;
    };

     //--------------------------------------------------------

    class CKFEXPORT CMutex {
      public:
        CMutex(const char* name = "");
        ~CMutex();
        CMutex(const CMutex&);
        CMutex& operator= (const CMutex&);

        RetValue lock(); 
        RetValue try_lock();
        RetValue unlock();

    CKFBool am_owner();

        //private:
        
        CKFMTMutexImplementation *m_impl;

        friend class CCondition;
    private:
        
    };

    // Used to help acquire and hold a mutex lock ONLY while inside 
    // the C++ scope
    // 
    enum GrabAction
        {DoGrab, DoNotGrab, GrabOnlyIfCurrentThreadNotOwner};
    class CKFEXPORT CMutexGrabber {
      public:
        CMutexGrabber(CMutex& a_mut, GrabAction act = DoGrab);
        ~CMutexGrabber() {if (m_do_ungrab) m_mut->unlock();};
      private:
        CMutex*    m_mut;
        CKFBool m_do_ungrab; 
    };

    //--------------------------------------------------------
    // Read/Write lock
    //
    class CKFEXPORT CRWMutex {
      public:
        CRWMutex(const char* name = "");
        CRWMutex(const CRWMutex&);
        CRWMutex& operator= (const CRWMutex&);
        ~CRWMutex();

        void     rdlock();
        RetValue try_rdlock();

        void     wrlock();
        RetValue try_wrlock();

        void unlock();

      private:

        CKFMTRWMutexImplementation *m_impl;
    };

    //
    // Used to help acquire and hold a RWmutex lock ONLY while
    // inside the C++ scope
    // 
    class CKFEXPORT CRWMutexGrabber {
      public:
        CRWMutexGrabber
            (CRWMutex& a_mut,
             CKFBool a_iswrtr = CKFFalse,
             GrabAction act = DoGrab
             ) : m_mut(&a_mut)
               { if (act == DoGrab) {
                  a_iswrtr ? m_mut->wrlock() :  m_mut->rdlock() ;
                 }
               };
        ~CRWMutexGrabber() {m_mut->unlock();};
      private:
        CRWMutex *m_mut;
    };

    //-------------------------------------------------------------

    class CKFEXPORT CCondition {
      public:
        CCondition(const char* name = "");
        CCondition(const CCondition&);
        CCondition& operator= (const CCondition&);
        ~CCondition();

        RetValue wait(CMutex, unsigned msecs = Infinity);
        RetValue signal();
        RetValue broadcast();
      private:
        CKFMTConditionImplementation *m_impl;
    };
    
};
inline ostream& operator<<(ostream& a_str, CKFMT::CRunnable* a_run)
{
    return a_str << a_run->get_name();
}

#endif
//End of File