/
mutex.cr
56 lines (47 loc) · 915 Bytes
/
mutex.cr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# A fiber-safe mutex.
#
# TODO: this isn't thread-safe yet.
class Mutex
@mutex_fiber : Fiber?
def initialize
@lock_count = 0
end
def lock
mutex_fiber = @mutex_fiber
current_fiber = Fiber.current
if !mutex_fiber
@mutex_fiber = current_fiber
elsif mutex_fiber == current_fiber
@lock_count += 1 # recursive lock
else
queue = @queue ||= Deque(Fiber).new
queue << current_fiber
Scheduler.reschedule
end
nil
end
def unlock
unless @mutex_fiber == Fiber.current
raise "Attempt to unlock a mutex which is not locked"
end
if @lock_count > 0
@lock_count -= 1
return
end
if fiber = @queue.try &.shift?
@mutex_fiber = fiber
Scheduler.enqueue fiber
else
@mutex_fiber = nil
end
nil
end
def synchronize
lock
begin
yield
ensure
unlock
end
end
end