    // @(#)root/thread:$Name:  $:$Id: TCondition.cxx,v 1.7 2005/05/27 08:48:27 rdm Exp $
    // Author: Fons Rademakers   01/07/97

    /*************************************************************************
     * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
     * All rights reserved.                                                  *
     *                                                                       *
     * For the licensing terms see $ROOTSYS/LICENSE.                         *
     * For the list of contributors see $ROOTSYS/README/CREDITS.             *
     *************************************************************************/

    //////////////////////////////////////////////////////////////////////////
    //                                                                      //
    // TCondition                                                           //
    //                                                                      //
    // This class implements a condition variable. Use a condition variable //
    // to signal threads. The actual work is done via the TConditionImp     //
    // class (either TPosixCondition or TWin32Condition).                   //
    //                                                                      //
    //////////////////////////////////////////////////////////////////////////

    #include "TCondition.h"
    #include "TMutex.h"
    #include "TThreadFactory.h"

    ClassImp(TCondition)

    //______________________________________________________________________________
     TCondition::TCondition(TMutex *m)
    {
       // Create a condition variable. The actual condition implementation
       // will be provided via the TThreadFactory. If no external mutex is
       // provided one will be created. Use GetMutex() to get this mutex
       // and use it before calling Signal() or Broadcast().

       fPrivateMutex = (m == 0);
       if (fPrivateMutex) {
          fMutex = new TMutex();
       } else {
          fMutex = m;
       }

       fConditionImp = gThreadFactory->CreateConditionImp(fMutex->fMutexImp);

       if (!fConditionImp)
          Error("TCondition", "could not create TConditionImp");
    }

    //______________________________________________________________________________
     TCondition::~TCondition()
    {
       // Clean up condition variable.

       delete fConditionImp;
       if (fPrivateMutex) delete fMutex;
    }

    //______________________________________________________________________________
     TMutex *TCondition::GetMutex() const
    {
       // Get internally created mutex. Use it to lock resources
       // before calling Signal() or Broadcast(). Returns 0 if
       // external mutex was provided in TCondition ctor.

       if (fPrivateMutex)
          return fMutex;
       return 0;
    }

    //______________________________________________________________________________
     Int_t TCondition::Wait()
    {
       // Wait to be signaled.

       if (!fConditionImp) return -1;

       Int_t iret;
       if (fPrivateMutex) fMutex->Lock();
       iret = fConditionImp->Wait();
       fMutex->fId = TThread::SelfId(); // fix the owner because lowlevel relock
       if (fPrivateMutex) fMutex->UnLock();
       return iret;
    }

    //______________________________________________________________________________
     Int_t TCondition::TimedWait(ULong_t secs, ULong_t nanoSec)
    {
       // Wait to be signaled or till the timer times out.
       // This method is given an absolute time since the beginning of
       // the EPOCH (use TThread::GetTime() to get this absolute time).
       // To wait for a relative time from now, use
       // TCondition::TimedWaitRelative(ULong_t ms).
       // Returns 0 if successfully signalled, 1 if time expired and -1 in
       // case of error.

       if (!fConditionImp) return -1;

       Int_t iret;
       if (fPrivateMutex) fMutex->Lock();
       iret = fConditionImp->TimedWait(secs, nanoSec);
       fMutex->fId = TThread::SelfId(); // fix the owner because lowlevel relock
       if (fPrivateMutex) fMutex->UnLock();
       return iret;
    }

    //______________________________________________________________________________
     Int_t TCondition::TimedWaitRelative(ULong_t ms)
    {
       // Wait to be signaled or till the timer times out.
       // This method is given a relative time from now.
       // To wait for an absolute time since the beginning of the EPOCH, use
       // TCondition::TimedWait(ULong_t secs, ULong_t nanoSec).
       // Returns 0 if successfully signalled, 1 if time expired and -1 in
       // case of error.

       if (!fConditionImp) return -1;

       ULong_t absSec, absNanoSec;
       TThread::GetTime(&absSec, &absNanoSec);

       ULong_t dsec = ms/1000;
       absSec += dsec;
       absNanoSec += (ms - dsec*1000) * 1000000;
       if (absNanoSec > 999999999) {
         absSec += 1;
         absNanoSec -= 1000000000;
       }

       return TimedWait(absSec, absNanoSec);
    }