Skip to content

Commit

Permalink
Added Thread.current, and store current fiber in Thread
Browse files Browse the repository at this point in the history
Ary Borenszweig committed Jun 21, 2016

Verified

This commit was signed with the committer’s verified signature.
jhass Jonne Haß
1 parent 4b30588 commit bab00a9
Showing 5 changed files with 35 additions and 33 deletions.
15 changes: 1 addition & 14 deletions spec/std/thread_spec.cr
Original file line number Diff line number Diff line change
@@ -4,27 +4,14 @@ describe Thread do
it "allows passing an argumentless fun to execute" do
a = 0
thread = Thread.new { a = 1; 10 }
thread.join.should eq(10)
thread.join
a.should eq(1)
end

it "allows passing a fun with an argument to execute" do
a = 0
thread = Thread.new(3) { |i| a += i; 20 }
thread.join.should eq(20)
a.should eq(3)
end

it "raises inside thread and gets it on join" do
thread = Thread.new { raise "OH NO" }
expect_raises Exception, "OH NO" do
thread.join
end
end

it "gets a non-nilable value from join" do
thread = Thread.new { 1 }
value = thread.join
(value + 2).should eq(3)
end
end
10 changes: 4 additions & 6 deletions src/fiber.cr
Original file line number Diff line number Diff line change
@@ -160,7 +160,7 @@ class Fiber
end

def resume
current, @@current = @@current, self
current, Thread.current.current_fiber = Thread.current.current_fiber, self
LibGC.stackbottom = @stack_bottom
Fiber.switch_stacks(pointerof(current.@stack_top), pointerof(@stack_top))
end
@@ -194,12 +194,10 @@ class Fiber
@@root
end

# TODO: Boehm GC doesn't scan thread local vars, so we can't use it yet
# @[ThreadLocal]
@@current : Fiber = root
Thread.current.current_fiber = root

def self.current : self
@@current
Thread.current.current_fiber
end

@@prev_push_other_roots = LibGC.get_push_other_roots
@@ -210,7 +208,7 @@ class Fiber

fiber = @@first_fiber
while fiber
fiber.push_gc_roots unless fiber == @@current
fiber.push_gc_roots unless fiber == Thread.current.current_fiber
fiber = fiber.next_fiber
end
end
39 changes: 28 additions & 11 deletions src/thread.cr
Original file line number Diff line number Diff line change
@@ -2,22 +2,22 @@ require "c/pthread"
require "./thread/*"

# :nodoc:
class Thread(T, R)
class Thread
# Don't use this class, it is used internally by the event scheduler.
# Use spawn and channels instead.

def self.new(&func : -> R)
Thread(Nil, R).new(nil) { func.call }
end

@th : LibC::PthreadT?
@exception : Exception?
@detached = false

property current_fiber

def initialize(&@func : ->)
@current_fiber = uninitialized Fiber
@@threads << self

def initialize(@arg : T, &@func : T -> R)
@detached = false
@ret = uninitialized R
ret = LibGC.pthread_create(out th, nil, ->(data) {
(data.as(Thread(T, R))).start
(data.as(Thread)).start
}, self.as(Void*))
@th = th

@@ -26,6 +26,12 @@ class Thread(T, R)
end
end

def initialize
@current_fiber = uninitialized Fiber
@func = ->{}
@@threads << self
end

def finalize
LibGC.pthread_detach(@th.not_nil!) unless @detached
end
@@ -39,15 +45,26 @@ class Thread(T, R)
if exception = @exception
raise exception
end
end

# All threads, so the GC can see them (GC doesn't scan thread locals)
@@threads = Set(Thread).new

@[ThreadLocal]
@@current = new

@ret
def self.current
@@current
end

protected def start
@@current = self
begin
@ret = @func.call(@arg)
@func.call
rescue ex
@exception = ex
ensure
@@threads.delete(self)
end
end
end
2 changes: 1 addition & 1 deletion src/thread/condition_variable.cr
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
require "c/pthread"

# :nodoc:
class Thread(T, R)
class Thread
# :nodoc:
class ConditionVariable
def initialize
2 changes: 1 addition & 1 deletion src/thread/mutex.cr
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
require "c/pthread"

# :nodoc:
class Thread(T, R)
class Thread
# :nodoc:
class Mutex
def initialize

0 comments on commit bab00a9

Please sign in to comment.