rubysl-monitor 2.0.0 → 2.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7362242f7582618baaf408e9c8eb46b1bc5c85e2
4
- data.tar.gz: bb1f3e3984987a4143417554aa7526e59b76d54e
3
+ metadata.gz: 58131016ac8f1dad3c38a2e60589dabbf189495e
4
+ data.tar.gz: ef3fd837b8753599ae54ec05b174ba8045bfbf8f
5
5
  SHA512:
6
- metadata.gz: 9f7a6cca87b357fc057709c176dfb7c7104d6fca0e6c3b446c4768c6045933111f88aa54184726f75467d8b9d9c8a0df00b8dc4eacb41e833c2419046e98b1fa
7
- data.tar.gz: 94bc9048a65ea57066ef16059b37aa07b1d973ba795da46693acdfe0d43fffc2b033b8ebfe6c0f23bc36d6105ad38c6271c94214bd5bee4f9df6ae3507e21aa2
6
+ metadata.gz: ca0bfdd83ac029c99a1806a2b7b8591341846dfe63fe998f8f35642771735f60da0a076c2e29ac42e276d4e6952ed12e2cdbb427027edd850255275c001684dd
7
+ data.tar.gz: ce649beccca122344d9387a09203ca412ec40a6b6fb73f9124a04cba9d91b42284e1f4cf91c55544a94fe3043a6a9543e0e9c5327a2ea8b50cdcc4a86cdfd5d7
@@ -1,7 +1,14 @@
1
1
  language: ruby
2
2
  env:
3
3
  - RUBYLIB=lib
4
- script: bundle exec mspec
4
+ - RUBYLIB=
5
+ script: mspec spec
5
6
  rvm:
6
- - 1.9.3
7
- - rbx-nightly-19mode
7
+ - 2.0.0
8
+ - rbx-2.2.1
9
+ matrix:
10
+ exclude:
11
+ - rvm: 2.0.0
12
+ env: RUBYLIB=lib
13
+ - rvm: rbx-2.2.1
14
+ env: RUBYLIB=
@@ -0,0 +1,56 @@
1
+ Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.jp>.
2
+ You can redistribute it and/or modify it under either the terms of the
3
+ 2-clause BSDL (see the file BSDL), or the conditions below:
4
+
5
+ 1. You may make and give away verbatim copies of the source form of the
6
+ software without restriction, provided that you duplicate all of the
7
+ original copyright notices and associated disclaimers.
8
+
9
+ 2. You may modify your copy of the software in any way, provided that
10
+ you do at least ONE of the following:
11
+
12
+ a) place your modifications in the Public Domain or otherwise
13
+ make them Freely Available, such as by posting said
14
+ modifications to Usenet or an equivalent medium, or by allowing
15
+ the author to include your modifications in the software.
16
+
17
+ b) use the modified software only within your corporation or
18
+ organization.
19
+
20
+ c) give non-standard binaries non-standard names, with
21
+ instructions on where to get the original software distribution.
22
+
23
+ d) make other distribution arrangements with the author.
24
+
25
+ 3. You may distribute the software in object code or binary form,
26
+ provided that you do at least ONE of the following:
27
+
28
+ a) distribute the binaries and library files of the software,
29
+ together with instructions (in the manual page or equivalent)
30
+ on where to get the original distribution.
31
+
32
+ b) accompany the distribution with the machine-readable source of
33
+ the software.
34
+
35
+ c) give non-standard binaries non-standard names, with
36
+ instructions on where to get the original software distribution.
37
+
38
+ d) make other distribution arrangements with the author.
39
+
40
+ 4. You may modify and include the part of the software into any other
41
+ software (possibly commercial). But some files in the distribution
42
+ are not written by the author, so that they are not under these terms.
43
+
44
+ For the list of those files and their copying conditions, see the
45
+ file LEGAL.
46
+
47
+ 5. The scripts and library files supplied as input to or produced as
48
+ output from the software do not automatically fall under the
49
+ copyright of the software, but belong to whomever generated them,
50
+ and may be sold commercially, and may be aggregated with this
51
+ software.
52
+
53
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
54
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
55
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
56
+ PURPOSE.
@@ -1 +1,300 @@
1
- require "rubysl/monitor"
1
+ # = monitor.rb
2
+ #
3
+ # Copyright (C) 2001 Shugo Maeda <shugo@ruby-lang.org>
4
+ #
5
+ # This library is distributed under the terms of the Ruby license.
6
+ # You can freely distribute/modify this library.
7
+ #
8
+
9
+ require 'thread'
10
+
11
+ #
12
+ # In concurrent programming, a monitor is an object or module intended to be
13
+ # used safely by more than one thread. The defining characteristic of a
14
+ # monitor is that its methods are executed with mutual exclusion. That is, at
15
+ # each point in time, at most one thread may be executing any of its methods.
16
+ # This mutual exclusion greatly simplifies reasoning about the implementation
17
+ # of monitors compared to reasoning about parallel code that updates a data
18
+ # structure.
19
+ #
20
+ # You can read more about the general principles on the Wikipedia page for
21
+ # Monitors[http://en.wikipedia.org/wiki/Monitor_%28synchronization%29]
22
+ #
23
+ # == Examples
24
+ #
25
+ # === Simple object.extend
26
+ #
27
+ # require 'monitor.rb'
28
+ #
29
+ # buf = []
30
+ # buf.extend(MonitorMixin)
31
+ # empty_cond = buf.new_cond
32
+ #
33
+ # # consumer
34
+ # Thread.start do
35
+ # loop do
36
+ # buf.synchronize do
37
+ # empty_cond.wait_while { buf.empty? }
38
+ # print buf.shift
39
+ # end
40
+ # end
41
+ # end
42
+ #
43
+ # # producer
44
+ # while line = ARGF.gets
45
+ # buf.synchronize do
46
+ # buf.push(line)
47
+ # empty_cond.signal
48
+ # end
49
+ # end
50
+ #
51
+ # The consumer thread waits for the producer thread to push a line to buf
52
+ # while <tt>buf.empty?</tt>. The producer thread (main thread) reads a
53
+ # line from ARGF and pushes it into buf then calls <tt>empty_cond.signal</tt>
54
+ # to notify the consumer thread of new data.
55
+ #
56
+ # === Simple Class include
57
+ #
58
+ # require 'monitor'
59
+ #
60
+ # class SynchronizedArray < Array
61
+ #
62
+ # include MonitorMixin
63
+ #
64
+ # def initialize(*args)
65
+ # super(*args)
66
+ # end
67
+ #
68
+ # alias :old_shift :shift
69
+ # alias :old_unshift :unshift
70
+ #
71
+ # def shift(n=1)
72
+ # self.synchronize do
73
+ # self.old_shift(n)
74
+ # end
75
+ # end
76
+ #
77
+ # def unshift(item)
78
+ # self.synchronize do
79
+ # self.old_unshift(item)
80
+ # end
81
+ # end
82
+ #
83
+ # # other methods ...
84
+ # end
85
+ #
86
+ # +SynchronizedArray+ implements an Array with synchronized access to items.
87
+ # This Class is implemented as subclass of Array which includes the
88
+ # MonitorMixin module.
89
+ #
90
+ module MonitorMixin
91
+ #
92
+ # FIXME: This isn't documented in Nutshell.
93
+ #
94
+ # Since MonitorMixin.new_cond returns a ConditionVariable, and the example
95
+ # above calls while_wait and signal, this class should be documented.
96
+ #
97
+ class ConditionVariable
98
+ class Timeout < Exception; end
99
+
100
+ #
101
+ # Releases the lock held in the associated monitor and waits; reacquires the lock on wakeup.
102
+ #
103
+ # If +timeout+ is given, this method returns after +timeout+ seconds passed,
104
+ # even if no other thread doesn't signal.
105
+ #
106
+ def wait(timeout = nil)
107
+ @monitor.__send__(:mon_check_owner)
108
+ count = @monitor.__send__(:mon_exit_for_cond)
109
+ begin
110
+ @cond.wait(@monitor.instance_variable_get(:@mon_mutex), timeout)
111
+ return true
112
+ ensure
113
+ @monitor.__send__(:mon_enter_for_cond, count)
114
+ end
115
+ end
116
+
117
+ #
118
+ # Calls wait repeatedly while the given block yields a truthy value.
119
+ #
120
+ def wait_while
121
+ while yield
122
+ wait
123
+ end
124
+ end
125
+
126
+ #
127
+ # Calls wait repeatedly until the given block yields a truthy value.
128
+ #
129
+ def wait_until
130
+ until yield
131
+ wait
132
+ end
133
+ end
134
+
135
+ #
136
+ # Wakes up the first thread in line waiting for this lock.
137
+ #
138
+ def signal
139
+ @monitor.__send__(:mon_check_owner)
140
+ @cond.signal
141
+ end
142
+
143
+ #
144
+ # Wakes up all threads waiting for this lock.
145
+ #
146
+ def broadcast
147
+ @monitor.__send__(:mon_check_owner)
148
+ @cond.broadcast
149
+ end
150
+
151
+ private
152
+
153
+ def initialize(monitor)
154
+ @monitor = monitor
155
+ @cond = ::ConditionVariable.new
156
+ end
157
+ end
158
+
159
+ def self.extend_object(obj)
160
+ super(obj)
161
+ obj.__send__(:mon_initialize)
162
+ end
163
+
164
+ #
165
+ # Attempts to enter exclusive section. Returns +false+ if lock fails.
166
+ #
167
+ def mon_try_enter
168
+ if @mon_owner != Thread.current
169
+ unless @mon_mutex.try_lock
170
+ return false
171
+ end
172
+ @mon_owner = Thread.current
173
+ end
174
+ @mon_count += 1
175
+ return true
176
+ end
177
+ # For backward compatibility
178
+ alias try_mon_enter mon_try_enter
179
+
180
+ #
181
+ # Enters exclusive section.
182
+ #
183
+ def mon_enter
184
+ if @mon_owner != Thread.current
185
+ @mon_mutex.lock
186
+ @mon_owner = Thread.current
187
+ end
188
+ @mon_count += 1
189
+ end
190
+
191
+ #
192
+ # Leaves exclusive section.
193
+ #
194
+ def mon_exit
195
+ mon_check_owner
196
+ @mon_count -=1
197
+ if @mon_count == 0
198
+ @mon_owner = nil
199
+ @mon_mutex.unlock
200
+ end
201
+ end
202
+
203
+ #
204
+ # Enters exclusive section and executes the block. Leaves the exclusive
205
+ # section automatically when the block exits. See example under
206
+ # +MonitorMixin+.
207
+ #
208
+ def mon_synchronize
209
+ mon_enter
210
+ begin
211
+ yield
212
+ ensure
213
+ mon_exit
214
+ end
215
+ end
216
+ alias synchronize mon_synchronize
217
+
218
+ #
219
+ # Creates a new MonitorMixin::ConditionVariable associated with the
220
+ # receiver.
221
+ #
222
+ def new_cond
223
+ return ConditionVariable.new(self)
224
+ end
225
+
226
+ private
227
+
228
+ # Use <tt>extend MonitorMixin</tt> or <tt>include MonitorMixin</tt> instead
229
+ # of this constructor. Have look at the examples above to understand how to
230
+ # use this module.
231
+ def initialize(*args)
232
+ super
233
+ mon_initialize
234
+ end
235
+
236
+ # Initializes the MonitorMixin after being included in a class or when an
237
+ # object has been extended with the MonitorMixin
238
+ def mon_initialize
239
+ @mon_owner = nil
240
+ @mon_count = 0
241
+ @mon_mutex = Mutex.new
242
+ end
243
+
244
+ def mon_check_owner
245
+ if @mon_owner != Thread.current
246
+ raise ThreadError, "current thread not owner"
247
+ end
248
+ end
249
+
250
+ def mon_enter_for_cond(count)
251
+ @mon_owner = Thread.current
252
+ @mon_count = count
253
+ end
254
+
255
+ def mon_exit_for_cond
256
+ count = @mon_count
257
+ @mon_owner = nil
258
+ @mon_count = 0
259
+ return count
260
+ end
261
+ end
262
+
263
+ # Use the Monitor class when you want to have a lock object for blocks with
264
+ # mutual exclusion.
265
+ #
266
+ # require 'monitor'
267
+ #
268
+ # lock = Monitor.new
269
+ # lock.synchronize do
270
+ # # exclusive access
271
+ # end
272
+ #
273
+ class Monitor
274
+ include MonitorMixin
275
+ alias try_enter try_mon_enter
276
+ alias enter mon_enter
277
+ alias exit mon_exit
278
+ end
279
+
280
+
281
+ # Documentation comments:
282
+ # - All documentation comes from Nutshell.
283
+ # - MonitorMixin.new_cond appears in the example, but is not documented in
284
+ # Nutshell.
285
+ # - All the internals (internal modules Accessible and Initializable, class
286
+ # ConditionVariable) appear in RDoc. It might be good to hide them, by
287
+ # making them private, or marking them :nodoc:, etc.
288
+ # - RDoc doesn't recognise aliases, so we have mon_synchronize documented, but
289
+ # not synchronize.
290
+ # - mon_owner is in Nutshell, but appears as an accessor in a separate module
291
+ # here, so is hard/impossible to RDoc. Some other useful accessors
292
+ # (mon_count and some queue stuff) are also in this module, and don't appear
293
+ # directly in the RDoc output.
294
+ # - in short, it may be worth changing the code layout in this file to make the
295
+ # documentation easier
296
+
297
+ # Local variables:
298
+ # mode: Ruby
299
+ # tab-width: 8
300
+ # End:
@@ -1,2 +1,3 @@
1
1
  require "rubysl/monitor/version"
2
2
  require "rubysl/monitor/monitor"
3
+ require "monitor"
@@ -1,5 +1,5 @@
1
1
  module RubySL
2
2
  module Monitor
3
- VERSION = "2.0.0"
3
+ VERSION = "2.1"
4
4
  end
5
5
  end
@@ -21,4 +21,5 @@ Gem::Specification.new do |spec|
21
21
  spec.add_development_dependency "bundler", "~> 1.3"
22
22
  spec.add_development_dependency "rake", "~> 10.0"
23
23
  spec.add_development_dependency "mspec", "~> 1.5"
24
+ spec.add_development_dependency "rubysl-prettyprint", "~> 2.0"
24
25
  end
metadata CHANGED
@@ -1,57 +1,71 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubysl-monitor
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: '2.1'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Shirai
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-08-17 00:00:00.000000000 Z
11
+ date: 2017-10-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.3'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.3'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '10.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: mspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ~>
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
47
  version: '1.5'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ~>
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '1.5'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubysl-prettyprint
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.0'
55
69
  description: Ruby standard library Monitor.
56
70
  email:
57
71
  - brixen@gmail.com
@@ -59,15 +73,15 @@ executables: []
59
73
  extensions: []
60
74
  extra_rdoc_files: []
61
75
  files:
62
- - .gitignore
63
- - .travis.yml
76
+ - ".gitignore"
77
+ - ".travis.yml"
64
78
  - Gemfile
65
79
  - LICENSE
80
+ - MRI_LICENSE
66
81
  - README.md
67
82
  - Rakefile
68
83
  - lib/monitor.rb
69
84
  - lib/rubysl/monitor.rb
70
- - lib/rubysl/monitor/monitor.rb
71
85
  - lib/rubysl/monitor/version.rb
72
86
  - rubysl-monitor.gemspec
73
87
  homepage: https://github.com/rubysl/rubysl-monitor
@@ -80,17 +94,17 @@ require_paths:
80
94
  - lib
81
95
  required_ruby_version: !ruby/object:Gem::Requirement
82
96
  requirements:
83
- - - ~>
97
+ - - "~>"
84
98
  - !ruby/object:Gem::Version
85
99
  version: '2.0'
86
100
  required_rubygems_version: !ruby/object:Gem::Requirement
87
101
  requirements:
88
- - - '>='
102
+ - - ">="
89
103
  - !ruby/object:Gem::Version
90
104
  version: '0'
91
105
  requirements: []
92
106
  rubyforge_project:
93
- rubygems_version: 2.0.7
107
+ rubygems_version: 2.5.1
94
108
  signing_key:
95
109
  specification_version: 4
96
110
  summary: Ruby standard library Monitor.
@@ -1,300 +0,0 @@
1
- # = monitor.rb
2
- #
3
- # Copyright (C) 2001 Shugo Maeda <shugo@ruby-lang.org>
4
- #
5
- # This library is distributed under the terms of the Ruby license.
6
- # You can freely distribute/modify this library.
7
- #
8
-
9
- require 'thread'
10
-
11
- #
12
- # In concurrent programming, a monitor is an object or module intended to be
13
- # used safely by more than one thread. The defining characteristic of a
14
- # monitor is that its methods are executed with mutual exclusion. That is, at
15
- # each point in time, at most one thread may be executing any of its methods.
16
- # This mutual exclusion greatly simplifies reasoning about the implementation
17
- # of monitors compared to reasoning about parallel code that updates a data
18
- # structure.
19
- #
20
- # You can read more about the general principles on the Wikipedia page for
21
- # Monitors[http://en.wikipedia.org/wiki/Monitor_%28synchronization%29]
22
- #
23
- # == Examples
24
- #
25
- # === Simple object.extend
26
- #
27
- # require 'monitor.rb'
28
- #
29
- # buf = []
30
- # buf.extend(MonitorMixin)
31
- # empty_cond = buf.new_cond
32
- #
33
- # # consumer
34
- # Thread.start do
35
- # loop do
36
- # buf.synchronize do
37
- # empty_cond.wait_while { buf.empty? }
38
- # print buf.shift
39
- # end
40
- # end
41
- # end
42
- #
43
- # # producer
44
- # while line = ARGF.gets
45
- # buf.synchronize do
46
- # buf.push(line)
47
- # empty_cond.signal
48
- # end
49
- # end
50
- #
51
- # The consumer thread waits for the producer thread to push a line to buf
52
- # while <tt>buf.empty?</tt>. The producer thread (main thread) reads a
53
- # line from ARGF and pushes it into buf then calls <tt>empty_cond.signal</tt>
54
- # to notify the consumer thread of new data.
55
- #
56
- # === Simple Class include
57
- #
58
- # require 'monitor'
59
- #
60
- # class SynchronizedArray < Array
61
- #
62
- # include MonitorMixin
63
- #
64
- # def initialize(*args)
65
- # super(*args)
66
- # end
67
- #
68
- # alias :old_shift :shift
69
- # alias :old_unshift :unshift
70
- #
71
- # def shift(n=1)
72
- # self.synchronize do
73
- # self.old_shift(n)
74
- # end
75
- # end
76
- #
77
- # def unshift(item)
78
- # self.synchronize do
79
- # self.old_unshift(item)
80
- # end
81
- # end
82
- #
83
- # # other methods ...
84
- # end
85
- #
86
- # +SynchronizedArray+ implements an Array with synchronized access to items.
87
- # This Class is implemented as subclass of Array which includes the
88
- # MonitorMixin module.
89
- #
90
- module MonitorMixin
91
- #
92
- # FIXME: This isn't documented in Nutshell.
93
- #
94
- # Since MonitorMixin.new_cond returns a ConditionVariable, and the example
95
- # above calls while_wait and signal, this class should be documented.
96
- #
97
- class ConditionVariable
98
- class Timeout < Exception; end
99
-
100
- #
101
- # Releases the lock held in the associated monitor and waits; reacquires the lock on wakeup.
102
- #
103
- # If +timeout+ is given, this method returns after +timeout+ seconds passed,
104
- # even if no other thread doesn't signal.
105
- #
106
- def wait(timeout = nil)
107
- @monitor.__send__(:mon_check_owner)
108
- count = @monitor.__send__(:mon_exit_for_cond)
109
- begin
110
- @cond.wait(@monitor.instance_variable_get(:@mon_mutex), timeout)
111
- return true
112
- ensure
113
- @monitor.__send__(:mon_enter_for_cond, count)
114
- end
115
- end
116
-
117
- #
118
- # Calls wait repeatedly while the given block yields a truthy value.
119
- #
120
- def wait_while
121
- while yield
122
- wait
123
- end
124
- end
125
-
126
- #
127
- # Calls wait repeatedly until the given block yields a truthy value.
128
- #
129
- def wait_until
130
- until yield
131
- wait
132
- end
133
- end
134
-
135
- #
136
- # Wakes up the first thread in line waiting for this lock.
137
- #
138
- def signal
139
- @monitor.__send__(:mon_check_owner)
140
- @cond.signal
141
- end
142
-
143
- #
144
- # Wakes up all threads waiting for this lock.
145
- #
146
- def broadcast
147
- @monitor.__send__(:mon_check_owner)
148
- @cond.broadcast
149
- end
150
-
151
- private
152
-
153
- def initialize(monitor)
154
- @monitor = monitor
155
- @cond = ::ConditionVariable.new
156
- end
157
- end
158
-
159
- def self.extend_object(obj)
160
- super(obj)
161
- obj.__send__(:mon_initialize)
162
- end
163
-
164
- #
165
- # Attempts to enter exclusive section. Returns +false+ if lock fails.
166
- #
167
- def mon_try_enter
168
- if @mon_owner != Thread.current
169
- unless @mon_mutex.try_lock
170
- return false
171
- end
172
- @mon_owner = Thread.current
173
- end
174
- @mon_count += 1
175
- return true
176
- end
177
- # For backward compatibility
178
- alias try_mon_enter mon_try_enter
179
-
180
- #
181
- # Enters exclusive section.
182
- #
183
- def mon_enter
184
- if @mon_owner != Thread.current
185
- @mon_mutex.lock
186
- @mon_owner = Thread.current
187
- end
188
- @mon_count += 1
189
- end
190
-
191
- #
192
- # Leaves exclusive section.
193
- #
194
- def mon_exit
195
- mon_check_owner
196
- @mon_count -=1
197
- if @mon_count == 0
198
- @mon_owner = nil
199
- @mon_mutex.unlock
200
- end
201
- end
202
-
203
- #
204
- # Enters exclusive section and executes the block. Leaves the exclusive
205
- # section automatically when the block exits. See example under
206
- # +MonitorMixin+.
207
- #
208
- def mon_synchronize
209
- mon_enter
210
- begin
211
- yield
212
- ensure
213
- mon_exit
214
- end
215
- end
216
- alias synchronize mon_synchronize
217
-
218
- #
219
- # Creates a new MonitorMixin::ConditionVariable associated with the
220
- # receiver.
221
- #
222
- def new_cond
223
- return ConditionVariable.new(self)
224
- end
225
-
226
- private
227
-
228
- # Use <tt>extend MonitorMixin</tt> or <tt>include MonitorMixin</tt> instead
229
- # of this constructor. Have look at the examples above to understand how to
230
- # use this module.
231
- def initialize(*args)
232
- super
233
- mon_initialize
234
- end
235
-
236
- # Initializes the MonitorMixin after being included in a class or when an
237
- # object has been extended with the MonitorMixin
238
- def mon_initialize
239
- @mon_owner = nil
240
- @mon_count = 0
241
- @mon_mutex = Mutex.new
242
- end
243
-
244
- def mon_check_owner
245
- if @mon_owner != Thread.current
246
- raise ThreadError, "current thread not owner"
247
- end
248
- end
249
-
250
- def mon_enter_for_cond(count)
251
- @mon_owner = Thread.current
252
- @mon_count = count
253
- end
254
-
255
- def mon_exit_for_cond
256
- count = @mon_count
257
- @mon_owner = nil
258
- @mon_count = 0
259
- return count
260
- end
261
- end
262
-
263
- # Use the Monitor class when you want to have a lock object for blocks with
264
- # mutual exclusion.
265
- #
266
- # require 'monitor'
267
- #
268
- # lock = Monitor.new
269
- # lock.synchronize do
270
- # # exclusive access
271
- # end
272
- #
273
- class Monitor
274
- include MonitorMixin
275
- alias try_enter try_mon_enter
276
- alias enter mon_enter
277
- alias exit mon_exit
278
- end
279
-
280
-
281
- # Documentation comments:
282
- # - All documentation comes from Nutshell.
283
- # - MonitorMixin.new_cond appears in the example, but is not documented in
284
- # Nutshell.
285
- # - All the internals (internal modules Accessible and Initializable, class
286
- # ConditionVariable) appear in RDoc. It might be good to hide them, by
287
- # making them private, or marking them :nodoc:, etc.
288
- # - RDoc doesn't recognise aliases, so we have mon_synchronize documented, but
289
- # not synchronize.
290
- # - mon_owner is in Nutshell, but appears as an accessor in a separate module
291
- # here, so is hard/impossible to RDoc. Some other useful accessors
292
- # (mon_count and some queue stuff) are also in this module, and don't appear
293
- # directly in the RDoc output.
294
- # - in short, it may be worth changing the code layout in this file to make the
295
- # documentation easier
296
-
297
- # Local variables:
298
- # mode: Ruby
299
- # tab-width: 8
300
- # End: