blob: ccf84c9d1b8a1edb565bbb8cee6c0aae1c9e29f4 (
plain)
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
require 'thread'
require 'concurrent/synchronization/lockable_object'
module Concurrent
# Old school kernel-style event reminiscent of Win32 programming in C++.
#
# When an `Event` is created it is in the `unset` state. Threads can choose to
# `#wait` on the event, blocking until released by another thread. When one
# thread wants to alert all blocking threads it calls the `#set` method which
# will then wake up all listeners. Once an `Event` has been set it remains set.
# New threads calling `#wait` will return immediately. An `Event` may be
# `#reset` at any time once it has been set.
#
# @see http://msdn.microsoft.com/en-us/library/windows/desktop/ms682655.aspx
# @example
# event = Concurrent::Event.new
#
# t1 = Thread.new do
# puts "t1 is waiting"
# event.wait(1)
# puts "event occurred"
# end
#
# t2 = Thread.new do
# puts "t2 calling set"
# event.set
# end
#
# [t1, t2].each(&:join)
#
# # prints:
# # t1 is waiting
# # t2 calling set
# # event occurred
class Event < Synchronization::LockableObject
# Creates a new `Event` in the unset state. Threads calling `#wait` on the
# `Event` will block.
def initialize
super
synchronize { ns_initialize }
end
# Is the object in the set state?
#
# @return [Boolean] indicating whether or not the `Event` has been set
def set?
synchronize { @set }
end
# Trigger the event, setting the state to `set` and releasing all threads
# waiting on the event. Has no effect if the `Event` has already been set.
#
# @return [Boolean] should always return `true`
def set
synchronize { ns_set }
end
def try?
synchronize { @set ? false : ns_set }
end
# Reset a previously set event back to the `unset` state.
# Has no effect if the `Event` has not yet been set.
#
# @return [Boolean] should always return `true`
def reset
synchronize do
if @set
@set = false
@iteration +=1
end
true
end
end
# Wait a given number of seconds for the `Event` to be set by another
# thread. Will wait forever when no `timeout` value is given. Returns
# immediately if the `Event` has already been set.
#
# @return [Boolean] true if the `Event` was set before timeout else false
def wait(timeout = nil)
synchronize do
unless @set
iteration = @iteration
ns_wait_until(timeout) { iteration < @iteration || @set }
else
true
end
end
end
protected
def ns_set
unless @set
@set = true
ns_broadcast
end
true
end
def ns_initialize
@set = false
@iteration = 0
end
end
end
|