lowdown 0.2.0 → 0.3.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.
@@ -1,188 +0,0 @@
1
- require "thread"
2
-
3
- module Lowdown
4
- # A collection of internal threading related helpers.
5
- #
6
- module Threading
7
- # This class performs jobs on a private thread, provides lifecycle callbacks, and sends exceptions onto its parent
8
- # thread.
9
- #
10
- class Consumer
11
- # @param [Thread::Queue] queue
12
- # a queue instance. Provide a `Thread::SizedQueue` if you want queue of a max size.
13
- #
14
- # @param [Thread] parent_thread
15
- # the thread to send exceptions to.
16
- #
17
- def initialize(queue: Thread::Queue.new, parent_thread: Thread.current)
18
- @queue, @parent_thread = queue, parent_thread
19
- @thread = Thread.new(&method(:main))
20
- end
21
-
22
- # Schedules a job to be performed.
23
- #
24
- # @return [void]
25
- #
26
- def enqueue(&job)
27
- queue << job
28
- end
29
-
30
- # Kills the private thread.
31
- #
32
- # @return [void]
33
- #
34
- def kill
35
- thread.kill
36
- end
37
-
38
- # @return [Boolean]
39
- # whether or not the private thread is still alive.
40
- #
41
- def alive?
42
- thread.alive?
43
- end
44
-
45
- # @return [Boolean]
46
- # whether or not there are any scheduled jobs left in the queue.
47
- #
48
- def empty?
49
- queue.empty?
50
- end
51
-
52
- protected
53
-
54
- # @return [Thread]
55
- # the private thread.
56
- #
57
- attr_reader :thread
58
-
59
- # @return [Thread]
60
- # the thread to send exceptions to.
61
- #
62
- attr_reader :parent_thread
63
-
64
- # @return [Thread::Queue]
65
- # the jobs queue.
66
- #
67
- attr_reader :queue
68
-
69
- # This represents the full lifecycle of the consumer thread. It performs the individual events, catches uncaught
70
- # exceptions and sends those to the parent thread, and performs cleanup.
71
- #
72
- # Subclasses should override the individual events.
73
- #
74
- # @note This method is ran on the private thread.
75
- #
76
- # @return [void]
77
- #
78
- def main
79
- pre_runloop
80
- runloop
81
- rescue Exception => exception
82
- parent_thread.raise(exception)
83
- ensure
84
- post_runloop
85
- end
86
-
87
- # Ran _before_ any jobs are performed.
88
- #
89
- # @note (see #main)
90
- #
91
- # @return [void]
92
- #
93
- def pre_runloop
94
- end
95
-
96
- # The loop that performs scheduled jobs.
97
- #
98
- # @note (see #main)
99
- #
100
- # @return [void]
101
- #
102
- def runloop
103
- loop { perform_job(non_block: false) }
104
- end
105
-
106
- # Ran when the thread is killed or an uncaught exception occurred.
107
- #
108
- # This kills the consumer thread, which means that any cleanup you need to perform should be done *before* calling
109
- # this `super` implementation.
110
- #
111
- # @note (see #main)
112
- #
113
- # @return [void]
114
- #
115
- def post_runloop
116
- thread.kill
117
- end
118
-
119
- # @param [Boolean] non_block
120
- # whether or not the thread should be halted if there are no jobs to perform.
121
- #
122
- # @param [Array<Object>] arguments
123
- # arguments that should be passed to the invoked job.
124
- #
125
- # @return [void]
126
- #
127
- def perform_job(non_block:, arguments: nil)
128
- queue.pop(non_block).call(*arguments)
129
- rescue ThreadError
130
- end
131
- end
132
-
133
- # A simple thread-safe counter.
134
- #
135
- class Counter
136
- # @param [Integer] value
137
- # the initial count.
138
- #
139
- def initialize(value = 0)
140
- @value = value
141
- @mutex = Mutex.new
142
- end
143
-
144
- # @return [Integer]
145
- # the current count.
146
- #
147
- def value
148
- value = nil
149
- @mutex.synchronize { value = @value }
150
- value
151
- end
152
-
153
- # @return [Boolean]
154
- # whether or not the current count is zero.
155
- #
156
- def zero?
157
- value.zero?
158
- end
159
-
160
- # @param [Integer] value
161
- # the new count.
162
- #
163
- # @return [Integer]
164
- # the input value.
165
- #
166
- def value=(value)
167
- @mutex.synchronize { @value = value }
168
- value
169
- end
170
-
171
- # Increments the current count.
172
- #
173
- # @return [void]
174
- #
175
- def increment!
176
- @mutex.synchronize { @value += 1 }
177
- end
178
-
179
- # Decrements the current count.
180
- #
181
- # @return [void]
182
- #
183
- def decrement!
184
- @mutex.synchronize { @value -= 1 }
185
- end
186
- end
187
- end
188
- end