Mercurial > hg > vampy
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 |