2 * Copyright (C) 2005-2011 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, write to
17 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18 * http://www.gnu.org/copyleft/gpl.html
24 #include <boost/thread/condition_variable.hpp>
26 #include "threads/SingleLock.h"
31 * This is a thin wrapper around boost::condition_variable. It is subject
32 * to "spurious returns" as it is built on boost which is built on posix
33 * on many of our platforms.
35 class ConditionVariable
38 boost::condition_variable_any impl;
40 // explicitly deny copying
41 inline ConditionVariable(const ConditionVariable& other) {}
42 inline ConditionVariable& operator=(ConditionVariable& other) { return *this; }
44 inline ConditionVariable() {}
46 enum TimedWaitResponse { TW_OK = 0, TW_TIMEDOUT = 1, TW_INTERRUPTED=-1, TW_ERROR=-2 };
48 template<typename L> inline void wait(L& lock) { impl.wait(lock); }
50 template<typename L> inline TimedWaitResponse wait(L& lock, int milliseconds)
52 ConditionVariable::TimedWaitResponse ret = TW_OK;
53 try { ret = (impl.timed_wait(lock, boost::posix_time::milliseconds(milliseconds))) ? TW_OK : TW_TIMEDOUT; }
54 catch (boost::thread_interrupted ) { ret = TW_INTERRUPTED; }
55 catch (...) { ret = TW_ERROR; }
59 inline void notifyAll() { impl.notify_all(); }
60 inline void notify() { impl.notify_one(); }
64 * This is a condition variable along with its predicate. This allows the use of a
65 * condition variable without the spurious returns since the state being monitored
66 * is also part of the condition.
68 * L should implement the Lockable concept
70 * The requirements on P are that it can act as a predicate (that is, I can use
71 * it in an 'while(!predicate){...}' where 'predicate' is of type 'P').
73 template <typename P> class TightConditionVariable
75 ConditionVariable cond;
78 inline TightConditionVariable(P predicate_) : predicate(predicate_) {}
79 template <typename L> inline void wait(L& lock) { while(!predicate) cond.wait(lock); }
81 template <typename L> inline ConditionVariable::TimedWaitResponse wait(L& lock, int milliseconds)
83 ConditionVariable::TimedWaitResponse ret = ConditionVariable::TW_OK;
84 boost::system_time const timeout=boost::get_system_time() + boost::posix_time::milliseconds(milliseconds);
85 while ((!predicate) && ret != ConditionVariable::TW_TIMEDOUT)
87 cond.wait(lock,milliseconds);
90 if ((!predicate) && boost::get_system_time() > timeout)
91 ret = ConditionVariable::TW_TIMEDOUT;
94 ret = (!predicate) ? ConditionVariable::TW_TIMEDOUT : ConditionVariable::TW_OK;
99 inline void notifyAll() { cond.notifyAll(); }
100 inline void notify() { cond.notify(); }