| ... | @@ -61,31 +61,57 @@ pub const Mutex = switch(builtin.os) { | ... | @@ -61,31 +61,57 @@ pub const Mutex = switch(builtin.os) { |
| 61 | } | 61 | } |
| 62 | }, | 62 | }, |
| 63 | builtin.Os.windows => struct { | 63 | builtin.Os.windows => struct { |
| 64 | lock: ?*windows.RTL_CRITICAL_SECTION, | 64 | |
| | 65 | lock: ?windows.CRITICAL_SECTION, |
| | 66 | init_once: windows.PINIT_ONCE, |
| 65 | | 67 | |
| 66 | pub const Held = struct { | 68 | pub const Held = struct { |
| 67 | mutex: *Mutex, | 69 | mutex: *Mutex, |
| 68 | | 70 | |
| 69 | pub fn release(self: Held) void { | 71 | pub fn release(self: Held) void { |
| 70 | windows.LeaveCriticalSection(self.mutex.lock); | 72 | if (self.mutex.lock) |*lock| { |
| | 73 | windows.LeaveCriticalSection(lock); |
| | 74 | } |
| 71 | } | 75 | } |
| 72 | }; | 76 | }; |
| 73 | | 77 | |
| 74 | pub fn init() Mutex { | 78 | pub fn init() Mutex { |
| 75 | var lock: ?*windows.RTL_CRITICAL_SECTION = null; | 79 | return Mutex { |
| 76 | windows.InitializeCriticalSection(lock); | 80 | .lock = null, |
| 77 | return Mutex { .lock = lock }; | 81 | .init_once = undefined, |
| | 82 | }; |
| | 83 | } |
| | 84 | |
| | 85 | extern fn initCriticalSection(InitOnce: *windows.PINIT_ONCE, Parameter: ?windows.PVOID, Context: ?*windows.PVOID) windows.BOOL { |
| | 86 | if (Context) |ctx| { |
| | 87 | var mutex = @ptrCast(*?windows.CRITICAL_SECTION, ctx); |
| | 88 | if (mutex.* == null) { |
| | 89 | var lock: windows.CRITICAL_SECTION = undefined; |
| | 90 | windows.InitializeCriticalSection(&lock); |
| | 91 | mutex.* = lock; |
| | 92 | } |
| | 93 | return windows.TRUE; |
| | 94 | } |
| | 95 | return windows.FALSE; |
| 78 | } | 96 | } |
| 79 | | 97 | |
| 80 | pub fn deinit(self: *Mutex) void { | 98 | pub fn deinit(self: *Mutex) void { |
| 81 | if (self.lock != null) { | 99 | if (self.lock) |*lock| { |
| 82 | windows.DeleteCriticalSection(self.lock); | 100 | windows.DeleteCriticalSection(lock); |
| 83 | self.lock = null; | | |
| 84 | } | 101 | } |
| 85 | } | 102 | } |
| 86 | | 103 | |
| 87 | pub fn acquire(self: *Mutex) Held { | 104 | pub fn acquire(self: *Mutex) Held { |
| 88 | windows.EnterCriticalSection(self.lock); | 105 | if (self.lock) |*lock| { |
| | 106 | windows.EnterCriticalSection(lock); |
| | 107 | } else { |
| | 108 | if (windows.InitOnceExecuteOnce(&self.init_once, initCriticalSection, null, @ptrCast(?*windows.PVOID, self)) == windows.TRUE) { |
| | 109 | windows.EnterCriticalSection(&self.lock.?); |
| | 110 | } else { |
| | 111 | @panic("unable to initialize Mutex"); |
| | 112 | } |
| | 113 | } |
| | 114 | |
| 89 | return Held { .mutex = self }; | 115 | return Held { .mutex = self }; |
| 90 | } | 116 | } |
| 91 | }, | 117 | }, |
| ... | @@ -116,7 +142,7 @@ pub const Mutex = switch(builtin.os) { | ... | @@ -116,7 +142,7 @@ pub const Mutex = switch(builtin.os) { |
| 116 | }, | 142 | }, |
| 117 | }; | 143 | }; |
| 118 | | 144 | |
| 119 | const Context = struct { | 145 | const TestContext = struct { |
| 120 | mutex: *Mutex, | 146 | mutex: *Mutex, |
| 121 | data: i128, | 147 | data: i128, |
| 122 | | 148 | |
| ... | @@ -136,7 +162,7 @@ test "std.Mutex" { | ... | @@ -136,7 +162,7 @@ test "std.Mutex" { |
| 136 | var mutex = Mutex.init(); | 162 | var mutex = Mutex.init(); |
| 137 | defer mutex.deinit(); | 163 | defer mutex.deinit(); |
| 138 | | 164 | |
| 139 | var context = Context{ | 165 | var context = TestContext{ |
| 140 | .mutex = &mutex, | 166 | .mutex = &mutex, |
| 141 | .data = 0, | 167 | .data = 0, |
| 142 | }; | 168 | }; |
| ... | @@ -149,12 +175,12 @@ test "std.Mutex" { | ... | @@ -149,12 +175,12 @@ test "std.Mutex" { |
| 149 | for (threads) |t| | 175 | for (threads) |t| |
| 150 | t.wait(); | 176 | t.wait(); |
| 151 | | 177 | |
| 152 | std.debug.assertOrPanic(context.data == thread_count * Context.incr_count); | 178 | std.debug.assertOrPanic(context.data == thread_count * TestContext.incr_count); |
| 153 | } | 179 | } |
| 154 | | 180 | |
| 155 | fn worker(ctx: *Context) void { | 181 | fn worker(ctx: *TestContext) void { |
| 156 | var i: usize = 0; | 182 | var i: usize = 0; |
| 157 | while (i != Context.incr_count) : (i += 1) { | 183 | while (i != TestContext.incr_count) : (i += 1) { |
| 158 | const held = ctx.mutex.acquire(); | 184 | const held = ctx.mutex.acquire(); |
| 159 | defer held.release(); | 185 | defer held.release(); |
| 160 | | 186 | |