1 //////////////////////////////////////////////////////////////////////
3 // CriticalSection.h: interface for the CCriticalSection class.
5 //////////////////////////////////////////////////////////////////////
10 * Copyright (C) 2005-2008 Team XBMC
13 * This Program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2, or (at your option)
18 * This Program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with XBMC; see the file COPYING. If not, write to
25 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
26 * http://www.gnu.org/copyleft/gpl.html
30 #include <boost/thread/recursive_mutex.hpp>
33 * Because there are several different Lockable schemes we use, this
34 * template extends the boost behavior and adds some xbmc assumptions
35 * mainly that a CriticalSection (or SharedSection) is "exitable."
37 * "Exitable" specifially means that, no matter how deep the recursion
38 * on the mutex/critical section, we can exit from it and then restore
41 * This requires us to extend boost so that we can keep track of the
42 * number of locks that have been recursively acquired so that we can
43 * undo it, and then restore that (See class CSingleExit).
45 * This implements boost's "Lockable concept" which simply means that
46 * it has the three methods:
52 template<class L> class CountingLockable
59 inline CountingLockable() : count(0) {}
61 // boost::thread Lockable concept
62 inline void lock() { mutex.lock(); count++; }
63 inline bool try_lock() { return mutex.try_lock() ? count++, true : false; }
64 inline void unlock() { count--; mutex.unlock(); }
67 * This implements the "exitable" behavior mentioned above.
69 inline unsigned int exit()
71 // it's possibe we don't actually own the lock
76 ret = count - 1; // The -1 is because we don't want
77 // to count the try_lock increment.
78 while (count > 0) // This will also unlock the try_lock.
86 * Restore a previous exit to the provided level.
88 inline void restore(unsigned int restoreCount)
90 for (unsigned int i = 0; i < restoreCount; i++)
94 inline unsigned int getCount() { return count; }
96 inline L& getLockable() { return mutex; }
100 * A CCriticalSection is a CountingLockable whose implementation is a boost
103 * This is not a typedef because of a number of "class CCriticalSection;"
104 * forward declarations in the code that break when it's done that way.
106 class CCriticalSection : public CountingLockable<boost::recursive_mutex> {};