7
7
#include < mutex>
8
8
#include < set>
9
9
10
- std::unique_ptr<std:: mutex> _lock_set_mutex = std::make_unique<std::mutex>() ;
10
+ std::mutex _lock_set_mutex;
11
11
12
12
// ----------------------------------------------------------------------------
13
13
// Lock class
@@ -23,19 +23,18 @@ typedef struct lock
23
23
std::unique_ptr<std::timed_mutex> _mutex = nullptr ;
24
24
} Lock;
25
25
26
- std::set<Lock*> lock_set; // Global set of locks for reset after fork
26
+ std::set<Lock*> lock_set;
27
27
28
28
// ----------------------------------------------------------------------------
29
29
static int
30
- Lock_init (Lock* self, PyObject* args, PyObject* kwargs)
30
+ Lock_init (Lock* self, PyObject* Py_UNUSED ( args) , PyObject* Py_UNUSED( kwargs) )
31
31
{
32
32
self->_mutex = std::make_unique<std::timed_mutex>();
33
33
34
- // Register the lock for reset after fork
35
34
{
36
35
AllowThreads _;
37
36
38
- std::lock_guard<std::mutex> guard (* _lock_set_mutex);
37
+ std::lock_guard<std::mutex> guard (_lock_set_mutex);
39
38
40
39
lock_set.insert (self);
41
40
}
@@ -51,11 +50,16 @@ Lock_dealloc(Lock* self)
51
50
{
52
51
AllowThreads _;
53
52
54
- std::lock_guard<std::mutex> guard (* _lock_set_mutex);
53
+ std::lock_guard<std::mutex> guard (_lock_set_mutex);
55
54
56
55
lock_set.erase (self);
57
56
}
58
57
58
+ if (self->_locked > 0 ) {
59
+ self->_mutex ->unlock ();
60
+ self->_locked = 0 ;
61
+ }
62
+
59
63
self->_mutex = nullptr ;
60
64
61
65
Py_TYPE (self)->tp_free ((PyObject*)self);
@@ -109,7 +113,7 @@ Lock_release(Lock* self)
109
113
}
110
114
111
115
self->_mutex ->unlock ();
112
- self->_locked = 0 ; // Reset the lock state
116
+ self->_locked = 0 ;
113
117
114
118
Py_RETURN_NONE;
115
119
}
@@ -127,7 +131,7 @@ Lock_locked(Lock* self)
127
131
128
132
// ----------------------------------------------------------------------------
129
133
static PyObject*
130
- Lock_enter (Lock* self, PyObject* args, PyObject* kwargs )
134
+ Lock_enter (Lock* self)
131
135
{
132
136
AllowThreads _;
133
137
@@ -140,7 +144,7 @@ Lock_enter(Lock* self, PyObject* args, PyObject* kwargs)
140
144
141
145
// ----------------------------------------------------------------------------
142
146
static PyObject*
143
- Lock_exit (Lock* self, PyObject* args, PyObject* kwargs)
147
+ Lock_exit (Lock* self, PyObject* Py_UNUSED ( args) , PyObject* Py_UNUSED( kwargs) )
144
148
{
145
149
// This method is called when the lock is used in a "with" statement
146
150
if (Lock_release (self) == NULL ) {
@@ -150,13 +154,6 @@ Lock_exit(Lock* self, PyObject* args, PyObject* kwargs)
150
154
Py_RETURN_FALSE;
151
155
}
152
156
153
- static inline void
154
- Lock_reset (Lock* self)
155
- {
156
- self->_mutex = std::make_unique<std::timed_mutex>();
157
- self->_locked = 0 ;
158
- }
159
-
160
157
// ----------------------------------------------------------------------------
161
158
static PyMethodDef Lock_methods[] = {
162
159
{ " acquire" , (PyCFunction)Lock_acquire, METH_VARARGS | METH_KEYWORDS, " Acquire the lock with an optional timeout" },
@@ -200,19 +197,18 @@ typedef struct rlock
200
197
std::unique_ptr<std::recursive_timed_mutex> _mutex = nullptr ;
201
198
} RLock;
202
199
203
- std::set<RLock*> rlock_set; // Global set of re-entrant locks for reset after fork
200
+ std::set<RLock*> rlock_set;
204
201
205
202
// ----------------------------------------------------------------------------
206
203
static int
207
- RLock_init (RLock* self, PyObject* args, PyObject* kwargs)
204
+ RLock_init (RLock* self, PyObject* Py_UNUSED ( args) , PyObject* Py_UNUSED( kwargs) )
208
205
{
209
206
self->_mutex = std::make_unique<std::recursive_timed_mutex>();
210
207
211
- // Register the re-entrant lock for reset after fork
212
208
{
213
209
AllowThreads _;
214
210
215
- std::lock_guard<std::mutex> guard (* _lock_set_mutex);
211
+ std::lock_guard<std::mutex> guard (_lock_set_mutex);
216
212
217
213
rlock_set.insert (self);
218
214
}
@@ -227,11 +223,15 @@ RLock_dealloc(RLock* self)
227
223
{
228
224
AllowThreads _;
229
225
230
- std::lock_guard<std::mutex> guard (* _lock_set_mutex);
226
+ std::lock_guard<std::mutex> guard (_lock_set_mutex);
231
227
232
228
rlock_set.erase (self);
233
229
}
234
230
231
+ for (; self->_locked > 0 ; self->_locked --) {
232
+ self->_mutex ->unlock ();
233
+ }
234
+
235
235
self->_mutex = nullptr ;
236
236
237
237
Py_TYPE (self)->tp_free ((PyObject*)self);
@@ -303,7 +303,7 @@ RLock_locked(RLock* self)
303
303
304
304
// ----------------------------------------------------------------------------
305
305
static PyObject*
306
- RLock_enter (RLock* self, PyObject* args, PyObject* kwargs )
306
+ RLock_enter (RLock* self)
307
307
{
308
308
AllowThreads _;
309
309
@@ -316,7 +316,7 @@ RLock_enter(RLock* self, PyObject* args, PyObject* kwargs)
316
316
317
317
// ----------------------------------------------------------------------------
318
318
static PyObject*
319
- RLock_exit (RLock* self, PyObject* args, PyObject* kwargs)
319
+ RLock_exit (RLock* self, PyObject* Py_UNUSED ( args) , PyObject* Py_UNUSED( kwargs) )
320
320
{
321
321
// This method is called when the lock is used in a "with" statement
322
322
if (RLock_release (self) == NULL ) {
@@ -326,13 +326,6 @@ RLock_exit(RLock* self, PyObject* args, PyObject* kwargs)
326
326
Py_RETURN_FALSE;
327
327
}
328
328
329
- static inline void
330
- RLock_reset (RLock* self)
331
- {
332
- self->_mutex = std::make_unique<std::recursive_timed_mutex>();
333
- self->_locked = 0 ;
334
- }
335
-
336
329
// ----------------------------------------------------------------------------
337
330
static PyMethodDef RLock_methods[] = {
338
331
{ " acquire" ,
@@ -367,21 +360,41 @@ static PyTypeObject RLockType = {
367
360
368
361
// ----------------------------------------------------------------------------
369
362
static PyObject*
370
- lock_reset_locks (PyObject* Py_UNUSED (self), PyObject* Py_UNUSED(args))
363
+ lock_acquire_all (PyObject* Py_UNUSED (self), PyObject* Py_UNUSED(args))
371
364
{
372
- // Reset all locks that have been registered for reset after a fork. This
373
- // MUST be called in a single-thread scenario only, e.g. soon after the
374
- // fork.
365
+ {
366
+ AllowThreads _;
367
+
368
+ _lock_set_mutex.lock ();
369
+
370
+ for (Lock* lock : lock_set) {
371
+ lock->_mutex ->lock ();
372
+ lock->_locked = 1 ;
373
+ }
374
+
375
+ for (RLock* rlock : rlock_set) {
376
+ rlock->_mutex ->lock ();
377
+ rlock->_locked ++;
378
+ }
379
+ }
380
+
381
+ Py_RETURN_NONE;
382
+ }
383
+
384
+ // ----------------------------------------------------------------------------
385
+ static PyObject*
386
+ lock_release_all (PyObject* Py_UNUSED (self), PyObject* Py_UNUSED(args))
387
+ {
388
+
375
389
for (Lock* lock : lock_set) {
376
- Lock_reset (lock);
390
+ Lock_exit (lock, NULL , NULL );
377
391
}
378
392
379
393
for (RLock* rlock : rlock_set) {
380
- RLock_reset (rlock);
394
+ RLock_exit (rlock, NULL , NULL );
381
395
}
382
396
383
- // Reset the lock set mutex too!
384
- _lock_set_mutex = std::make_unique<std::mutex>();
397
+ _lock_set_mutex.unlock ();
385
398
386
399
Py_RETURN_NONE;
387
400
}
0 commit comments