text: /*
   *      Copyright (C) 2005-2013 Team XBMC
   *      http://xbmc.org
   *
   *  This Program is free software; you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License as published by
   *  the Free Software Foundation; either version 2, or (at your option)
   *  any later version.
   *
   *  This Program 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 General Public License for more details.
   *
   *  You should have received a copy of the GNU General Public License
   *  along with XBMC; see the file COPYING.  If not, see
   *  <http://www.gnu.org/licenses/>.
   *
   */
  
  #pragma once
  
  #include "threads/SingleLock.h"
  #include "threads/Helpers.h"
  
  #include <pthread.h>
  
  #ifdef TARGET_DARWIN
    #include <sys/time.h> //for gettimeofday
  #else
    #include <time.h> //for clock_gettime
  #endif
  
  namespace XbmcThreads
  {
  
    /**
     * This is a thin wrapper around boost::condition_variable. It is subject
     *  to "spurious returns" as it is built on boost which is built on posix
     *  on many of our platforms.
     */
    class ConditionVariable : public NonCopyable
    {
    private:
      pthread_cond_t cond;
  
    public:
      inline ConditionVariable() 
      { 
        pthread_cond_init(&cond,NULL); 
      }
  
      inline ~ConditionVariable() 
      { 
        pthread_cond_destroy(&cond);
      }
  
      inline void wait(CCriticalSection& lock) 
      {
        int count  = lock.count;
        lock.count = 0;
        pthread_cond_wait(&cond,&lock.get_underlying().mutex);
        lock.count = count;
      }
  
      inline bool wait(CCriticalSection& lock, unsigned long milliseconds) 
      { 
        struct timespec ts;
  
  #ifdef TARGET_DARWIN
        struct timeval tv;
        gettimeofday(&tv, NULL);
        ts.tv_nsec = tv.tv_usec * 1000;
        ts.tv_sec  = tv.tv_sec;
  #else
        clock_gettime(CLOCK_REALTIME, &ts);
  #endif
  
        ts.tv_nsec += milliseconds % 1000 * 1000000;
        ts.tv_sec  += milliseconds / 1000 + ts.tv_nsec / 1000000000;
        ts.tv_nsec %= 1000000000;
        int count  = lock.count;
        lock.count = 0;
        int res    = pthread_cond_timedwait(&cond,&lock.get_underlying().mutex,&ts);
        lock.count = count;
        return res == 0;
      }
  
      inline void wait(CSingleLock& lock) { wait(lock.get_underlying()); }
      inline bool wait(CSingleLock& lock, unsigned long milliseconds) { return wait(lock.get_underlying(), milliseconds); }
  
      inline void notifyAll() 
      { 
        pthread_cond_broadcast(&cond);
      }
  
      inline void notify() 
      { 
        pthread_cond_signal(&cond);
      }
    };
  
  }
  