concurrent-ruby-edge 0.2.0.pre2 → 0.2.0.pre3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +7 -5
- data/lib/concurrent/channel.rb +272 -6
- data/lib/concurrent/channel/buffer.rb +9 -0
- data/lib/concurrent/channel/buffer/base.rb +197 -0
- data/lib/concurrent/channel/buffer/buffered.rb +127 -0
- data/lib/concurrent/channel/buffer/dropping.rb +53 -0
- data/lib/concurrent/channel/buffer/sliding.rb +54 -0
- data/lib/concurrent/channel/buffer/ticker.rb +80 -0
- data/lib/concurrent/channel/buffer/timer.rb +78 -0
- data/lib/concurrent/channel/buffer/unbuffered.rb +151 -0
- data/lib/concurrent/channel/selector.rb +70 -0
- data/lib/concurrent/channel/selector/after_clause.rb +27 -0
- data/lib/concurrent/channel/selector/default_clause.rb +19 -0
- data/lib/concurrent/channel/selector/error_clause.rb +21 -0
- data/lib/concurrent/channel/selector/put_clause.rb +26 -0
- data/lib/concurrent/channel/selector/take_clause.rb +24 -0
- data/lib/concurrent/channel/tick.rb +55 -0
- data/lib/concurrent/edge/future.rb +23 -41
- data/lib/concurrent/edge/lock_free_linked_set.rb +2 -1
- metadata +20 -11
- data/lib/concurrent/channel/blocking_ring_buffer.rb +0 -82
- data/lib/concurrent/channel/buffered_channel.rb +0 -89
- data/lib/concurrent/channel/channel.rb +0 -19
- data/lib/concurrent/channel/ring_buffer.rb +0 -65
- data/lib/concurrent/channel/unbuffered_channel.rb +0 -39
- data/lib/concurrent/channel/waitable_list.rb +0 -48
@@ -1,89 +0,0 @@
|
|
1
|
-
require 'concurrent/synchronization'
|
2
|
-
require 'concurrent/channel/waitable_list'
|
3
|
-
|
4
|
-
module Concurrent
|
5
|
-
module Channel
|
6
|
-
|
7
|
-
# @api Channel
|
8
|
-
# @!macro edge_warning
|
9
|
-
class BufferedChannel < Synchronization::LockableObject
|
10
|
-
|
11
|
-
def initialize(size)
|
12
|
-
super()
|
13
|
-
synchronize { ns_initialize(size) }
|
14
|
-
end
|
15
|
-
|
16
|
-
def probe_set_size
|
17
|
-
@probe_set.size # TODO (pitr 12-Sep-2015): unsafe?
|
18
|
-
end
|
19
|
-
|
20
|
-
def buffer_queue_size
|
21
|
-
synchronize { @buffer.count }
|
22
|
-
end
|
23
|
-
|
24
|
-
def push(value)
|
25
|
-
until set_probe_or_ns_push_into_buffer(value)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def pop
|
30
|
-
probe = Channel::Probe.new
|
31
|
-
select(probe)
|
32
|
-
probe.value
|
33
|
-
end
|
34
|
-
|
35
|
-
def select(probe)
|
36
|
-
synchronize do
|
37
|
-
if @buffer.empty?
|
38
|
-
@probe_set.put(probe)
|
39
|
-
true
|
40
|
-
else
|
41
|
-
ns_shift_buffer if probe.try_set([ns_peek_buffer, self])
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def remove_probe(probe)
|
47
|
-
@probe_set.delete(probe)
|
48
|
-
end
|
49
|
-
|
50
|
-
protected
|
51
|
-
|
52
|
-
def ns_initialize(size)
|
53
|
-
@probe_set = WaitableList.new
|
54
|
-
@buffer = RingBuffer.new(size)
|
55
|
-
end
|
56
|
-
|
57
|
-
private
|
58
|
-
|
59
|
-
def ns_push_into_buffer(value)
|
60
|
-
ns_wait while @buffer.full?
|
61
|
-
@buffer.offer value
|
62
|
-
ns_broadcast
|
63
|
-
end
|
64
|
-
|
65
|
-
def ns_peek_buffer
|
66
|
-
ns_wait while @buffer.empty?
|
67
|
-
@buffer.peek
|
68
|
-
end
|
69
|
-
|
70
|
-
def ns_shift_buffer
|
71
|
-
ns_wait while @buffer.empty?
|
72
|
-
result = @buffer.poll
|
73
|
-
ns_broadcast
|
74
|
-
result
|
75
|
-
end
|
76
|
-
|
77
|
-
def set_probe_or_ns_push_into_buffer(value)
|
78
|
-
synchronize do
|
79
|
-
if @probe_set.empty?
|
80
|
-
ns_push_into_buffer(value)
|
81
|
-
true
|
82
|
-
else
|
83
|
-
@probe_set.take.try_set([value, self])
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
require 'concurrent/ivar'
|
2
|
-
|
3
|
-
module Concurrent
|
4
|
-
|
5
|
-
# @api Channel
|
6
|
-
# @!macro edge_warning
|
7
|
-
module Channel
|
8
|
-
|
9
|
-
Probe = IVar
|
10
|
-
|
11
|
-
def self.select(*channels)
|
12
|
-
probe = Probe.new
|
13
|
-
channels.each { |channel| channel.select(probe) }
|
14
|
-
result = probe.value
|
15
|
-
channels.each { |channel| channel.remove_probe(probe) }
|
16
|
-
result
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
@@ -1,65 +0,0 @@
|
|
1
|
-
module Concurrent
|
2
|
-
module Channel
|
3
|
-
|
4
|
-
# non-thread safe buffer
|
5
|
-
#
|
6
|
-
# @api Channel
|
7
|
-
# @!macro edge_warning
|
8
|
-
class RingBuffer
|
9
|
-
|
10
|
-
def initialize(capacity)
|
11
|
-
@buffer = ::Array.new(capacity)
|
12
|
-
@first = @last = 0
|
13
|
-
@count = 0
|
14
|
-
end
|
15
|
-
|
16
|
-
|
17
|
-
# @return [Integer] the capacity of the buffer
|
18
|
-
def capacity
|
19
|
-
@buffer.size
|
20
|
-
end
|
21
|
-
|
22
|
-
# @return [Integer] the number of elements currently in the buffer
|
23
|
-
def count
|
24
|
-
@count
|
25
|
-
end
|
26
|
-
|
27
|
-
# @return [Boolean] true if buffer is empty, false otherwise
|
28
|
-
def empty?
|
29
|
-
@count == 0
|
30
|
-
end
|
31
|
-
|
32
|
-
# @return [Boolean] true if buffer is full, false otherwise
|
33
|
-
def full?
|
34
|
-
@count == capacity
|
35
|
-
end
|
36
|
-
|
37
|
-
# @param [Object] value
|
38
|
-
# @return [Boolean] true if value has been inserted, false otherwise
|
39
|
-
def offer(value)
|
40
|
-
return false if full?
|
41
|
-
|
42
|
-
@buffer[@last] = value
|
43
|
-
@last = (@last + 1) % @buffer.size
|
44
|
-
@count += 1
|
45
|
-
true
|
46
|
-
end
|
47
|
-
|
48
|
-
# @return [Object] the first available value and removes it from the buffer. If buffer is empty returns nil
|
49
|
-
def poll
|
50
|
-
result = @buffer[@first]
|
51
|
-
@buffer[@first] = nil
|
52
|
-
@first = (@first + 1) % @buffer.size
|
53
|
-
@count -= 1
|
54
|
-
result
|
55
|
-
end
|
56
|
-
|
57
|
-
# @return [Object] the first available value and without removing it from
|
58
|
-
# the buffer. If buffer is empty returns nil
|
59
|
-
def peek
|
60
|
-
@buffer[@first]
|
61
|
-
end
|
62
|
-
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
@@ -1,39 +0,0 @@
|
|
1
|
-
require 'concurrent/channel/waitable_list'
|
2
|
-
|
3
|
-
module Concurrent
|
4
|
-
module Channel
|
5
|
-
|
6
|
-
# @api Channel
|
7
|
-
# @!macro edge_warning
|
8
|
-
class UnbufferedChannel
|
9
|
-
|
10
|
-
def initialize
|
11
|
-
@probe_set = WaitableList.new
|
12
|
-
end
|
13
|
-
|
14
|
-
def probe_set_size
|
15
|
-
@probe_set.size
|
16
|
-
end
|
17
|
-
|
18
|
-
def push(value)
|
19
|
-
until @probe_set.take.try_set([value, self])
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def pop
|
24
|
-
probe = Channel::Probe.new
|
25
|
-
select(probe)
|
26
|
-
probe.value
|
27
|
-
end
|
28
|
-
|
29
|
-
def select(probe)
|
30
|
-
@probe_set.put(probe)
|
31
|
-
end
|
32
|
-
|
33
|
-
def remove_probe(probe)
|
34
|
-
@probe_set.delete(probe)
|
35
|
-
end
|
36
|
-
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
@@ -1,48 +0,0 @@
|
|
1
|
-
require 'concurrent/synchronization'
|
2
|
-
|
3
|
-
module Concurrent
|
4
|
-
module Channel
|
5
|
-
|
6
|
-
# @api Channel
|
7
|
-
# @!macro edge_warning
|
8
|
-
class WaitableList < Synchronization::LockableObject
|
9
|
-
|
10
|
-
def initialize
|
11
|
-
super()
|
12
|
-
synchronize { ns_initialize }
|
13
|
-
end
|
14
|
-
|
15
|
-
def size
|
16
|
-
synchronize { @list.size }
|
17
|
-
end
|
18
|
-
|
19
|
-
def empty?
|
20
|
-
synchronize { @list.empty? }
|
21
|
-
end
|
22
|
-
|
23
|
-
def put(value)
|
24
|
-
synchronize do
|
25
|
-
@list << value
|
26
|
-
ns_signal
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def delete(value)
|
31
|
-
synchronize { @list.delete(value) }
|
32
|
-
end
|
33
|
-
|
34
|
-
def take
|
35
|
-
synchronize do
|
36
|
-
ns_wait_until { !@list.empty? }
|
37
|
-
@list.shift
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
protected
|
42
|
-
|
43
|
-
def ns_initialize
|
44
|
-
@list = []
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|