dispatch_queue_rb 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +13 -0
- data/LICENSE +22 -0
- data/README.md +98 -0
- data/dispatch_queue_rb.gemspec +43 -0
- data/lib/dispatch_queue_rb.rb +32 -0
- data/lib/dispatch_queue_rb/concurrent_queue.rb +116 -0
- data/lib/dispatch_queue_rb/dispatch.rb +66 -0
- data/lib/dispatch_queue_rb/dispatch_group.rb +72 -0
- data/lib/dispatch_queue_rb/internal/condition_variable_pool.rb +33 -0
- data/lib/dispatch_queue_rb/internal/continuation.rb +41 -0
- data/lib/dispatch_queue_rb/internal/heap.rb +88 -0
- data/lib/dispatch_queue_rb/internal/thread_pool_queue.rb +127 -0
- data/lib/dispatch_queue_rb/internal/thread_queue.rb +62 -0
- data/lib/dispatch_queue_rb/internal/timer_pool.rb +71 -0
- data/lib/dispatch_queue_rb/mixins/dispatch_after_impl.rb +18 -0
- data/lib/dispatch_queue_rb/mixins/dispatch_sync_impl.rb +42 -0
- data/lib/dispatch_queue_rb/serial_queue.rb +77 -0
- data/lib/dispatch_queue_rb/version.rb +12 -0
- data/rakefile.rb +110 -0
- data/test/_test_env.rb +52 -0
- data/test/test_concurrent_queue.rb +90 -0
- data/test/test_condition_variable_pool.rb +41 -0
- data/test/test_continuation.rb +23 -0
- data/test/test_dispatch.rb +91 -0
- data/test/test_dispatch_group.rb +59 -0
- data/test/test_group_concurrent_queue.rb +75 -0
- data/test/test_group_serial_queue.rb +33 -0
- data/test/test_group_thread_pool_queue.rb +34 -0
- data/test/test_heap.rb +58 -0
- data/test/test_serial_queue.rb +77 -0
- data/test/test_thread_pool_queue.rb +63 -0
- data/test/test_thread_queue.rb +77 -0
- data/test/test_timer_pool.rb +124 -0
- data/test/test_version.rb +155 -0
- metadata +181 -0
@@ -0,0 +1,77 @@
|
|
1
|
+
# =============================================================================
|
2
|
+
#
|
3
|
+
# MODULE : test/test_thread_queue.rb
|
4
|
+
# PROJECT : DispatchQueue
|
5
|
+
# DESCRIPTION :
|
6
|
+
#
|
7
|
+
# Copyright (c) 2016, Marc-Antoine Argenton. All rights reserved.
|
8
|
+
# =============================================================================
|
9
|
+
|
10
|
+
|
11
|
+
require '_test_env.rb'
|
12
|
+
|
13
|
+
module DispatchQueue
|
14
|
+
describe ThreadQueue do
|
15
|
+
|
16
|
+
let( :task_count ) { 4 }
|
17
|
+
let( :log ) { [] }
|
18
|
+
let( :lock ) { Mutex.new }
|
19
|
+
let( :logger ) { Proc.new { |e, d| lock.synchronize { log << [e, d] } } }
|
20
|
+
subject { ThreadQueue.new }
|
21
|
+
|
22
|
+
it "can initialize a thread queue" do
|
23
|
+
subject.must_be_instance_of ThreadQueue
|
24
|
+
end
|
25
|
+
|
26
|
+
def task( task_id )
|
27
|
+
logger.call( :begin_task, { task_id:task_id, thread:Thread.current } )
|
28
|
+
sleep(0.001)
|
29
|
+
logger.call( :end_task, { task_id:task_id, thread:Thread.current } )
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "dispatch_async" do
|
33
|
+
it "executes tasks serially" do
|
34
|
+
(1..task_count).each { |i| subject.dispatch_async { task( i ) } }
|
35
|
+
subject.dispatch_barrier_sync {} # wait for all previous tasks to complete
|
36
|
+
|
37
|
+
log.map { |e,d| e }.must_equal [:begin_task, :end_task] * task_count
|
38
|
+
end
|
39
|
+
|
40
|
+
it "executes tasks in enqueue order" do
|
41
|
+
(1..task_count).each { |i| subject.dispatch_async { task( i ) } }
|
42
|
+
subject.dispatch_barrier_sync {} # wait for all previous tasks to complete
|
43
|
+
|
44
|
+
task_id_list = log.select { |e,d| e == :begin_task }.map { |e,d| d[:task_id] }
|
45
|
+
task_id_list.must_equal (1..task_count).to_a
|
46
|
+
end
|
47
|
+
|
48
|
+
it "resumes execution when new tasks are enqueues" do
|
49
|
+
(1..task_count).each { |i| subject.dispatch_async { task( "a#{i}".to_sym ) } }
|
50
|
+
subject.dispatch_barrier_sync {} # wait for all previous tasks to complete
|
51
|
+
sleep( 0.01 )
|
52
|
+
|
53
|
+
(1..task_count).each { |i| subject.dispatch_async { task( "b#{i}".to_sym ) } }
|
54
|
+
subject.dispatch_barrier_sync {} # wait for all previous tasks to complete
|
55
|
+
|
56
|
+
task_id_list = log.select { |e,d| e == :begin_task }.map { |e,d| d[:task_id] }
|
57
|
+
task_id_list.count.must_equal task_count*2, task_id_list
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "with multiple thread queues" do
|
62
|
+
let( :subject2 ) { ThreadQueue.new }
|
63
|
+
|
64
|
+
it "interleaves tasks from different queues" do
|
65
|
+
(1..task_count).each { |i| subject.dispatch_async { task( "a#{i}".to_sym ) } }
|
66
|
+
(1..task_count).each { |i| subject2.dispatch_async { task( "b#{i}".to_sym ) } }
|
67
|
+
subject.dispatch_barrier_sync {} # wait for all previous tasks to complete
|
68
|
+
subject2.dispatch_barrier_sync {} # wait for all previous tasks to complete
|
69
|
+
|
70
|
+
task_id_list = log.select { |e,d| e == :begin_task }.map { |e,d| d[:task_id] }
|
71
|
+
task_chunks = task_id_list.chunk { |e| e.to_s[0] }.map { |c, l| l }
|
72
|
+
task_chunks.count.must_be :>, 3, task_chunks
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
# =============================================================================
|
2
|
+
#
|
3
|
+
# MODULE : test/test_timer_pool.rb
|
4
|
+
# PROJECT : DispatchQueue
|
5
|
+
# DESCRIPTION :
|
6
|
+
#
|
7
|
+
# Copyright (c) 2016, Marc-Antoine Argenton. All rights reserved.
|
8
|
+
# =============================================================================
|
9
|
+
|
10
|
+
|
11
|
+
require '_test_env.rb'
|
12
|
+
|
13
|
+
module DispatchQueue
|
14
|
+
describe TimerPool do
|
15
|
+
let( :group ) { DispatchGroup.new }
|
16
|
+
let( :queue ) { SerialQueue.new }
|
17
|
+
let( :reference_time ) { Time.now + 0.005 }
|
18
|
+
let( :result ) { [] }
|
19
|
+
|
20
|
+
describe "default_pool" do
|
21
|
+
subject { TimerPool.default_pool }
|
22
|
+
|
23
|
+
it "is a valid TimerPool" do
|
24
|
+
subject.must_be_instance_of TimerPool
|
25
|
+
end
|
26
|
+
|
27
|
+
it "execute tasks after specified time" do
|
28
|
+
done = false
|
29
|
+
subject.dispatch_after( Time.now() + 0.001 ) { done = true }
|
30
|
+
done.must_equal false
|
31
|
+
sleep( 0.002 )
|
32
|
+
done.must_equal true
|
33
|
+
end
|
34
|
+
|
35
|
+
it "execute tasks after specified delay" do
|
36
|
+
done = false
|
37
|
+
subject.dispatch_after( 0.001 ) { done = true }
|
38
|
+
done.must_equal false
|
39
|
+
sleep( 0.002 )
|
40
|
+
done.must_equal true
|
41
|
+
end
|
42
|
+
|
43
|
+
it "execute tasks in eta order" do
|
44
|
+
subject.dispatch_after( reference_time + 0.001, target_queue:queue, group:group ) { result << 1 }
|
45
|
+
subject.dispatch_after( reference_time + 0.003, target_queue:queue, group:group ) { result << 3 }
|
46
|
+
subject.dispatch_after( reference_time + 0.004, target_queue:queue, group:group ) { result << 4 }
|
47
|
+
subject.dispatch_after( reference_time + 0.002, target_queue:queue, group:group ) { result << 2 }
|
48
|
+
group.wait()
|
49
|
+
result.must_equal [1,2,3,4]
|
50
|
+
end
|
51
|
+
end # describe "default_pool"
|
52
|
+
|
53
|
+
describe "SerialQueue.dispatch_after" do
|
54
|
+
subject { SerialQueue.new }
|
55
|
+
|
56
|
+
it "execute tasks in eta order" do
|
57
|
+
subject.dispatch_after( reference_time + 0.001, group:group ) { result << 1 }
|
58
|
+
subject.dispatch_after( reference_time + 0.003, group:group ) { result << 3 }
|
59
|
+
subject.dispatch_after( reference_time + 0.004, group:group ) { result << 4 }
|
60
|
+
subject.dispatch_after( reference_time + 0.002, group:group ) { result << 2 }
|
61
|
+
group.wait()
|
62
|
+
result.must_equal [1,2,3,4]
|
63
|
+
end
|
64
|
+
|
65
|
+
it "execute more tasks in eta order" do
|
66
|
+
count = 100
|
67
|
+
(1..count).to_a.shuffle.each do |i|
|
68
|
+
subject.dispatch_after( reference_time + i * 0.001, group:group ) { result << i }
|
69
|
+
end
|
70
|
+
group.wait()
|
71
|
+
result.must_equal (1..count).to_a
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "ThreadQueue.dispatch_after" do
|
76
|
+
subject { ThreadQueue.new }
|
77
|
+
|
78
|
+
it "execute tasks in eta order" do
|
79
|
+
subject.dispatch_after( reference_time + 0.001, group:group ) { result << 1 }
|
80
|
+
subject.dispatch_after( reference_time + 0.003, group:group ) { result << 3 }
|
81
|
+
subject.dispatch_after( reference_time + 0.004, group:group ) { result << 4 }
|
82
|
+
subject.dispatch_after( reference_time + 0.002, group:group ) { result << 2 }
|
83
|
+
group.wait()
|
84
|
+
result.must_equal [1,2,3,4]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
# NOTE: these test may fail occasionally since the target queues uses are
|
90
|
+
# concurrent and only guaranty that work will be scheduled in order.
|
91
|
+
# Execution might be out of order by the time the result is enqueued.
|
92
|
+
# Ordering relies exclusively on the delays introduced by dispatch_after(),
|
93
|
+
# which might not be nough.
|
94
|
+
# Also note that there is no synchronization on writing to result, so this
|
95
|
+
# will result in a race condition in multi-threaded ruby interpretter.
|
96
|
+
|
97
|
+
describe "ConcurrentQueue.dispatch_after" do
|
98
|
+
subject { ConcurrentQueue.new }
|
99
|
+
|
100
|
+
it "execute tasks in eta order" do
|
101
|
+
subject.dispatch_after( reference_time + 0.001, group:group ) { result << 1 }
|
102
|
+
subject.dispatch_after( reference_time + 0.003, group:group ) { result << 3 }
|
103
|
+
subject.dispatch_after( reference_time + 0.004, group:group ) { result << 4 }
|
104
|
+
subject.dispatch_after( reference_time + 0.002, group:group ) { result << 2 }
|
105
|
+
group.wait()
|
106
|
+
result.must_equal [1,2,3,4]
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe "ThreadPoolQueue.dispatch_after" do
|
111
|
+
subject { ThreadPoolQueue.new }
|
112
|
+
|
113
|
+
it "execute tasks in eta order" do
|
114
|
+
subject.dispatch_after( reference_time + 0.001, group:group ) { result << 1 }
|
115
|
+
subject.dispatch_after( reference_time + 0.003, group:group ) { result << 3 }
|
116
|
+
subject.dispatch_after( reference_time + 0.004, group:group ) { result << 4 }
|
117
|
+
subject.dispatch_after( reference_time + 0.002, group:group ) { result << 2 }
|
118
|
+
group.wait()
|
119
|
+
result.must_equal [1,2,3,4]
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
end # describe TimerPool
|
124
|
+
end # module DispatchQueue
|
@@ -0,0 +1,155 @@
|
|
1
|
+
# =============================================================================
|
2
|
+
#
|
3
|
+
# MODULE : test/test_version.rb
|
4
|
+
# PROJECT : DispatchQueueRb
|
5
|
+
# DESCRIPTION :
|
6
|
+
#
|
7
|
+
# Copyright (c) 2016, Marc-Antoine Argenton. All rights reserved.
|
8
|
+
# =============================================================================
|
9
|
+
|
10
|
+
|
11
|
+
require '_test_env.rb'
|
12
|
+
|
13
|
+
module DispatchQueue
|
14
|
+
describe VERSION do
|
15
|
+
|
16
|
+
subject { VERSION }
|
17
|
+
|
18
|
+
it "is definied as a string" do
|
19
|
+
subject.must_be_instance_of String
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
class Expectation
|
26
|
+
def initialize( target, action=nil, *args, **opts, &block )
|
27
|
+
@target = target
|
28
|
+
@action = action
|
29
|
+
@args = args
|
30
|
+
@opts = opts
|
31
|
+
@block = block
|
32
|
+
end
|
33
|
+
|
34
|
+
def to
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_be
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
def method_missing( name, *args, **opts, &block )
|
43
|
+
# puts "method_missing( #{name.inspect} )"
|
44
|
+
Expectation.new( self, name, *args, **opts, &block )
|
45
|
+
end
|
46
|
+
|
47
|
+
def inspect
|
48
|
+
"#{@target.inspect}#{_inspect_action()}"
|
49
|
+
end
|
50
|
+
|
51
|
+
def ==( arg )
|
52
|
+
Expectation.new( self, :==, arg )
|
53
|
+
end
|
54
|
+
|
55
|
+
def !=( arg )
|
56
|
+
Expectation.new( self, :!=, arg )
|
57
|
+
end
|
58
|
+
|
59
|
+
def =~( arg, within:nil )
|
60
|
+
Expectation.new( self, :=~, arg, within:within )
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
private
|
65
|
+
def _inspect_action()
|
66
|
+
return "" if @action.nil?
|
67
|
+
return " #{@action} #{@args[0]}" if _is_operator_action()
|
68
|
+
return ".#{@action}" if @args.empty? && @opts.empty?
|
69
|
+
return ".#{@action}(#{_inspect_action_args()})"
|
70
|
+
end
|
71
|
+
|
72
|
+
def _is_operator_action()
|
73
|
+
@args.count == 1 && [:==, :!=, :=~, :<=>, :<, :>, :<=, :>=, :<<, :>>].include?( @action )
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
def _inspect_action_args()
|
78
|
+
return "" if @args.empty? && @opts.empty?
|
79
|
+
return " " + ( @args.map { |a| a.inspect } +
|
80
|
+
@opts.map { |k,v| "#{k}: #{v.inspect}" } ).join( ', ' ) + " "
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
# expect( subject ) < 10
|
86
|
+
# expect( subject ).start_with?( "aaa" )
|
87
|
+
# expect( subject ).to.start_with?( "aaa" )
|
88
|
+
# expect( subject ).to.include?( "aaa" )
|
89
|
+
# expect( subject ).count < 10
|
90
|
+
# expect( subject ).count.to_equal( 10 ).within( 20 )
|
91
|
+
# expect( subject ).count.to_equal( 10 ).within( 20 )
|
92
|
+
|
93
|
+
describe Expectation do
|
94
|
+
|
95
|
+
def expect( value )
|
96
|
+
Expectation.new( value )
|
97
|
+
end
|
98
|
+
|
99
|
+
it "can create a new expectation" do
|
100
|
+
expectation = expect( :value )
|
101
|
+
expectation.must_be_instance_of Expectation
|
102
|
+
end
|
103
|
+
|
104
|
+
it "inspects to the wrapped value" do
|
105
|
+
expectation = expect( :value )
|
106
|
+
expectation.inspect.must_equal ":value"
|
107
|
+
end
|
108
|
+
|
109
|
+
it "inspects with method call" do
|
110
|
+
expectation = expect( :value ).something()
|
111
|
+
expectation.inspect.must_equal ":value.something"
|
112
|
+
end
|
113
|
+
|
114
|
+
it "inspects with method call and arguments" do
|
115
|
+
expectation = expect( :value ).something(:aaa, :bbb)
|
116
|
+
expectation.inspect.must_equal ":value.something( :aaa, :bbb )"
|
117
|
+
end
|
118
|
+
|
119
|
+
it "inspects with method call and optional arguments" do
|
120
|
+
expectation = expect( :value ).something(:aaa, bbb:1)
|
121
|
+
expectation.inspect.must_equal ":value.something( :aaa, bbb: 1 )"
|
122
|
+
end
|
123
|
+
|
124
|
+
it "inspects with chained method calls" do
|
125
|
+
expectation = expect( :value ).something(:aaa, :bbb).something_else( aaa:1, bbb:2 )
|
126
|
+
expectation.inspect.must_equal ":value.something( :aaa, :bbb ).something_else( aaa: 1, bbb: 2 )"
|
127
|
+
end
|
128
|
+
|
129
|
+
it "inspects with chained method calls and binary operators" do
|
130
|
+
expectation = expect( :value ).something(:aaa, :bbb) < 10
|
131
|
+
expectation.inspect.must_equal ":value.something( :aaa, :bbb ) < 10"
|
132
|
+
end
|
133
|
+
|
134
|
+
it "inspects with chained method calls and binary operators 2" do
|
135
|
+
expectation = expect( :value ).something(:aaa, :bbb).to_be << 10
|
136
|
+
expectation.inspect.must_equal ":value.something( :aaa, :bbb ) << 10"
|
137
|
+
end
|
138
|
+
|
139
|
+
it "inspects with chained method calls and binary operators 3" do
|
140
|
+
expectation = expect( [1,2,3] ).size == 10
|
141
|
+
expectation.inspect.must_equal "[1, 2, 3].size == 10"
|
142
|
+
end
|
143
|
+
|
144
|
+
it "inspects with chained method calls and binary operators 4" do
|
145
|
+
expectation = expect( [1,2,3] ).size != 10
|
146
|
+
expectation.inspect.must_equal "[1, 2, 3].size != 10"
|
147
|
+
end
|
148
|
+
|
149
|
+
it "inspects with chained method calls and binary operators 4" do
|
150
|
+
expectation = expect( [1,2,3] ).size.=~( 10, within:1 )
|
151
|
+
expectation.inspect.must_equal "[1, 2, 3].size =~ 10"
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
155
|
+
end
|
metadata
ADDED
@@ -0,0 +1,181 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dispatch_queue_rb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Marc-Antoine Argenton
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-12-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.7'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: watch
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.1'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.1'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rr
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.1'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.1'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: minitest
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '5.3'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ~>
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '5.3'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: minitest-reporters
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ~>
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.1'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ~>
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.1'
|
97
|
+
description: DispatchQueueRb is a pure ruby implementation of Grand Central Dispatch
|
98
|
+
concurrency primitives. It implements serial and concurrent queues, with synchronous,
|
99
|
+
asynchronous, barrier and delayed dispatch methods. All queues dispatch methods
|
100
|
+
support an optional dispatch groups to synchronize on completion of a group of tasks.
|
101
|
+
It also provides a thread pool based concurrent queue, scaled to the number of available
|
102
|
+
cpu cores, and used by default to schedule the actual work.
|
103
|
+
email:
|
104
|
+
- maargenton.dev@gmail.com
|
105
|
+
executables: []
|
106
|
+
extensions: []
|
107
|
+
extra_rdoc_files: []
|
108
|
+
files:
|
109
|
+
- Gemfile
|
110
|
+
- LICENSE
|
111
|
+
- README.md
|
112
|
+
- dispatch_queue_rb.gemspec
|
113
|
+
- lib/dispatch_queue_rb.rb
|
114
|
+
- lib/dispatch_queue_rb/concurrent_queue.rb
|
115
|
+
- lib/dispatch_queue_rb/dispatch.rb
|
116
|
+
- lib/dispatch_queue_rb/dispatch_group.rb
|
117
|
+
- lib/dispatch_queue_rb/internal/condition_variable_pool.rb
|
118
|
+
- lib/dispatch_queue_rb/internal/continuation.rb
|
119
|
+
- lib/dispatch_queue_rb/internal/heap.rb
|
120
|
+
- lib/dispatch_queue_rb/internal/thread_pool_queue.rb
|
121
|
+
- lib/dispatch_queue_rb/internal/thread_queue.rb
|
122
|
+
- lib/dispatch_queue_rb/internal/timer_pool.rb
|
123
|
+
- lib/dispatch_queue_rb/mixins/dispatch_after_impl.rb
|
124
|
+
- lib/dispatch_queue_rb/mixins/dispatch_sync_impl.rb
|
125
|
+
- lib/dispatch_queue_rb/serial_queue.rb
|
126
|
+
- lib/dispatch_queue_rb/version.rb
|
127
|
+
- rakefile.rb
|
128
|
+
- test/_test_env.rb
|
129
|
+
- test/test_concurrent_queue.rb
|
130
|
+
- test/test_condition_variable_pool.rb
|
131
|
+
- test/test_continuation.rb
|
132
|
+
- test/test_dispatch.rb
|
133
|
+
- test/test_dispatch_group.rb
|
134
|
+
- test/test_group_concurrent_queue.rb
|
135
|
+
- test/test_group_serial_queue.rb
|
136
|
+
- test/test_group_thread_pool_queue.rb
|
137
|
+
- test/test_heap.rb
|
138
|
+
- test/test_serial_queue.rb
|
139
|
+
- test/test_thread_pool_queue.rb
|
140
|
+
- test/test_thread_queue.rb
|
141
|
+
- test/test_timer_pool.rb
|
142
|
+
- test/test_version.rb
|
143
|
+
homepage: https://github.com/marcus999/dispatch_queue_rb
|
144
|
+
licenses: []
|
145
|
+
metadata: {}
|
146
|
+
post_install_message:
|
147
|
+
rdoc_options: []
|
148
|
+
require_paths:
|
149
|
+
- lib
|
150
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
151
|
+
requirements:
|
152
|
+
- - '>='
|
153
|
+
- !ruby/object:Gem::Version
|
154
|
+
version: '0'
|
155
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - '>='
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
requirements: []
|
161
|
+
rubyforge_project:
|
162
|
+
rubygems_version: 2.4.5
|
163
|
+
signing_key:
|
164
|
+
specification_version: 4
|
165
|
+
summary: Pure ruby implementation of Grand Central Dispatch concurrency primitives.
|
166
|
+
test_files:
|
167
|
+
- test/_test_env.rb
|
168
|
+
- test/test_concurrent_queue.rb
|
169
|
+
- test/test_condition_variable_pool.rb
|
170
|
+
- test/test_continuation.rb
|
171
|
+
- test/test_dispatch.rb
|
172
|
+
- test/test_dispatch_group.rb
|
173
|
+
- test/test_group_concurrent_queue.rb
|
174
|
+
- test/test_group_serial_queue.rb
|
175
|
+
- test/test_group_thread_pool_queue.rb
|
176
|
+
- test/test_heap.rb
|
177
|
+
- test/test_serial_queue.rb
|
178
|
+
- test/test_thread_pool_queue.rb
|
179
|
+
- test/test_thread_queue.rb
|
180
|
+
- test/test_timer_pool.rb
|
181
|
+
- test/test_version.rb
|