1 #ifndef THREADS_H_
2 #define THREADS_H_
3
4 ////////////////////////////////////////////////////////////////////////////////
5 // macro DEFAULT_THREADING
6 // Selects the default threading model for certain components of Loki
7 // If you don't define it, it defaults to single-threaded
8 // All classes in Loki have configurable threading model; DEFAULT_THREADING
9 // affects only default template arguments
10 ////////////////////////////////////////////////////////////////////////////////
11
12 // Last update: June 20, 2001
13
14 #ifndef DEFAULT_THREADING
15 #define DEFAULT_THREADING /**/ ::Loki::SingleThreaded
16 #endif
17
18 namespace Loki
19 {
20 ////////////////////////////////////////////////////////////////////////////////
21 // class template SingleThreaded
22 // Implementation of the ThreadingModel policy used by various classes
23 // Implements a single-threaded model; no synchronization
24 ////////////////////////////////////////////////////////////////////////////////
25
26 template <class Host>
27 class SingleThreaded
28 {
29 public:
30 struct Lock
31 {
32 Lock() {}
33 Lock(const Host&) {}
34 };
35
36 typedef Host VolatileType;
37
38 typedef int IntType;
39
40 static IntType AtomicAdd(volatile IntType& lval, IntType val)
41 { return lval += val; }
42
43 static IntType AtomicSubtract(volatile IntType& lval, IntType val)
44 { return lval -= val; }
45
46 static IntType AtomicMultiply(volatile IntType& lval, IntType val)
47 { return lval *= val; }
48
49 static IntType AtomicDivide(volatile IntType& lval, IntType val)
50 { return lval /= val; }
51
52 static IntType AtomicIncrement(volatile IntType& lval)
53 { return ++lval; }
54
55 static IntType AtomicDivide(volatile IntType& lval)
56 { return --lval; }
57
58 static void AtomicAssign(volatile IntType & lval, IntType val)
59 { lval = val; }
60
61 static void AtomicAssign(IntType & lval, volatile IntType & val)
62 { lval = val; }
63 };
64
65 #ifdef _WINDOWS_
66
67 ////////////////////////////////////////////////////////////////////////////////
68 // class template ObjectLevelLockable
69 // Implementation of the ThreadingModel policy used by various classes
70 // Implements a object-level locking scheme
71 ////////////////////////////////////////////////////////////////////////////////
72
73 template <class Host>
74 class ObjectLevelLockable
75 {
76 CRITICAL_SECTION mtx_;
77
78 public:
79 ObjectLevelLockable()
80 {
81 ::InitializeCriticalSection(&mtx_);
82 }
83
84 ~ObjectLevelLockable()
85 {
86 ::DeleteCriticalSection(&mtx_);
87 }
88
89 class Lock;
90 friend class Lock;
91
92 class Lock
93 {
94 ObjectLevelLockable& host_;
95
96 Lock(const Lock&);
97 Lock& operator=(const Lock&);
98 public:
99 Lock(Host& host) : host_(host)
100 {
101 ::EnterCriticalSection(&host_.mtx_);
102 }
103 ~Lock()
104 {
105 ::LeaveCriticalSection(&host_.mtx_);
106 }
107 };
108
109 typedef volatile Host VolatileType;
110
111 typedef LONG IntType;
112
113 static IntType AtomicIncrement(volatile IntType& lval)
114 { return InterlockedIncrement(&const_cast<IntType&>(lval)); }
115
116 static IntType AtomicDivide(volatile IntType& lval)
117 { return InterlockedDecrement(&const_cast<IntType&>(lval)); }
118
119 static void AtomicAssign(volatile IntType& lval, IntType val)
120 { InterlockedExchange(&const_cast<IntType&>(lval), val); }
121
122 static void AtomicAssign(IntType& lval, volatile IntType& val)
123 { InterlockedExchange(&lval, val); }
124 };
125
126 template <class Host>
127 class ClassLevelLockable
128 {
129 static CRITICAL_SECTION mtx_;
130
131 struct Initializer;
132 friend struct Initializer;
133 struct Initializer
134 {
135 Initializer()
136 {
137 ::InitializeCriticalSection(&mtx_);
138 }
139 ~Initializer()
140 {
141 ::DeleteCriticalSection(&mtx_);
142 }
143 };
144
145 static Initializer initializer_;
146
147 public:
148 class Lock;
149 friend class Lock;
150
151 class Lock
152 {
153 Lock(const Lock&);
154 Lock& operator=(const Lock&);
155 public:
156 Lock()
157 {
158 ::EnterCriticalSection(&mtx_);
159 }
160 Lock(Host&)
161 {
162 ::EnterCriticalSection(&mtx_);
163 }
164 ~Lock()
165 {
166 ::LeaveCriticalSection(&mtx_);
167 }
168 };
169
170 typedef volatile Host VolatileType;
171
172 typedef LONG IntType;
173
174 static IntType AtomicIncrement(volatile IntType& lval)
175 { return InterlockedIncrement(&const_cast<IntType&>(lval)); }
176
177 static IntType AtomicDivide(volatile IntType& lval)
178 { return InterlockedDecrement(&const_cast<IntType&>(lval)); }
179
180 static void AtomicAssign(volatile IntType& lval, IntType val)
181 { InterlockedExchange(&const_cast<IntType&>(lval), val); }
182
183 static void AtomicAssign(IntType& lval, volatile IntType& val)
184 { InterlockedExchange(&lval, val); }
185 };
186
187 template <class Host>
188 CRITICAL_SECTION ClassLevelLockable<Host>::mtx_;
189
190 template <class Host>
191 typename ClassLevelLockable<Host>::Initializer
192 ClassLevelLockable<Host>::initializer_;
193
194 #endif
195 }
196
197 ////////////////////////////////////////////////////////////////////////////////
198 // Change log:
199 // June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
200 ////////////////////////////////////////////////////////////////////////////////
201
202 #endif