35
35
// See threadCritical.hpp for details of this class.
36
36
//
37
37
38
- static bool initialized = false ;
39
- static volatile int lock_count = - 1 ;
38
+ static INIT_ONCE initialized = INIT_ONCE_STATIC_INIT ;
39
+ static int lock_count = 0 ;
40
40
static HANDLE lock_event;
41
- static DWORD lock_owner = - 1 ;
41
+ static DWORD lock_owner = 0 ;
42
42
43
43
//
44
44
// Note that Microsoft's critical region code contains a race
@@ -51,48 +51,36 @@ static DWORD lock_owner = -1;
51
51
// and found them ~30 times slower than the critical region code.
52
52
//
53
53
54
+ static BOOL WINAPI initialize (PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context) {
55
+ lock_event = CreateEvent (NULL , false , true , NULL );
56
+ assert (lock_event != NULL , " unexpected return value from CreateEvent" );
57
+ return true ;
58
+ }
59
+
54
60
ThreadCritical::ThreadCritical () {
55
- DWORD current_thread = GetCurrentThreadId ( );
61
+ InitOnceExecuteOnce (&initialized, &initialize, NULL , NULL );
56
62
63
+ DWORD current_thread = GetCurrentThreadId ();
57
64
if (lock_owner != current_thread) {
58
65
// Grab the lock before doing anything.
59
- while (Atomic::cmpxchg (&lock_count, -1 , 0 ) != -1 ) {
60
- if (initialized) {
61
- DWORD ret = WaitForSingleObject (lock_event, INFINITE);
62
- assert (ret == WAIT_OBJECT_0, " unexpected return value from WaitForSingleObject" );
63
- }
64
- }
65
-
66
- // Make sure the event object is allocated.
67
- if (!initialized) {
68
- // Locking will not work correctly unless this is autoreset.
69
- lock_event = CreateEvent (NULL , false , false , NULL );
70
- initialized = true ;
71
- }
72
-
73
- assert (lock_owner == -1 , " Lock acquired illegally." );
66
+ DWORD ret = WaitForSingleObject (lock_event, INFINITE);
67
+ assert (ret == WAIT_OBJECT_0, " unexpected return value from WaitForSingleObject" );
74
68
lock_owner = current_thread;
75
- } else {
76
- // Atomicity isn't required. Bump the recursion count.
77
- lock_count++;
78
69
}
79
-
80
- assert (lock_owner == GetCurrentThreadId (), " Lock acquired illegally. " ) ;
70
+ // Atomicity isn't required. Bump the recursion count.
71
+ lock_count++ ;
81
72
}
82
73
83
74
ThreadCritical::~ThreadCritical () {
84
75
assert (lock_owner == GetCurrentThreadId (), " unlock attempt by wrong thread" );
85
76
assert (lock_count >= 0 , " Attempt to unlock when already unlocked" );
86
77
78
+ lock_count--;
87
79
if (lock_count == 0 ) {
88
80
// We're going to unlock
89
- lock_owner = -1 ;
90
- lock_count = -1 ;
81
+ lock_owner = 0 ;
91
82
// No lost wakeups, lock_event stays signaled until reset.
92
83
DWORD ret = SetEvent (lock_event);
93
84
assert (ret != 0 , " unexpected return value from SetEvent" );
94
- } else {
95
- // Just unwinding a recursive lock;
96
- lock_count--;
97
85
}
98
86
}
0 commit comments