Merge pull request #184 from pieh/python_editControl
[vuplus_xbmc] / xbmc / threads / Condition.h
1 /*
2  *      Copyright (C) 2005-2011 Team XBMC
3  *      http://www.xbmc.org
4  *
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)
8  *  any later version.
9  *
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.
14  *
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
19  *
20  */
21
22 #pragma once
23
24 #include <boost/thread/condition_variable.hpp>
25
26 #include "threads/SingleLock.h"
27
28 namespace XbmcThreads
29 {
30   /**
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.
34    */
35   class ConditionVariable
36   {
37   private:
38     boost::condition_variable_any impl;
39
40     // explicitly deny copying
41     inline ConditionVariable(const ConditionVariable& other) {}
42     inline ConditionVariable& operator=(ConditionVariable& other) { return *this; }
43   public:
44     inline ConditionVariable() {}
45
46     enum TimedWaitResponse { TW_OK = 0, TW_TIMEDOUT = 1, TW_INTERRUPTED=-1, TW_ERROR=-2 };
47
48     template<typename L> inline void wait(L& lock) { impl.wait(lock); }
49
50     template<typename L> inline TimedWaitResponse wait(L& lock, int milliseconds)
51     {
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; }
56       return ret;
57     }
58
59     inline void notifyAll() { impl.notify_all(); }
60     inline void notify() { impl.notify_one(); }
61   };
62
63   /**
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.
67    *
68    * L should implement the Lockable concept
69    *
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').
72    */
73   template <typename P> class TightConditionVariable
74   {
75     ConditionVariable cond;
76     P predicate;
77   public:
78     inline TightConditionVariable(P predicate_) : predicate(predicate_) {}
79     template <typename L> inline void wait(L& lock) { while(!predicate) cond.wait(lock); }
80
81     template <typename L> inline ConditionVariable::TimedWaitResponse wait(L& lock, int milliseconds)
82     {
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)
86       {
87         ret = cond.wait(lock,milliseconds);
88
89         if (!predicate && boost::get_system_time() > timeout)
90           ret = ConditionVariable::TW_TIMEDOUT;
91       }
92       return ret;
93     }
94
95     inline void notifyAll() { cond.notifyAll(); }
96     inline void notify() { cond.notify(); }
97   };
98 }
99