CPPMyth
Library to interoperate with MythTV server
mutex.h
1 #pragma once
2 /*
3  * Copyright (C) 2015 Jean-Luc Barriere
4  *
5  * This library is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU Lesser General Public License as published
7  * by the Free Software Foundation; either version 3, or (at your option)
8  * any later version.
9  *
10  * This library 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 Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with this library; see the file COPYING. If not, write to
17  * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
18  * MA 02110-1301 USA
19  * http://www.gnu.org/copyleft/gpl.html
20  *
21  */
22 
23 #include "os-threads.h"
24 
25 #ifdef NSROOT
26 namespace NSROOT {
27 #endif
28 namespace OS
29 {
30 
31  class CMutex
32  {
33  public:
34  CMutex()
35  : m_lockCount(0)
36  {
37  mutex_init(&m_handle);
38  }
39 
40  ~CMutex()
41  {
42  Clear();
43  mutex_destroy(&m_handle);
44  }
45 
46  mutex_t* NativeHandle()
47  {
48  return &m_handle;
49  }
50 
51  bool TryLock()
52  {
53  if (mutex_trylock(&m_handle))
54  {
55  ++m_lockCount;
56  return true;
57  }
58  return false;
59  }
60 
61  void Lock()
62  {
63  mutex_lock(&m_handle);
64  ++m_lockCount;
65  }
66 
67  void Unlock()
68  {
69  if (mutex_trylock(&m_handle))
70  {
71  if (m_lockCount > 0)
72  {
73  mutex_unlock(&m_handle);
74  --m_lockCount;
75  }
76  mutex_unlock(&m_handle);
77  }
78  }
79 
80  void Clear()
81  {
82  if (mutex_trylock(&m_handle))
83  {
84  for (unsigned i = m_lockCount; i > 0; --i)
85  mutex_unlock(&m_handle);
86  m_lockCount = 0;
87  mutex_unlock(&m_handle);
88  }
89  }
90 
91  private:
92  mutex_t m_handle;
93  volatile unsigned m_lockCount;
94 
95  // Prevent copy
96  CMutex(const CMutex& other);
97  CMutex& operator=(const CMutex& other);
98  };
99 
101  {
102  public:
103  CLockGuard(CMutex& mutex)
104  : m_mutex(mutex)
105  , m_lockCount(0)
106  {
107  Lock();
108  }
109 
110  ~CLockGuard()
111  {
112  Clear();
113  }
114 
115  bool TryLock()
116  {
117  if (m_mutex.TryLock())
118  {
119  ++m_lockCount;
120  return true;
121  }
122  return false;
123  }
124 
125  void Lock()
126  {
127  m_mutex.Lock();
128  ++m_lockCount;
129  }
130 
131  void Unlock()
132  {
133  if (m_mutex.TryLock())
134  {
135  if (m_lockCount > 0)
136  {
137  m_mutex.Unlock();
138  --m_lockCount;
139  }
140  m_mutex.Unlock();
141  }
142  }
143 
144  void Clear()
145  {
146  if (m_mutex.TryLock())
147  {
148  for (unsigned i = m_lockCount; i > 0; --i)
149  m_mutex.Unlock();
150  m_lockCount = 0;
151  m_mutex.Unlock();
152  }
153  }
154 
155  private:
156  CMutex& m_mutex;
157  volatile unsigned m_lockCount;
158 
159  // Prevent copy
160  CLockGuard(const CLockGuard& other);
161  CLockGuard& operator=(const CLockGuard& other);
162  };
163 
164 }
165 #ifdef NSROOT
166 }
167 #endif