ext_monitor 0.1.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/.gitignore +17 -0
- data/.rspec +3 -0
- data/.travis.yml +19 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +26 -0
- data/README.md +35 -0
- data/Rakefile +14 -0
- data/appveyor.yml +20 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/ext/ext_monitor/ext_monitor.c +243 -0
- data/ext/ext_monitor/ext_monitor.h +6 -0
- data/ext/ext_monitor/extconf.rb +3 -0
- data/ext_monitor.gemspec +43 -0
- data/lib/ext_monitor.rb +117 -0
- data/lib/ext_monitor/version.rb +3 -0
- metadata +119 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c211d6fb0f3e8efc24f6cadf7475a5cbd3d2c0f60e696d765fdea25000e90c1e
|
4
|
+
data.tar.gz: 9bcee9ffef01ce644eab720b8e3c118710223b51fd2c4eb7d94e92668619f45e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f462496ab98137332dec5f26555957727680ee3f075cbc392f655a881f73379976fd949f1945edbe35024ed0dd95caf58579ba5a82378b5e61ae13d62539b89b
|
7
|
+
data.tar.gz: 7adb8d2be65629df25f4e3b68dc5c5a9308792817caa5a80d8939ae9af9efa2c450d4c08e87a29f110fcf40cfcb9253ec47f0ab07cfef23d674f420070e8268d
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
---
|
2
|
+
sudo: false
|
3
|
+
language: ruby
|
4
|
+
os:
|
5
|
+
- linux
|
6
|
+
rvm:
|
7
|
+
- 2.3.8
|
8
|
+
- 2.3.8-clang
|
9
|
+
- 2.4.9
|
10
|
+
- 2.4.9-clang
|
11
|
+
- 2.5.7
|
12
|
+
- 2.6.5
|
13
|
+
- ruby-head
|
14
|
+
matrix:
|
15
|
+
allow_failures:
|
16
|
+
- rvm: ruby-head
|
17
|
+
before_install:
|
18
|
+
- gem install bundler
|
19
|
+
cache: bundler
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
Copyright (C) 2015 NARUSE, Yui. All rights reserved.
|
2
|
+
|
3
|
+
Redistribution and use in source and binary forms, with or without
|
4
|
+
modification, are permitted provided that the following conditions
|
5
|
+
are met:
|
6
|
+
1. Redistributions of source code must retain the above copyright
|
7
|
+
notice, this list of conditions and the following disclaimer.
|
8
|
+
2. Redistributions in binary form must reproduce the above copyright
|
9
|
+
notice, this list of conditions and the following disclaimer in the
|
10
|
+
documentation and/or other materials provided with the distribution.
|
11
|
+
|
12
|
+
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
13
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
14
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
15
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
16
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
17
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
18
|
+
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
19
|
+
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
20
|
+
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
21
|
+
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
22
|
+
SUCH DAMAGE.
|
23
|
+
|
24
|
+
ext/strptime/strptime.c:
|
25
|
+
date_strptime.c: Coded by Tadayoshi Funaba 2011,2012
|
26
|
+
Copyright (C) 2004-2007 Koichi Sasada
|
data/README.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# ExtMonitor
|
2
|
+
|
3
|
+
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/ext_monitor`. To experiment with that code, run `bin/console` for an interactive prompt.
|
4
|
+
|
5
|
+
TODO: Delete this and the text above, and describe your gem
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'ext_monitor'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install ext_monitor
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
TODO: Write usage instructions here
|
26
|
+
|
27
|
+
## Development
|
28
|
+
|
29
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
30
|
+
|
31
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
32
|
+
|
33
|
+
## Contributing
|
34
|
+
|
35
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/nurse/ext_monitor.
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rspec/core/rake_task"
|
3
|
+
|
4
|
+
RSpec::Core::RakeTask.new(:spec)
|
5
|
+
|
6
|
+
require "rake/extensiontask"
|
7
|
+
|
8
|
+
task :build => :compile
|
9
|
+
|
10
|
+
Rake::ExtensionTask.new("ext_monitor") do |ext|
|
11
|
+
ext.lib_dir = "lib/ext_monitor"
|
12
|
+
end
|
13
|
+
|
14
|
+
task :default => [:clobber, :compile, :spec]
|
data/appveyor.yml
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
---
|
2
|
+
install:
|
3
|
+
- SET PATH=C:\Ruby%ruby_version%\bin;%PATH%
|
4
|
+
- ruby --version
|
5
|
+
- gem --version
|
6
|
+
- bundle install
|
7
|
+
build_script:
|
8
|
+
- bundle exec rake -rdevkit build
|
9
|
+
test_script:
|
10
|
+
- bundle exec rake -rdevkit spec
|
11
|
+
environment:
|
12
|
+
matrix:
|
13
|
+
- ruby_version: "23"
|
14
|
+
- ruby_version: "23-x64"
|
15
|
+
- ruby_version: "24"
|
16
|
+
- ruby_version: "24-x64"
|
17
|
+
- ruby_version: "25"
|
18
|
+
- ruby_version: "25-x64"
|
19
|
+
- ruby_version: "26"
|
20
|
+
- ruby_version: "26-x64"
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "ext_monitor"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,243 @@
|
|
1
|
+
#include "ext_monitor.h"
|
2
|
+
|
3
|
+
struct monitor_core {
|
4
|
+
long count;
|
5
|
+
const VALUE owner;
|
6
|
+
const VALUE mutex;
|
7
|
+
};
|
8
|
+
|
9
|
+
static void
|
10
|
+
mcore_mark(void *ptr)
|
11
|
+
{
|
12
|
+
struct monitor_core *mc = ptr;
|
13
|
+
rb_gc_mark(mc->owner);
|
14
|
+
rb_gc_mark(mc->mutex);
|
15
|
+
}
|
16
|
+
|
17
|
+
static size_t
|
18
|
+
mcore_memsize(const void *ptr)
|
19
|
+
{
|
20
|
+
return sizeof(struct monitor_core);
|
21
|
+
}
|
22
|
+
|
23
|
+
static const rb_data_type_t mcore_data_type = {
|
24
|
+
"thread/monitor_data",
|
25
|
+
{mcore_mark, RUBY_TYPED_DEFAULT_FREE, mcore_memsize,},
|
26
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED
|
27
|
+
};
|
28
|
+
|
29
|
+
static VALUE
|
30
|
+
mcore_alloc(VALUE klass)
|
31
|
+
{
|
32
|
+
struct monitor_core *mc;
|
33
|
+
VALUE obj;
|
34
|
+
|
35
|
+
obj = TypedData_Make_Struct(klass, struct monitor_core, &mcore_data_type, mc);
|
36
|
+
RB_OBJ_WRITE(obj, &mc->mutex, Qnil);
|
37
|
+
RB_OBJ_WRITE(obj, &mc->owner, Qnil);
|
38
|
+
mc->count = 0;
|
39
|
+
|
40
|
+
return obj;
|
41
|
+
}
|
42
|
+
|
43
|
+
static struct monitor_core *
|
44
|
+
mcore_ptr(VALUE mcore)
|
45
|
+
{
|
46
|
+
struct monitor_core *mc;
|
47
|
+
TypedData_Get_Struct(mcore, struct monitor_core, &mcore_data_type, mc);
|
48
|
+
return mc;
|
49
|
+
}
|
50
|
+
|
51
|
+
/*
|
52
|
+
* call-seq:
|
53
|
+
* MonitorCore.new
|
54
|
+
* MonitorCore.new(mutex, owner, count)
|
55
|
+
*
|
56
|
+
* returns MonitorCore object
|
57
|
+
*/
|
58
|
+
static VALUE
|
59
|
+
mcore_init(int argc, VALUE *argv, VALUE mcore)
|
60
|
+
{
|
61
|
+
struct monitor_core *mc = mcore_ptr(mcore);
|
62
|
+
|
63
|
+
if (argc == 0) {
|
64
|
+
RB_OBJ_WRITE(mcore, &mc->mutex, rb_mutex_new());
|
65
|
+
RB_OBJ_WRITE(mcore, &mc->owner, Qnil);
|
66
|
+
mc->count = 0;
|
67
|
+
}
|
68
|
+
else if(argc == 3) {
|
69
|
+
RB_OBJ_WRITE(mcore, &mc->mutex, argv[0]);
|
70
|
+
RB_OBJ_WRITE(mcore, &mc->owner, argv[1]);
|
71
|
+
mc->count = NUM2LONG(argv[2]);
|
72
|
+
}
|
73
|
+
else {
|
74
|
+
rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 0 or 3)", argc);
|
75
|
+
}
|
76
|
+
|
77
|
+
return mcore;
|
78
|
+
}
|
79
|
+
|
80
|
+
static int
|
81
|
+
mc_owner_p(struct monitor_core *mc)
|
82
|
+
{
|
83
|
+
return mc->owner == rb_thread_current();
|
84
|
+
}
|
85
|
+
|
86
|
+
static VALUE
|
87
|
+
mcore_try_enter(VALUE mcore)
|
88
|
+
{
|
89
|
+
struct monitor_core *mc = mcore_ptr(mcore);
|
90
|
+
|
91
|
+
if (!mc_owner_p(mc)) {
|
92
|
+
if (!rb_mutex_trylock(mc->mutex)) {
|
93
|
+
return Qfalse;
|
94
|
+
}
|
95
|
+
RB_OBJ_WRITE(mcore, &mc->owner, rb_thread_current());
|
96
|
+
mc->count = 0;
|
97
|
+
}
|
98
|
+
mc->count += 1;
|
99
|
+
return Qtrue;
|
100
|
+
}
|
101
|
+
|
102
|
+
static VALUE
|
103
|
+
mcore_enter(VALUE mcore)
|
104
|
+
{
|
105
|
+
struct monitor_core *mc = mcore_ptr(mcore);
|
106
|
+
if (!mc_owner_p(mc)) {
|
107
|
+
rb_mutex_lock(mc->mutex);
|
108
|
+
RB_OBJ_WRITE(mcore, &mc->owner, rb_thread_current());
|
109
|
+
mc->count = 0;
|
110
|
+
}
|
111
|
+
mc->count++;
|
112
|
+
return Qnil;
|
113
|
+
}
|
114
|
+
|
115
|
+
static VALUE
|
116
|
+
mcore_exit(VALUE mcore)
|
117
|
+
{
|
118
|
+
struct monitor_core *mc = mcore_ptr(mcore);
|
119
|
+
mc->count--;
|
120
|
+
if (mc->count == 0) {
|
121
|
+
RB_OBJ_WRITE(mcore, &mc->owner, Qnil);
|
122
|
+
rb_mutex_unlock(mc->mutex);
|
123
|
+
}
|
124
|
+
return Qnil;
|
125
|
+
}
|
126
|
+
|
127
|
+
static VALUE
|
128
|
+
mcore_locked_p(VALUE mcore)
|
129
|
+
{
|
130
|
+
struct monitor_core *mc = mcore_ptr(mcore);
|
131
|
+
return rb_mutex_locked_p(mc->mutex);
|
132
|
+
}
|
133
|
+
|
134
|
+
static VALUE
|
135
|
+
mcore_owned_p(VALUE mcore)
|
136
|
+
{
|
137
|
+
struct monitor_core *mc = mcore_ptr(mcore);
|
138
|
+
return (rb_mutex_locked_p(mc->mutex) && mc_owner_p(mc)) ? Qtrue : Qfalse;
|
139
|
+
}
|
140
|
+
|
141
|
+
static VALUE
|
142
|
+
mcore_owner(VALUE mcore)
|
143
|
+
{
|
144
|
+
struct monitor_core *mc = mcore_ptr(mcore);
|
145
|
+
return mc->owner;
|
146
|
+
}
|
147
|
+
|
148
|
+
static VALUE
|
149
|
+
mcore_check_owner(VALUE mcore)
|
150
|
+
{
|
151
|
+
struct monitor_core *mc = mcore_ptr(mcore);
|
152
|
+
if (!mc_owner_p(mc)) {
|
153
|
+
rb_raise(rb_eThreadError, "current thread not owner");
|
154
|
+
}
|
155
|
+
return Qnil;
|
156
|
+
}
|
157
|
+
|
158
|
+
static VALUE
|
159
|
+
mcore_enter_for_cond(VALUE mcore, VALUE target_thread, VALUE count)
|
160
|
+
{
|
161
|
+
struct monitor_core *mc = mcore_ptr(mcore);
|
162
|
+
RB_OBJ_WRITE(mcore, &mc->owner, target_thread);
|
163
|
+
mc->count = NUM2LONG(count);
|
164
|
+
return Qnil;
|
165
|
+
}
|
166
|
+
|
167
|
+
static VALUE
|
168
|
+
mcore_exit_for_cond(VALUE mcore)
|
169
|
+
{
|
170
|
+
struct monitor_core *mc = mcore_ptr(mcore);
|
171
|
+
long cnt = mc->count;
|
172
|
+
if (!mc_owner_p(mc)) {
|
173
|
+
rb_raise(rb_eThreadError, "current thread not owner");
|
174
|
+
}
|
175
|
+
RB_OBJ_WRITE(mcore, &mc->owner, Qnil);
|
176
|
+
mc->count = 0;
|
177
|
+
return LONG2NUM(cnt);
|
178
|
+
}
|
179
|
+
|
180
|
+
static VALUE
|
181
|
+
mcore_mutex_for_cond(VALUE mcore)
|
182
|
+
{
|
183
|
+
struct monitor_core *mc = mcore_ptr(mcore);
|
184
|
+
return mc->mutex;
|
185
|
+
}
|
186
|
+
|
187
|
+
#if 0
|
188
|
+
static VALUE
|
189
|
+
mcore_sync_body(VALUE mcore)
|
190
|
+
{
|
191
|
+
return rb_yield_values(0);
|
192
|
+
}
|
193
|
+
|
194
|
+
static VALUE
|
195
|
+
mcore_sync_ensure(VALUE mcore)
|
196
|
+
{
|
197
|
+
return mcore_exit(mcore);
|
198
|
+
}
|
199
|
+
|
200
|
+
static VALUE
|
201
|
+
mcore_synchronize(VALUE mcore)
|
202
|
+
{
|
203
|
+
mcore_enter(mcore);
|
204
|
+
return rb_ensure(mcore_sync_body, mcore, mcore_sync_ensure, mcore);
|
205
|
+
}
|
206
|
+
#endif
|
207
|
+
|
208
|
+
/*
|
209
|
+
* call-seq:
|
210
|
+
* monitor_core.inspect -> string
|
211
|
+
*
|
212
|
+
*/
|
213
|
+
VALUE
|
214
|
+
mcore_inspect(VALUE mcore)
|
215
|
+
{
|
216
|
+
struct monitor_core *mc = mcore_ptr(mcore);
|
217
|
+
return rb_sprintf("#<%s:%p mutex:%+"PRIsVALUE" owner:%+"PRIsVALUE" count:%ld>",
|
218
|
+
rb_obj_classname(mcore), (void*)mcore, mc->mutex, mc->owner, mc->count);
|
219
|
+
}
|
220
|
+
|
221
|
+
void
|
222
|
+
Init_ext_monitor(void)
|
223
|
+
{
|
224
|
+
/* Thread::MonitorCore (internal data for Monitor) */
|
225
|
+
VALUE rb_cMonitorCore = rb_define_class_under(rb_cThread, "MonitorCore", rb_cObject);
|
226
|
+
rb_define_alloc_func(rb_cMonitorCore, mcore_alloc);
|
227
|
+
rb_define_method(rb_cMonitorCore, "initialize", mcore_init, -1);
|
228
|
+
rb_define_method(rb_cMonitorCore, "try_enter", mcore_try_enter, 0);
|
229
|
+
rb_define_method(rb_cMonitorCore, "enter", mcore_enter, 0);
|
230
|
+
rb_define_method(rb_cMonitorCore, "exit", mcore_exit, 0);
|
231
|
+
rb_define_method(rb_cMonitorCore, "locked?", mcore_locked_p, 0);
|
232
|
+
rb_define_method(rb_cMonitorCore, "owned?", mcore_owned_p, 0);
|
233
|
+
rb_define_method(rb_cMonitorCore, "owner", mcore_owner, 0);
|
234
|
+
rb_define_method(rb_cMonitorCore, "check_owner", mcore_check_owner, 0);
|
235
|
+
rb_define_method(rb_cMonitorCore, "enter_for_cond", mcore_enter_for_cond, 2); // thread, count
|
236
|
+
rb_define_method(rb_cMonitorCore, "exit_for_cond", mcore_exit_for_cond, 0);
|
237
|
+
rb_define_method(rb_cMonitorCore, "mutex_for_cond", mcore_mutex_for_cond, 0);
|
238
|
+
#if 0
|
239
|
+
// Ruby definition is faster than C-impl now.
|
240
|
+
rb_define_method(rb_cMonitorCore, "synchronize", mcore_synchronize, 0);
|
241
|
+
#endif
|
242
|
+
rb_define_method(rb_cMonitorCore, "inspect", mcore_inspect, 0);
|
243
|
+
}
|
data/ext_monitor.gemspec
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "ext_monitor/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "ext_monitor"
|
8
|
+
spec.version = ExtMonitor::VERSION
|
9
|
+
spec.authors = ["NARUSE, Yui"]
|
10
|
+
spec.email = ["naruse@airemix.jp"]
|
11
|
+
|
12
|
+
spec.summary = %q{faster MonitorMixin implementation}
|
13
|
+
spec.description = %q{faster MonitorMixin implementation with C extension which is introduced in Ruby 2.7}
|
14
|
+
spec.homepage = "https://github.com/nurse/ext_monitor"
|
15
|
+
|
16
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
17
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
18
|
+
if spec.respond_to?(:metadata)
|
19
|
+
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
20
|
+
|
21
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
22
|
+
spec.metadata["source_code_uri"] = "https://github.com/nurse/ext_monitor"
|
23
|
+
else
|
24
|
+
raise "RubyGems 2.0 or newer is required to protect against " \
|
25
|
+
"public gem pushes."
|
26
|
+
end
|
27
|
+
|
28
|
+
# Specify which files should be added to the gem when it is released.
|
29
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
30
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
31
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
32
|
+
end
|
33
|
+
spec.bindir = "exe"
|
34
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
35
|
+
spec.require_paths = ["lib"]
|
36
|
+
spec.extensions = ["ext/ext_monitor/extconf.rb"]
|
37
|
+
spec.required_ruby_version = '~> 2.3'
|
38
|
+
|
39
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
40
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
41
|
+
spec.add_development_dependency "rake-compiler"
|
42
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
43
|
+
end
|
data/lib/ext_monitor.rb
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
require "monitor"
|
2
|
+
require "ext_monitor/version"
|
3
|
+
require "ext_monitor/ext_monitor"
|
4
|
+
|
5
|
+
module MonitorMixin
|
6
|
+
class ConditionVariable
|
7
|
+
remove_method :wait
|
8
|
+
|
9
|
+
#
|
10
|
+
# Releases the lock held in the associated monitor and waits; reacquires the lock on wakeup.
|
11
|
+
#
|
12
|
+
# If +timeout+ is given, this method returns after +timeout+ seconds passed,
|
13
|
+
# even if no other thread doesn't signal.
|
14
|
+
#
|
15
|
+
def wait(timeout = nil)
|
16
|
+
@monitor.__send__(:mon_check_owner)
|
17
|
+
count = @monitor.__send__(:mon_exit_for_cond)
|
18
|
+
begin
|
19
|
+
@cond.wait(@monitor.instance_variable_get(:@mon_data).mutex_for_cond, timeout)
|
20
|
+
return true
|
21
|
+
ensure
|
22
|
+
@monitor.__send__(:mon_enter_for_cond, count)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
remove_method :mon_try_enter, :mon_enter, :mon_exit, :mon_synchronize,
|
28
|
+
:mon_initialize, :mon_check_owner, :mon_enter_for_cond, :mon_exit_for_cond
|
29
|
+
remove_method :mon_locked? if defined?(mon_locked?)
|
30
|
+
remove_method :mon_owned? if defined?(mon_owned?)
|
31
|
+
|
32
|
+
# Attempts to enter exclusive section. Returns +false+ if lock fails.
|
33
|
+
#
|
34
|
+
def mon_try_enter
|
35
|
+
(defined?(@mon_data) ? @mon_data : use_monitor_core).try_enter
|
36
|
+
end
|
37
|
+
|
38
|
+
# Enters exclusive section.
|
39
|
+
#
|
40
|
+
def mon_enter
|
41
|
+
(defined?(@mon_data) ? @mon_data : use_monitor_core).enter
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# Leaves exclusive section.
|
46
|
+
#
|
47
|
+
def mon_exit
|
48
|
+
(defined?(@mon_data) ? @mon_data : use_monitor_core).exit
|
49
|
+
end
|
50
|
+
|
51
|
+
#
|
52
|
+
# Returns true if this monitor is locked by any thread
|
53
|
+
#
|
54
|
+
def mon_locked?
|
55
|
+
(defined?(@mon_data) ? @mon_data : use_monitor_core).locked?
|
56
|
+
end
|
57
|
+
|
58
|
+
#
|
59
|
+
# Returns true if this monitor is locked by current thread.
|
60
|
+
#
|
61
|
+
def mon_owned?
|
62
|
+
(defined?(@mon_data) ? @mon_data : use_monitor_core).owned?
|
63
|
+
end
|
64
|
+
|
65
|
+
#
|
66
|
+
# Enters exclusive section and executes the block. Leaves the exclusive
|
67
|
+
# section automatically when the block exits. See example under
|
68
|
+
# +MonitorMixin+.
|
69
|
+
#
|
70
|
+
def mon_synchronize(&b)
|
71
|
+
@mon_data.enter
|
72
|
+
begin
|
73
|
+
yield
|
74
|
+
ensure
|
75
|
+
@mon_data.exit
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# Initializes the MonitorMixin after being included in a class or when an
|
80
|
+
# object has been extended with the MonitorMixin
|
81
|
+
def mon_initialize
|
82
|
+
if defined?(@mon_data) && @mon_data_owner_object_id == self.object_id
|
83
|
+
raise ThreadError, "already initialized"
|
84
|
+
end
|
85
|
+
@mon_data = ::Thread::MonitorCore.new
|
86
|
+
@mon_data_owner_object_id = self.object_id
|
87
|
+
end
|
88
|
+
|
89
|
+
def mon_check_owner
|
90
|
+
(defined?(@mon_data) ? @mon_data : use_monitor_core).check_owner
|
91
|
+
end
|
92
|
+
|
93
|
+
|
94
|
+
def mon_enter_for_cond(count)
|
95
|
+
(defined?(@mon_data) ? @mon_data : use_monitor_core).enter_for_cond(Thread.current, count)
|
96
|
+
end
|
97
|
+
|
98
|
+
def mon_exit_for_cond
|
99
|
+
(defined?(@mon_data) ? @mon_data : use_monitor_core).exit_for_cond
|
100
|
+
end
|
101
|
+
|
102
|
+
def use_monitor_core
|
103
|
+
# below doesn't call RUBY_VM_CHECK_INTS
|
104
|
+
@mon_data = ::Thread::MonitorCore.new(@mon_mutex, @mon_owner, @mon_count)
|
105
|
+
@mon_data_owner_object_id = self.object_id
|
106
|
+
remove_instance_variable(:@mon_mutex)
|
107
|
+
remove_instance_variable(:@mon_owner)
|
108
|
+
remove_instance_variable(:@mon_count)
|
109
|
+
@mon_data
|
110
|
+
end
|
111
|
+
end
|
112
|
+
class Monitor
|
113
|
+
alias try_mon_enter mon_try_enter
|
114
|
+
alias try_enter try_mon_enter
|
115
|
+
alias enter mon_enter
|
116
|
+
alias exit mon_exit
|
117
|
+
end
|
metadata
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ext_monitor
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- NARUSE, Yui
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-10-09 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: '2.0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.0'
|
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: rake-compiler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
69
|
+
description: faster MonitorMixin implementation with C extension which is introduced
|
70
|
+
in Ruby 2.7
|
71
|
+
email:
|
72
|
+
- naruse@airemix.jp
|
73
|
+
executables: []
|
74
|
+
extensions:
|
75
|
+
- ext/ext_monitor/extconf.rb
|
76
|
+
extra_rdoc_files: []
|
77
|
+
files:
|
78
|
+
- ".gitignore"
|
79
|
+
- ".rspec"
|
80
|
+
- ".travis.yml"
|
81
|
+
- Gemfile
|
82
|
+
- LICENSE.txt
|
83
|
+
- README.md
|
84
|
+
- Rakefile
|
85
|
+
- appveyor.yml
|
86
|
+
- bin/console
|
87
|
+
- bin/setup
|
88
|
+
- ext/ext_monitor/ext_monitor.c
|
89
|
+
- ext/ext_monitor/ext_monitor.h
|
90
|
+
- ext/ext_monitor/extconf.rb
|
91
|
+
- ext_monitor.gemspec
|
92
|
+
- lib/ext_monitor.rb
|
93
|
+
- lib/ext_monitor/version.rb
|
94
|
+
homepage: https://github.com/nurse/ext_monitor
|
95
|
+
licenses: []
|
96
|
+
metadata:
|
97
|
+
allowed_push_host: https://rubygems.org
|
98
|
+
homepage_uri: https://github.com/nurse/ext_monitor
|
99
|
+
source_code_uri: https://github.com/nurse/ext_monitor
|
100
|
+
post_install_message:
|
101
|
+
rdoc_options: []
|
102
|
+
require_paths:
|
103
|
+
- lib
|
104
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - "~>"
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '2.3'
|
109
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
111
|
+
- - ">="
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: '0'
|
114
|
+
requirements: []
|
115
|
+
rubygems_version: 3.0.3
|
116
|
+
signing_key:
|
117
|
+
specification_version: 4
|
118
|
+
summary: faster MonitorMixin implementation
|
119
|
+
test_files: []
|