1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
/**
\file G3D/GMutex.h
\created 2005-09-22
\edited 2013-04-03
*/
#ifndef G3D_GMutex_h
#define G3D_GMutex_h
#include "G3D/platform.h"
#include "G3D/AtomicInt32.h"
#include "G3D/debugAssert.h"
#include <string>
#ifndef G3D_WINDOWS
# include <pthread.h>
# include <signal.h>
#endif
#if defined(G3D_LINUX) || defined(G3D_OSX)
# include <unistd.h> // For usleep
#endif
namespace G3D {
/**
\brief A mutual exclusion lock that busy-waits when locking.
On a machine with one (significant) thread per processor core,
a Spinlock may be substantially faster than a mutex.
\sa G3D::GThread, G3D::GMutex, G3D::AtomicInt32
*/
class Spinlock {
private:
AtomicInt32 x;
public:
inline Spinlock() : x(0) {}
/** Busy waits until the lock is unlocked, then locks it
exclusively. Returns true if the lock succeeded on the first
try (indicating no contention).
Unlike a G3D::GMutex, a single thread cannot re-enter
Spinlock::lock() that it already locked.
*/
inline bool lock() {
bool first = true;
while (x.compareAndSet(0, 1) == 1) {
first = false;
# ifdef G3D_WINDOWS
Sleep(0);
# else
usleep(0);
# endif
}
return first;
}
inline void unlock() {
x.compareAndSet(1, 0);
}
};
/**
\brief Mutual exclusion lock used for synchronization.
@sa G3D::GThread, G3D::AtomicInt32, G3D::Spinlock
*/
class GMutex {
private:
# ifdef G3D_WINDOWS
CRITICAL_SECTION m_handle;
# else
pthread_mutex_t m_handle;
pthread_mutexattr_t m_attr;
# endif
// Not implemented on purpose, don't use
GMutex(const GMutex &mlock);
GMutex &operator=(const GMutex &);
bool operator==(const GMutex&);
public:
GMutex();
~GMutex();
/** Locks the mutex or blocks until available. */
void lock();
/** Locks the mutex if it not already locked.
Returns true if lock successful, false otherwise. */
bool tryLock();
/** Unlocks the mutex. */
void unlock();
};
/**
Automatically locks while in scope.
*/
class GMutexLock {
private:
GMutex* m;
// Not implemented on purpose, don't use
GMutexLock(const GMutexLock &mlock);
GMutexLock &operator=(const GMutexLock &);
bool operator==(const GMutexLock&);
public:
GMutexLock(GMutex* mutex) {
m = mutex;
m->lock();
}
~GMutexLock() {
m->unlock();
}
};
} // G3D
#endif
|