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