#ifndef MARS_MThread
#define MARS_MThread

#ifndef ROOT_TThread
#include <TThread.h>
#endif

/*
class MyThread : public TThread
{
    friend class MyThreadX;

private:

    virtual Int_t Thread() = 0;
    static void *MapThread(void *arg)
    {
        // GetPriority();     High: -1 - -20, Norm: 0, Low: 1-20
        // pthread_setschedprio(SelfId(), priority);
        // 0: ok,

        MyThread *th = (MyThread*)arg;
        return (void*)th->Thread();
    }

public:
    MyThread(EPriority pri = kNormalPriority)
        : TThread(MapThread, this, pri) { }
    MyThread(const char *thname, EPriority pri = kNormalPriority)
        : TThread(thname, MapThread, this, pri) { }
};
*/

class MyThreadX
{
private:
    TThread fThread;

    Int_t fNumCleanups;

    virtual void CleanUp() { }
    static void MapCleanUp(void *arg)
    {
        MyThreadX *th = (MyThreadX*)arg;
        th->CleanUp();
    }

    virtual Int_t Thread() = 0;
    static void *MapThread(void *arg)
    {
        // GetPriority();     High: -1 - -20, Norm: 0, Low: 1-20
        // pthread_setschedprio(SelfId(), priority);
        // 0: ok,

        TThread::CleanUpPush((void*)&MapCleanUp, arg);

        MyThreadX *th = (MyThreadX*)arg;
        return (void*)th->Thread();
    }

public:
    MyThreadX(TThread::EPriority pri = TThread::kNormalPriority)
        : fThread(MapThread, this, pri), fNumCleanups(0) { }
    MyThreadX(const char *thname, TThread::EPriority pri = TThread::kNormalPriority)
        : fThread(thname, MapThread, this, pri), fNumCleanups(0) { }
    virtual ~MyThreadX() { }

//        Int_t            Kill() { return fThread.Kill(); }
        Int_t            RunThread(void *arg = 0) { return fThread.Run(); }
//    void             SetPriority(EPriority pri)
//    void             Delete(Option_t *option="") { TObject::Delete(option); }
//    EPriority        GetPriority() const { return fPriority; }
        TThread::EState  GetThreadState() const { return fThread.GetState(); }
        Long_t           GetThreadId() const { return fThread.GetId(); }
//        Long_t           Join(void **ret = 0) { return fThread.Join(ret); }

        TString GetThreadStateStr() const;

        Bool_t IsThreadRunning()  const { return fThread.GetState()==TThread::kRunningState; }
        Bool_t IsThreadCanceled() const { return fThread.GetState()==TThread::kCancelingState; }

        // Send cancel request and wait for cancellation
        // 13 is returned if thread is not running,
        // the return code of Join otherwise
        Int_t CancelThread(void **ret = 0) {
            const Int_t rc = fThread.Kill();
            if (rc==13) // Thread not running
                return rc;
            return fThread.Join(ret);
        }

        // This is a version of usleep which is a cancel point
        static void Sleep(UInt_t us)
        {
            TThread::SetCancelOn();
            usleep(us);
            TThread::SetCancelOff();
        }


//   ClassDef(MyThreadX,0)  // Thread class
};

#endif
