Skip to content

Commit 7487cb5

Browse files
committed
Windows: go back to TlsAlloc with custom destructor array
1 parent 19f631b commit 7487cb5

File tree

2 files changed

+24
-7
lines changed

2 files changed

+24
-7
lines changed

src/crystal/system/thread.cr

+4
Original file line numberDiff line numberDiff line change
@@ -220,12 +220,16 @@ class Thread
220220
rescue ex
221221
@exception = ex
222222
ensure
223+
run_destructors
223224
Thread.threads.delete(self)
224225
Fiber.inactive(fiber)
225226
detach { system_close }
226227
end
227228
end
228229

230+
protected def run_destructors : Nil
231+
end
232+
229233
protected def name=(@name : String)
230234
self.system_name = name
231235
end
+20-7
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,43 @@
11
require "c/fibersapi"
22

33
class Thread
4+
protected class_getter(destructors : Array({LibC::DWORD, Proc(Void*, Nil)})) do
5+
Array({LibC::DWORD, Proc(Void*, Nil)}).new
6+
end
7+
48
struct Local(T)
59
@key : LibC::DWORD
610

711
def initialize
812
{% raise "T must be a Reference or Pointer" unless T < Reference || T < Pointer %}
9-
@key = LibC.FlsAlloc(nil)
10-
raise RuntimeError.from_winerror("FlsAlloc: out of indexes") if @key == LibC::TLS_OUT_OF_INDEXES
13+
@key = LibC.TlsAlloc()
14+
raise RuntimeError.from_winerror("TlsAlloc: out of indexes") if @key == LibC::TLS_OUT_OF_INDEXES
1115
end
1216

1317
def initialize(&destructor : Proc(T, Nil))
1418
{% raise "T must be a Reference or Pointer" unless T < Reference || T < Pointer %}
15-
@key = LibC.FlsAlloc(destructor.unsafe_as(Proc(Void*, Nil)))
16-
raise RuntimeError.from_winerror("FlsAlloc: out of indexes") if @key == LibC::TLS_OUT_OF_INDEXES
19+
@key = LibC.TlsAlloc()
20+
raise RuntimeError.from_winerror("TlsAlloc: out of indexes") if @key == LibC::TLS_OUT_OF_INDEXES
21+
Thread.destructors << {@key, destructor.unsafe_as(Proc(Void*, Nil))}
1722
end
1823

1924
def get? : T?
20-
pointer = LibC.FlsGetValue(@key)
25+
pointer = LibC.TlsGetValue(@key)
2126
pointer.as(T) if pointer
2227
end
2328

2429
def set(value : T) : T
25-
ret = LibC.FlsSetValue(@key, value.as(Void*))
26-
raise RuntimeError.from_winerror("FlsSetValue") if ret == 0
30+
ret = LibC.TlsSetValue(@key, value.as(Void*))
31+
raise RuntimeError.from_winerror("TlsSetValue") if ret == 0
2732
value
2833
end
2934
end
35+
36+
private def run_destructors
37+
@@destructors.try(&.each do |(key, destructor)|
38+
if pointer = LibC.TlsGetValue(key)
39+
destructor.call(pointer) # rescue nil
40+
end
41+
end)
42+
end
3043
end

0 commit comments

Comments
 (0)