thread_executor 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d5bde7f16838ab701a01d2ba70657239959a54a0
4
+ data.tar.gz: 2e809fb597ad664d6db40dd4d4eb9b4a4c83a857
5
+ SHA512:
6
+ metadata.gz: 809c32bc10a3e9eef3fa86bcf714ecfdb5b3222e262f4e14b07835e7107267ff0f5fb2aca372cb6892cbdca8e7bdd67e94e95a007dc4050d6f1083f0edcb90c3
7
+ data.tar.gz: 99c0696e26e27722809e10c09c1d438006d4c3a9ad93da0ddf2153473dd38e453e1f6713e2717f4d8e1ac6d687fe3c2db4b68c87796756588199f6c35e7949f1
data/Changelog ADDED
@@ -0,0 +1,8 @@
1
+ 2015-04-21 Sam Baskinger <basking2@yahoo.com>
2
+ * Extracting executor into independent package.
3
+
4
+ 2015-03-18 Sam Baskinger <basking2@yahoo.com>
5
+ * Adding concurrency with thread pool implementation.
6
+
7
+ Copyright 2014, 2015 Sam Baskinger <basking2@yahoo.com>
8
+
data/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # thread_executor
2
+ Ruby 2 thread executor library.
3
+
@@ -0,0 +1,40 @@
1
+ # Copyright (c) 2015, Sam Baskinger <basking2@yahoo.com>
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+ #
7
+ # * Redistributions of source code must retain the above copyright notice, this
8
+ # list of conditions and the following disclaimer.
9
+ #
10
+ # * Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ #
14
+ # * Neither the name of thread_executor nor the names of its
15
+ # contributors may be used to endorse or promote products derived from
16
+ # this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+
29
+ require 'thread_executor/future'
30
+ require 'thread_executor/promise'
31
+ require 'thread_executor/executor'
32
+ require 'thread_executor/processor'
33
+
34
+ # A future/promise thread executor library.
35
+ #
36
+ # Start by checking out Executor.
37
+ #
38
+ module ThreadExecutor
39
+ end
40
+
@@ -0,0 +1,107 @@
1
+ # Copyright (c) 2015, Sam Baskinger <basking2@yahoo.com>
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+ #
7
+ # * Redistributions of source code must retain the above copyright notice, this
8
+ # list of conditions and the following disclaimer.
9
+ #
10
+ # * Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ #
14
+ # * Neither the name of thread_executor nor the names of its
15
+ # contributors may be used to endorse or promote products derived from
16
+ # this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+
29
+ #
30
+ module ThreadExecutor
31
+
32
+ # A threaded executor.
33
+ #
34
+ # Procs can be given to this executor and are
35
+ # executed according to the availability of threads.
36
+ #
37
+ # = Use
38
+ #
39
+ # # Make an executor.
40
+ # executor = ThreadExecutor::Executor.new 10
41
+ #
42
+ # begin
43
+ #
44
+ # # Dispatch 100 jobs across the 10 threads.
45
+ # futures = 100.times.map { executor.call { do_long_running_work } }
46
+ #
47
+ # # Collect the results.
48
+ # results = futures.map { |future| future.value }
49
+ #
50
+ # ensure
51
+ # # Clean up the threads.
52
+ # executor.finish
53
+ # end
54
+ #
55
+ class Executor
56
+
57
+ # Build a new executor with +size+ Processor objects.
58
+ # The default size is 2.
59
+ #
60
+ # Each Processor contains a work queue and a running ruby Thread
61
+ # which will process the elements in the work queue.
62
+ #
63
+ # This Executor will insert elements into the work queue.
64
+ #
65
+ # Use of the Executor is not thread safe. If more than one thread
66
+ # submit work to Processor objects through this Executor, the
67
+ # Executor must be protected by a lock of some sort.
68
+ def initialize size=2
69
+ @processors = []
70
+
71
+ size.times do
72
+ @processors << Processor.new
73
+ end
74
+ end
75
+
76
+ # Enqueues the block in a processor queue with the fewest tasks.
77
+ #
78
+ # Returns a future for the result.
79
+ def call(&t)
80
+ min_processor = @processors[0]
81
+ min_size = min_processor.size
82
+ @processors.each do |p|
83
+ min_size2 = p.size
84
+ if min_size > min_size2
85
+ min_processor = p
86
+ min_size = min_size2
87
+ end
88
+ end
89
+
90
+ # Forward the user's block to the processor.
91
+ min_processor.call &t
92
+ end
93
+
94
+ # Sum of all queue depths.
95
+ def size
96
+ @processors.reduce(0) {|x,y| x + y.size}
97
+ end
98
+
99
+ # Shutdown and join all worker threads.
100
+ def finish
101
+ @processors.each do |p|
102
+ p.finish
103
+ end
104
+ end
105
+ end
106
+
107
+ end # module Sake
@@ -0,0 +1,51 @@
1
+ # Copyright (c) 2015, Sam Baskinger <basking2@yahoo.com>
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+ #
7
+ # * Redistributions of source code must retain the above copyright notice, this
8
+ # list of conditions and the following disclaimer.
9
+ #
10
+ # * Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ #
14
+ # * Neither the name of thread_executor nor the names of its
15
+ # contributors may be used to endorse or promote products derived from
16
+ # this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+
29
+ module ThreadExecutor
30
+
31
+ # Proxies access to a Future object.
32
+ #
33
+ # This protects the user from doing the "wrong thing"
34
+ # with a Promise.
35
+ class Future
36
+ def initialize(promise)
37
+ @promise = promise
38
+ end
39
+
40
+ # Block until a value is ready.
41
+ #
42
+ # If an Exception was raised instead of producing a value
43
+ # it is rethrown.
44
+ #
45
+ # This call is proxied to Promise#value.
46
+ def value
47
+ @promise.value
48
+ end
49
+ end
50
+
51
+ end # module ThreadExecutor
@@ -0,0 +1,103 @@
1
+ # Copyright (c) 2015, Sam Baskinger <basking2@yahoo.com>
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+ #
7
+ # * Redistributions of source code must retain the above copyright notice, this
8
+ # list of conditions and the following disclaimer.
9
+ #
10
+ # * Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ #
14
+ # * Neither the name of thread_executor nor the names of its
15
+ # contributors may be used to endorse or promote products derived from
16
+ # this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+
29
+ require 'thread'
30
+
31
+ module ThreadExecutor
32
+
33
+ # A processor is a Queue feeding a Thread.
34
+ class Processor
35
+
36
+ # Create Processor.
37
+ #
38
+ # This will create a new Queue and start a new ruby Thread.
39
+ #
40
+ # The created thread will block until work is inserted n the Queue
41
+ # using #call.
42
+ #
43
+ # To avoid leaking active threads you must call #finish to stop
44
+ # processing and join the Thread behind this object.
45
+ # Once this object is finished it may not be used again. It
46
+ # should be discarded.
47
+ #
48
+ # Typically the user should never create or use this class, but
49
+ # use an Executor, though there is nothing wrong in using this
50
+ # directly..
51
+ def initialize
52
+ @q = Queue.new
53
+ @t = Thread.new do
54
+ while true do
55
+ promise, task = @q.deq
56
+
57
+ # This is how we shut down the thread cleanly.
58
+ break if promise.nil? && task.nil?
59
+
60
+ begin
61
+ promise.value = task.call
62
+ rescue Exception => e
63
+ promise.exception = e
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ # Signal that the worker thread should exit.
70
+ #
71
+ # More precisely, this enqueues a stop request
72
+ # into the work queue, which, when encountered,
73
+ # causes the worker thread to cleanly exit and
74
+ # take no more work.
75
+ def shutdown
76
+ @q.enq [nil, nil]
77
+ end
78
+
79
+ # Adds a task, creates a Promise and returns a Future.
80
+ def call(&t)
81
+ p = Promise.new
82
+ @q.enq [ p, t ]
83
+ p.future
84
+ end
85
+
86
+ # Return the size of the work queue.
87
+ def size
88
+ @q.size
89
+ end
90
+
91
+ # Call #shutdown and join the thread.
92
+ #
93
+ # This will block until the thread is joined.
94
+ #
95
+ # When this returns this object is unusable and should
96
+ # be discarded.
97
+ def finish
98
+ shutdown
99
+ @t.join
100
+ end
101
+ end
102
+
103
+ end # module ThreadExecutor
@@ -0,0 +1,89 @@
1
+ # Copyright (c) 2015, Sam Baskinger <basking2@yahoo.com>
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+ #
7
+ # * Redistributions of source code must retain the above copyright notice, this
8
+ # list of conditions and the following disclaimer.
9
+ #
10
+ # * Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ #
14
+ # * Neither the name of thread_executor nor the names of its
15
+ # contributors may be used to endorse or promote products derived from
16
+ # this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+
29
+ require 'thread_executor/future'
30
+
31
+ module ThreadExecutor
32
+
33
+ # A Promise is a container for a value that a Processor will compute.
34
+ #
35
+ # It contains locking objects to ensure that the value is communicated
36
+ # safely from the Processor 's Thread to user's Thread.
37
+ #
38
+ # A user typically never touches this object directly but
39
+ # examines the Future.
40
+ class Promise
41
+ attr_reader :value, :exception, :future
42
+
43
+ def initialize()
44
+ @value = nil
45
+ @exception = nil
46
+ @ready = false
47
+ @lock = Mutex.new
48
+ @cond = ConditionVariable.new
49
+ @no_result = true
50
+ @future = Future.new(self)
51
+ end
52
+
53
+ # Wait until this Promise is fulfilled and return the value
54
+ # If an exception was raised, it is reraised here.
55
+ def value
56
+ @lock.synchronize do
57
+
58
+ while ! @ready do
59
+ @cond.wait @lock
60
+ end
61
+
62
+ raise @exception if @exception
63
+
64
+ @value
65
+ end
66
+ end
67
+
68
+ def ready?
69
+ @ready
70
+ end
71
+
72
+ def value= v
73
+ @lock.synchronize do
74
+ @value = v
75
+ @ready = true
76
+ @cond.signal
77
+ end
78
+ end
79
+
80
+ def exception= e
81
+ @lock.synchronize do
82
+ @exception = e
83
+ @ready = true
84
+ @cond.signal
85
+ end
86
+ end
87
+ end
88
+
89
+ end # module ThreadExecutor
metadata ADDED
@@ -0,0 +1,53 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: thread_executor
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Sam Baskinger
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-04-22 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: |2
14
+ Thread executor library.
15
+ email: basking2@yahoo.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files:
19
+ - README.md
20
+ - Changelog
21
+ files:
22
+ - Changelog
23
+ - README.md
24
+ - lib/thread_executor.rb
25
+ - lib/thread_executor/executor.rb
26
+ - lib/thread_executor/future.rb
27
+ - lib/thread_executor/processor.rb
28
+ - lib/thread_executor/promise.rb
29
+ homepage: https://github.com/basking2/thread_executor/
30
+ licenses:
31
+ - BSD
32
+ metadata: {}
33
+ post_install_message:
34
+ rdoc_options: []
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: 2.0.0
42
+ required_rubygems_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ requirements: []
48
+ rubyforge_project:
49
+ rubygems_version: 2.2.2
50
+ signing_key:
51
+ specification_version: 4
52
+ summary: Thread executor library.
53
+ test_files: []