comparison Mutex.cpp @ 3:134313c59d82

* Add global mutex to PyPlugin -- all plugin method calls are strictly serialised in order to avoid problems with Python interpreter's lack of thread safety.
author cannam
date Fri, 14 Mar 2008 12:02:15 +0000
parents
children 6ed5ebd38fde
comparison
equal deleted inserted replaced
2:211ebe55d521 3:134313c59d82
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 Basic cross-platform mutex abstraction class.
5 This file copyright 2007 Chris Cannam.
6 */
7
8 #include "Mutex.h"
9
10 #include <iostream>
11
12 #ifndef _WIN32
13 #include <sys/time.h>
14 #include <time.h>
15 #endif
16
17 using std::cerr;
18 using std::endl;
19 using std::string;
20
21 #ifdef _WIN32
22
23 Mutex::Mutex()
24 #ifndef NO_THREAD_CHECKS
25 :
26 m_lockedBy(-1)
27 #endif
28 {
29 m_mutex = CreateMutex(NULL, FALSE, NULL);
30 #ifdef DEBUG_MUTEX
31 cerr << "MUTEX DEBUG: " << (void *)GetCurrentThreadId() << ": Initialised mutex " << &m_mutex << endl;
32 #endif
33 }
34
35 Mutex::~Mutex()
36 {
37 #ifdef DEBUG_MUTEX
38 cerr << "MUTEX DEBUG: " << (void *)GetCurrentThreadId() << ": Destroying mutex " << &m_mutex << endl;
39 #endif
40 CloseHandle(m_mutex);
41 }
42
43 void
44 Mutex::lock()
45 {
46 #ifndef NO_THREAD_CHECKS
47 DWORD tid = GetCurrentThreadId();
48 if (m_lockedBy == tid) {
49 cerr << "ERROR: Deadlock on mutex " << &m_mutex << endl;
50 }
51 #endif
52 #ifdef DEBUG_MUTEX
53 cerr << "MUTEX DEBUG: " << (void *)tid << ": Want to lock mutex " << &m_mutex << endl;
54 #endif
55 WaitForSingleObject(m_mutex, INFINITE);
56 #ifndef NO_THREAD_CHECKS
57 m_lockedBy = tid;
58 #endif
59 #ifdef DEBUG_MUTEX
60 cerr << "MUTEX DEBUG: " << (void *)tid << ": Locked mutex " << &m_mutex << endl;
61 #endif
62 }
63
64 void
65 Mutex::unlock()
66 {
67 #ifndef NO_THREAD_CHECKS
68 DWORD tid = GetCurrentThreadId();
69 if (m_lockedBy != tid) {
70 cerr << "ERROR: Mutex " << &m_mutex << " not owned by unlocking thread" << endl;
71 return;
72 }
73 #endif
74 #ifdef DEBUG_MUTEX
75 cerr << "MUTEX DEBUG: " << (void *)tid << ": Unlocking mutex " << &m_mutex << endl;
76 #endif
77 #ifndef NO_THREAD_CHECKS
78 m_lockedBy = -1;
79 #endif
80 ReleaseMutex(m_mutex);
81 }
82
83 bool
84 Mutex::trylock()
85 {
86 #ifndef NO_THREAD_CHECKS
87 DWORD tid = GetCurrentThreadId();
88 #endif
89 DWORD result = WaitForSingleObject(m_mutex, 0);
90 if (result == WAIT_TIMEOUT || result == WAIT_FAILED) {
91 #ifdef DEBUG_MUTEX
92 cerr << "MUTEX DEBUG: " << (void *)tid << ": Mutex " << &m_mutex << " unavailable" << endl;
93 #endif
94 return false;
95 } else {
96 #ifndef NO_THREAD_CHECKS
97 m_lockedBy = tid;
98 #endif
99 #ifdef DEBUG_MUTEX
100 cerr << "MUTEX DEBUG: " << (void *)tid << ": Locked mutex " << &m_mutex << " (from trylock)" << endl;
101 #endif
102 return true;
103 }
104 }
105
106 #else /* !_WIN32 */
107
108 Mutex::Mutex()
109 #ifndef NO_THREAD_CHECKS
110 :
111 m_lockedBy(0),
112 m_locked(false)
113 #endif
114 {
115 pthread_mutex_init(&m_mutex, 0);
116 #ifdef DEBUG_MUTEX
117 cerr << "MUTEX DEBUG: " << (void *)pthread_self() << ": Initialised mutex " << &m_mutex << endl;
118 #endif
119 }
120
121 Mutex::~Mutex()
122 {
123 #ifdef DEBUG_MUTEX
124 cerr << "MUTEX DEBUG: " << (void *)pthread_self() << ": Destroying mutex " << &m_mutex << endl;
125 #endif
126 pthread_mutex_destroy(&m_mutex);
127 }
128
129 void
130 Mutex::lock()
131 {
132 #ifndef NO_THREAD_CHECKS
133 pthread_t tid = pthread_self();
134 if (m_locked && m_lockedBy == tid) {
135 cerr << "ERROR: Deadlock on mutex " << &m_mutex << endl;
136 }
137 #endif
138 #ifdef DEBUG_MUTEX
139 cerr << "MUTEX DEBUG: " << (void *)tid << ": Want to lock mutex " << &m_mutex << endl;
140 #endif
141 pthread_mutex_lock(&m_mutex);
142 #ifndef NO_THREAD_CHECKS
143 m_lockedBy = tid;
144 m_locked = true;
145 #endif
146 #ifdef DEBUG_MUTEX
147 cerr << "MUTEX DEBUG: " << (void *)tid << ": Locked mutex " << &m_mutex << endl;
148 #endif
149 }
150
151 void
152 Mutex::unlock()
153 {
154 #ifndef NO_THREAD_CHECKS
155 pthread_t tid = pthread_self();
156 if (!m_locked) {
157 cerr << "ERROR: Mutex " << &m_mutex << " not locked in unlock" << endl;
158 return;
159 } else if (m_lockedBy != tid) {
160 cerr << "ERROR: Mutex " << &m_mutex << " not owned by unlocking thread" << endl;
161 return;
162 }
163 #endif
164 #ifdef DEBUG_MUTEX
165 cerr << "MUTEX DEBUG: " << (void *)tid << ": Unlocking mutex " << &m_mutex << endl;
166 #endif
167 #ifndef NO_THREAD_CHECKS
168 m_locked = false;
169 #endif
170 pthread_mutex_unlock(&m_mutex);
171 }
172
173 bool
174 Mutex::trylock()
175 {
176 #ifndef NO_THREAD_CHECKS
177 pthread_t tid = pthread_self();
178 #endif
179 if (pthread_mutex_trylock(&m_mutex)) {
180 #ifdef DEBUG_MUTEX
181 cerr << "MUTEX DEBUG: " << (void *)tid << ": Mutex " << &m_mutex << " unavailable" << endl;
182 #endif
183 return false;
184 } else {
185 #ifndef NO_THREAD_CHECKS
186 m_lockedBy = tid;
187 m_locked = true;
188 #endif
189 #ifdef DEBUG_MUTEX
190 cerr << "MUTEX DEBUG: " << (void *)tid << ": Locked mutex " << &m_mutex << " (from trylock)" << endl;
191 #endif
192 return true;
193 }
194 }
195
196 #endif