// Revision: 29 1.14.1.11 source/core/base/ingthrd.hpp, oss, ioc.v400, 001006  











#ifndef _INGTHRD_
#define _INGTHRD_
/*----------------------------------------------------------------------------*/
/* FILE NAME: ingthrd.hpp                                                     */
/*                                                                            */
/* DESCRIPTION:                                                               */
/*   Declaration of the classes:                                              */
/*     INonGUIThread                                                          */
/*     INonGUIThread::Cursor                                                  */
/*     IThreadFn                                                              */
/*     IThreadMemberFn                                                        */
/*     ICurrentNonGUIThread                                                   */
/*                                                                            */
/* COPYRIGHT:                                                                 */
/*   IBM Open Class Library                                                   */
/*   Licensed Materials - Property of IBM                                     */
/*                                                                            */
/*   5645-001                                                                 */
/*   (C) Copyright IBM Corporation 1992, 1997                                 */
/*                                                                            */
/*----------------------------------------------------------------------------*/


//         INonGUIThread is not supported in MVS SOM Environment


#ifdef IC_POSIX
extern "C" 
{
#include <pthread.h>
}
#endif

#include <ibhandle.hpp>
#include <ireslock.hpp>
#include <irefcnt.hpp>
#include <ingapp.hpp>

#if __IBMCPP__ >= 400
#pragma namemangling(compat)
#endif

struct tib_s;
class ICurrentNonGUIThread;
class ICurrentNonGUIThreadData;
class IStartedThread;
class IThreadCursorData;

#pragma enum(4)
#pragma pack(push,4)

class IC_EXPORTB IThreadFn {
public:
/*------------------------------- Constructors -------------------------------*/
    IThreadFn();
    virtual ~IThreadFn();

/*------------------------------- Run Function -------------------------------*/
    virtual void run() = 0;

private:
/*------------------------------ Hidden Members ------------------------------*/
    IThreadFn(const IThreadFn& function);
    IThreadFn &operator=(const IThreadFn& function);
}; // class IThreadFn


template < class T >
class IC_EXPORTB IThreadMemberFn : public IThreadFn 
{
    typedef IThreadFn Inherited;
public:
/*------------------------------- Constructors -------------------------------*/
    IThreadMemberFn(T &obj, void (T :: *mem)());
    virtual ~IThreadMemberFn();

/*------------------------------- Run Function -------------------------------*/
    virtual void run() {
        (object.*member)();
    }

private:
/*------------------------------ Hidden Members ------------------------------*/
    IThreadMemberFn(const IThreadMemberFn<T>& threadFunction);
    IThreadMemberFn<T> &operator=(const IThreadMemberFn<T>& threadFunction);
    
/*--------------------------------- Private ----------------------------------*/
    T &object;
    void (T::*member)();
}; // IThreadMemberFn


class IC_EXPORTB INonGUIThread {
public:
    
/*----------------------------------- Enums ----------------------------------*/

//
//  Note that these are purposefully very high numbers so that they can
//  be used (under OS/2 where the old API is still available) without
//  conflict with the 0..31 values that the old API supports.
//
    enum EThreadPriority
    {
        idle              = 1000,
        belowNormal       = 1001,
        normal            = 1002,
        aboveNormal       = 1003,
        timeCritical      = 1004,
        
        minPriority       = 1000,
        maxPriority       = 1004
    };

/*------------------------------ Function Types ------------------------------*/
    typedef void (_Optlink* OptlinkFnPtr) (void*);
    typedef void (_System*  SystemFnPtr) (unsigned long);
    
/*------------------------------- Constructors -------------------------------*/
    INonGUIThread();
    INonGUIThread(const INonGUIThread& thread);






#if (defined(IC_POSIX) || defined(IC_PM))
    INonGUIThread(const IThreadId&     threadID,
                  const IThreadHandle& threadHandle = IThreadHandle());
#endif

    INonGUIThread(IThreadFn *);
    INonGUIThread(OptlinkFnPtr function, void *functionArgument);
    INonGUIThread(SystemFnPtr function, unsigned long functionArgument);

    virtual ~INonGUIThread();

/*---------------------- Starting and Stopping Threads -----------------------*/
    virtual void start(IThreadFn *);
    virtual void start(OptlinkFnPtr function, void *functionArgument);
    virtual void start(SystemFnPtr function, unsigned long  functionArgument);
    virtual void stop();

#ifndef IC_POSIX_FLAGNOP
    virtual void suspend();
    virtual void resume();
#endif

/* ---------------------- Portable Priority Methods --------------------------*/
    virtual INonGUIThread::EThreadPriority threadPriority() const;
    virtual INonGUIThread& setThreadPriority(
        const INonGUIThread::EThreadPriority newPriority);


/* ------------------- Deprecated Priority Methods ---------------------------
 * These are only supported on OS/2 now because they are non-portable. They
 * are left available under OS/2 to avoid breaking old OS/2 client code.
   ------------------- Deprecated Priority Methods ---------------------------*/

    virtual unsigned priorityLevel() const;
    virtual INonGUIApplication::PriorityClass priorityClass() const;
    virtual INonGUIThread& setPriority(
        INonGUIApplication::PriorityClass priority, unsigned level);    
    virtual INonGUIThread& adjustPriority(int delta);

//
//  Helper to convert from new priority to old for OS/2, or just returns
//  current value if already in old form. This saves lots of grunt work
//  internally.
//
    static int convertedPriority(
        const int toConvert, INonGUIApplication::PriorityClass& classToSet);



/** @group Thread Information */
    static ICurrentNonGUIThread&    current();
    virtual IThreadId               id() const;
    static IThreadId                currentId();
    virtual IThreadHandle           handle() const;
    static IThreadHandle            currentHandle();
    IString                         variable(const IString& key) const;
    INonGUIThread&                  setVariable(const IString& key,
                                                const IString& value);
    virtual bool                    isStarted() const;
    unsigned long                   exitCode() const;
    

/*-------------------------------- Diagnostics -------------------------------*/
    virtual IString asString() const;
    virtual IString asDebugInfo() const;

/*-------------------------------- Stack Size --------------------------------*/
    virtual unsigned long stackSize() const;
    virtual INonGUIThread& setStackSize(unsigned long size);
    static unsigned long defaultStackSize();
    static void setDefaultStackSize(unsigned long size);

    class IC_EXPORTB Cursor
    {
    public:
        /*------------------------ Constructors -------------------------------*/
        Cursor(bool allThreads = true);
        virtual ~Cursor();

        /*---------------------- Thread Iteration -----------------------------*/
        virtual bool setToFirst();
        virtual bool setToNext();
        virtual bool isValid() const;

        virtual void invalidate();

        IThreadId threadId() const;

    private:
        /*-------------------------- Private ----------------------------------*/
        friend class IStartedThread;
        friend class IWindow;

        bool all;
        bool iteratedAll;
        bool advance();
        unsigned cursor;
        unsigned created;
        static unsigned timeStamp;
        IThreadCursorData* fCursorData;
    };


protected:
/*------------------------------ Implementation ------------------------------*/
    virtual IStartedThread* startedThread() const;
    static IStartedThread* newStartedThread();
    
/*------------------------------- Constructors -------------------------------*/
    INonGUIThread& operator=(const INonGUIThread& thread);

private:
/*--------------------------------- Private ----------------------------------*/
    friend class ICurrentNonGUIThread;
    friend class IWindow;
   
    IStartedThread* prepareToStart(IThreadFn *);    
    void threadStarted(IStartedThread* thread, int rc, IThreadId threadId);
    
    IStartedThread *thread;    
    static unsigned long dfltStackSize;
    
#ifdef IC_POSIX
    static bool initInProgress;
#endif    
}; // INonGUIThread

/**
 * Represents the current thread
 *
 */
class IC_EXPORTB ICurrentNonGUIThread : public INonGUIThread
{
    typedef INonGUIThread Inherited;
public:
    /** @group Constructors */
                                      ICurrentNonGUIThread();                                  
    virtual                           ~ICurrentNonGUIThread();
    
    /** @group Current Thread Support */
#ifndef IC_POSIXWIN_FLAGNOP
    virtual unsigned long            remainingStack() const;
#endif

    virtual ICurrentNonGUIThread&    sleep(unsigned long milliseconds);
    virtual ICurrentNonGUIThread&    waitFor(const INonGUIThread& anotherThread);
    virtual ICurrentNonGUIThread&    waitFor(const INonGUIThread& anotherThread,
                                             long timeout);
    virtual ICurrentNonGUIThread&    waitFor(const INonGUIThread& anotherThread,
                                             long timeout, bool *timedOut);
    virtual ICurrentNonGUIThread&    waitForAllThreads(long timeout = -1,
                                                       bool *timedOut = 0);
    virtual IThreadId                waitForAnyThread(long timeout = -1);

    virtual void                     exit(unsigned long returnCode);

    /** @group Current Thread Information */
    virtual IThreadId                id() const;
    virtual IThreadHandle            handle() const;

    /** @group Starting and Stopping Threads */
    virtual void                     suspend();

protected:
    /** @group Implementation */
    virtual IStartedThread*          startedThread() const;
private:
    friend class                     INonGUIThread;
    friend class                     ICurrentThread;

    ICurrentNonGUIThreadData*        fCurrentThreadData;
}; // ICurrentNonGUIThread

#pragma pack(pop)
#pragma enum(pop)

#if __IBMCPP__ >= 400
#pragma namemangling()
#endif

#if ! defined(__TEMPINC__)
#include <ingthrd.c>
#endif
#include <ingthrd.inl>



#endif // _INGTHRD_
