isomorfeus-ferret 0.13.2 → 0.13.5
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 +4 -4
- data/LICENSE +0 -26
- data/README.md +6 -5
- data/ext/isomorfeus_ferret_ext/benchmark.c +2 -2
- data/ext/isomorfeus_ferret_ext/frb_index.c +13 -18
- data/ext/isomorfeus_ferret_ext/frt_except.c +0 -1
- data/ext/isomorfeus_ferret_ext/frt_fs_store.c +0 -2
- data/ext/isomorfeus_ferret_ext/frt_global.h +0 -7
- data/ext/isomorfeus_ferret_ext/frt_lang.c +8 -1
- data/ext/isomorfeus_ferret_ext/frt_store.h +1 -1
- data/ext/isomorfeus_ferret_ext/isomorfeus_ferret.c +2 -2
- data/ext/isomorfeus_ferret_ext/isomorfeus_ferret.h +1 -2
- data/ext/isomorfeus_ferret_ext/test_threading.c +1 -1
- data/lib/isomorfeus/ferret/index/index.rb +1 -1
- data/lib/isomorfeus/ferret/version.rb +1 -1
- data/lib/isomorfeus-ferret.rb +1 -1
- metadata +2 -6
- data/ext/isomorfeus_ferret_ext/frb_lang.c +0 -9
- data/ext/isomorfeus_ferret_ext/frb_lang.h +0 -17
- data/ext/isomorfeus_ferret_ext/frb_threading.h +0 -29
- data/lib/isomorfeus/ferret/monitor.rb +0 -323
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1f2a4a6ea097a25d4d32a958c730fffca81ded61133f37ef4c86ca5b78ecef77
|
4
|
+
data.tar.gz: 7be1f98b64559be5f02e39d7a74894476046fef3fdd46d1e69ee3079c74c9681
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d173777ee520433e8df0e1a07853f92b65aa350427668baea67a957a28a8cadc05790396d8d5167282c4c83fb1e874eec3316c226e8c961f9f3161f3bf3ecb79
|
7
|
+
data.tar.gz: c64a96813a4b2546e21825cb4a6310c9384a8090bafe51e9c65c49d8c2b8bc69ab3deed82780e6df09089b6a915d6b7e7418bcac30f3d9770c1358800aa2286d
|
data/LICENSE
CHANGED
@@ -139,32 +139,6 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
139
139
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
140
140
|
|
141
141
|
|
142
|
-
lib/isomorfeus/ferret/monitor.rb originally taken from the gem 'monitor':
|
143
|
-
|
144
|
-
Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved.
|
145
|
-
|
146
|
-
Redistribution and use in source and binary forms, with or without
|
147
|
-
modification, are permitted provided that the following conditions
|
148
|
-
are met:
|
149
|
-
|
150
|
-
1. Redistributions of source code must retain the above copyright notice,
|
151
|
-
this list of conditions and the following disclaimer.
|
152
|
-
2. Redistributions in binary form must reproduce the above copyright notice,
|
153
|
-
this list of conditions and the following disclaimer in the documentation
|
154
|
-
and/or other materials provided with the distribution.
|
155
|
-
|
156
|
-
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
157
|
-
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
158
|
-
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
159
|
-
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
160
|
-
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
161
|
-
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
162
|
-
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
163
|
-
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
164
|
-
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
165
|
-
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
166
|
-
|
167
|
-
|
168
142
|
The following licenses apply to files, which are distributed within the repo
|
169
143
|
but not distributed with the gem and not used at runtime:
|
170
144
|
|
data/README.md
CHANGED
@@ -26,7 +26,7 @@ It should work on *nixes, *nuxes, *BSDs and also works on Windows.
|
|
26
26
|
- The :store option no longer accepts :compress, compression must now be specified by the separate :compress options (see below).
|
27
27
|
- The ASCII-specific Tokenizers and Analyzers have been removed
|
28
28
|
|
29
|
-
###
|
29
|
+
### String Encoding support
|
30
30
|
|
31
31
|
#### Input strings and stored fields
|
32
32
|
|
@@ -37,12 +37,13 @@ All Ruby string encodings are supported.
|
|
37
37
|
When fields are stored, they are now stored with the encoding, so that when they are retrieved again, they
|
38
38
|
retain the original encoding with positions matching the string in its original encoding.
|
39
39
|
|
40
|
-
#### Tokens and
|
40
|
+
#### Tokens, Terms, Filters and Queries
|
41
41
|
|
42
42
|
Tokens are internally converted to UTF-8, which may change their length compared to their original encoding,
|
43
|
-
yet they retain position information according to the source in its original encoding.
|
44
|
-
|
45
|
-
|
43
|
+
yet they retain position information according to the source in its original encoding. Terms are likewise stored in UTF-8 encoding.
|
44
|
+
Queries are converted to UTF-8 encoding too.
|
45
|
+
The benefit is, that Filters, Stemmers or anything else working with Tokens and Terms only needs to support UTF-8 encoding,
|
46
|
+
greatly simplifying things and ensuring consistent query results, independent of source encoding.
|
46
47
|
|
47
48
|
### Compression
|
48
49
|
|
@@ -117,13 +117,13 @@ static void bm_single_run(BenchMarkUnit *unit, BenchMarkTimes *bm_times)
|
|
117
117
|
struct rusage ru_before, ru_after;
|
118
118
|
|
119
119
|
if (gettimeofday(&tv_before, NULL) == -1)
|
120
|
-
|
120
|
+
rb_raise(rb_eRuntimeError, "gettimeofday failed\n");
|
121
121
|
getrusage(RUSAGE_SELF, &ru_before);
|
122
122
|
|
123
123
|
unit->run();
|
124
124
|
|
125
125
|
if (gettimeofday(&tv_after, NULL) == -1)
|
126
|
-
|
126
|
+
rb_raise(rb_eRuntimeError, "gettimeofday failed\n");
|
127
127
|
getrusage(RUSAGE_SELF, &ru_after);
|
128
128
|
|
129
129
|
bm_times->rtime = TVAL_TO_SEC(tv_before, tv_after);
|
@@ -182,8 +182,9 @@ static VALUE frb_get_field_info(FrtFieldInfo *fi) {
|
|
182
182
|
fi->rfi = TypedData_Wrap_Struct(cFieldInfo, &frb_field_info_t, fi);
|
183
183
|
FRT_REF(fi);
|
184
184
|
}
|
185
|
+
return fi->rfi;
|
185
186
|
}
|
186
|
-
return
|
187
|
+
return Qnil;
|
187
188
|
}
|
188
189
|
|
189
190
|
/*
|
@@ -412,8 +413,9 @@ static VALUE frb_get_field_infos(FrtFieldInfos *fis) {
|
|
412
413
|
fis->rfis = TypedData_Wrap_Struct(cFieldInfos, &frb_field_infos_t, fis);
|
413
414
|
FRT_REF(fis);
|
414
415
|
}
|
416
|
+
return fis->rfis;
|
415
417
|
}
|
416
|
-
return
|
418
|
+
return Qnil;
|
417
419
|
}
|
418
420
|
|
419
421
|
/*
|
@@ -497,11 +499,6 @@ static VALUE frb_fis_get(VALUE self, VALUE ridx) {
|
|
497
499
|
case T_STRING:
|
498
500
|
rfi = frb_get_field_info(frt_fis_get_field(fis, frb_field(ridx)));
|
499
501
|
break;
|
500
|
-
/*
|
501
|
-
case T_STRING:
|
502
|
-
rfi = frb_get_field_info(frt_fis_get_field(fis, StringValuePtr(ridx)));
|
503
|
-
break;
|
504
|
-
*/
|
505
502
|
default:
|
506
503
|
rb_raise(rb_eArgError, "Can't index FieldInfos with %s",
|
507
504
|
rs2s(rb_obj_as_string(ridx)));
|
@@ -1274,11 +1271,11 @@ void frb_iw_free(void *p) {
|
|
1274
1271
|
|
1275
1272
|
void frb_iw_mark(void *p) {
|
1276
1273
|
FrtIndexWriter *iw = (FrtIndexWriter *)p;
|
1277
|
-
if (iw->analyzer->ranalyzer)
|
1274
|
+
if (iw->analyzer && iw->analyzer->ranalyzer)
|
1278
1275
|
rb_gc_mark(iw->analyzer->ranalyzer);
|
1279
|
-
if (iw->store->rstore)
|
1276
|
+
if (iw->store && iw->store->rstore)
|
1280
1277
|
rb_gc_mark(iw->store->rstore);
|
1281
|
-
if (iw->fis->rfis)
|
1278
|
+
if (iw->fis && iw->fis->rfis)
|
1282
1279
|
rb_gc_mark(iw->fis->rfis);
|
1283
1280
|
}
|
1284
1281
|
|
@@ -1699,10 +1696,9 @@ frb_iw_delete(VALUE self, VALUE rfield, VALUE rterm)
|
|
1699
1696
|
* Get the FieldInfos object for this FrtIndexWriter. This is useful if you need
|
1700
1697
|
* to dynamically add new fields to the index with specific properties.
|
1701
1698
|
*/
|
1702
|
-
static VALUE
|
1703
|
-
|
1704
|
-
|
1705
|
-
FrtIndexWriter *iw = (FrtIndexWriter *)DATA_PTR(self);
|
1699
|
+
static VALUE frb_iw_field_infos(VALUE self) {
|
1700
|
+
FrtIndexWriter *iw;
|
1701
|
+
TypedData_Get_Struct(self, FrtIndexWriter, &frb_index_writer_t, iw);
|
1706
1702
|
return frb_get_field_infos(iw->fis);
|
1707
1703
|
}
|
1708
1704
|
|
@@ -2717,10 +2713,9 @@ frb_ir_fields(VALUE self)
|
|
2717
2713
|
*
|
2718
2714
|
* Get the FieldInfos object for this IndexReader.
|
2719
2715
|
*/
|
2720
|
-
static VALUE
|
2721
|
-
|
2722
|
-
|
2723
|
-
FrtIndexReader *ir = (FrtIndexReader *)DATA_PTR(self);
|
2716
|
+
static VALUE frb_ir_field_infos(VALUE self) {
|
2717
|
+
FrtIndexReader *ir;
|
2718
|
+
TypedData_Get_Struct(self, FrtIndexReader, &frb_index_reader_t, ir);
|
2724
2719
|
return frb_get_field_infos(ir->fis);
|
2725
2720
|
}
|
2726
2721
|
|
@@ -266,13 +266,6 @@ extern FILE *frt_x_exception_stream;
|
|
266
266
|
#define EXCEPTION 2
|
267
267
|
#define EXCEPTION_STREAM (frt_x_exception_stream ? frt_x_exception_stream : stderr)
|
268
268
|
|
269
|
-
#ifdef DEBUG
|
270
|
-
extern bool frt_x_do_logging;
|
271
|
-
#define xlog if (frt_x_do_logging) printf
|
272
|
-
#else
|
273
|
-
#define xlog()
|
274
|
-
#endif
|
275
|
-
|
276
269
|
extern void frt_init(int arc, const char *const argv[]);
|
277
270
|
extern void frt_micro_sleep(const int micro_seconds);
|
278
271
|
|
@@ -43,7 +43,14 @@ void *frt_erealloc(void *ptr, size_t size)
|
|
43
43
|
return p;
|
44
44
|
}
|
45
45
|
|
46
|
-
|
46
|
+
|
47
|
+
struct timeval rb_time_interval _((VALUE));
|
48
|
+
|
49
|
+
extern void frt_micro_sleep(const int micro_seconds) {
|
50
|
+
rb_thread_wait_for(rb_time_interval(rb_float_new((double)micro_seconds/1000000.0)));
|
51
|
+
}
|
52
|
+
|
53
|
+
/* void frt_micro_sleep(const int micro_seconds)
|
47
54
|
{
|
48
55
|
#if (defined POSH_OS_WIN32 || defined POSH_OS_WIN64) && !defined __MINGW32__
|
49
56
|
Sleep(micro_seconds / 1000);
|
@@ -175,7 +175,7 @@ TestSuite *ts_threading(TestSuite *suite)
|
|
175
175
|
|
176
176
|
tst_run_test(suite, test_number_to_str, NULL);
|
177
177
|
tst_run_test(suite, test_threading_test, index);
|
178
|
-
|
178
|
+
tst_run_test(suite, test_threading, index);
|
179
179
|
|
180
180
|
frt_index_destroy(index);
|
181
181
|
|
@@ -4,7 +4,7 @@ module Isomorfeus
|
|
4
4
|
# This is a simplified interface to the index. See the TUTORIAL for more
|
5
5
|
# information on how to use this class.
|
6
6
|
class Index
|
7
|
-
include
|
7
|
+
include MonitorMixin
|
8
8
|
include Isomorfeus::Ferret::Store
|
9
9
|
include Isomorfeus::Ferret::Search
|
10
10
|
|
data/lib/isomorfeus-ferret.rb
CHANGED
@@ -2,7 +2,7 @@ require 'isomorfeus_ferret_ext'
|
|
2
2
|
require 'isomorfeus/ferret/version'
|
3
3
|
require 'isomorfeus/ferret/field_symbol'
|
4
4
|
require 'isomorfeus/ferret/stdlib_patches'
|
5
|
-
require '
|
5
|
+
require 'monitor'
|
6
6
|
require 'isomorfeus/ferret/index/field_infos'
|
7
7
|
require 'isomorfeus/ferret/index/index'
|
8
8
|
require 'isomorfeus/ferret/document'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: isomorfeus-ferret
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.13.
|
4
|
+
version: 0.13.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jan Biedermann
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-04-
|
11
|
+
date: 2022-04-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -167,12 +167,9 @@ files:
|
|
167
167
|
- ext/isomorfeus_ferret_ext/fio_tmpfile.h
|
168
168
|
- ext/isomorfeus_ferret_ext/frb_analysis.c
|
169
169
|
- ext/isomorfeus_ferret_ext/frb_index.c
|
170
|
-
- ext/isomorfeus_ferret_ext/frb_lang.c
|
171
|
-
- ext/isomorfeus_ferret_ext/frb_lang.h
|
172
170
|
- ext/isomorfeus_ferret_ext/frb_qparser.c
|
173
171
|
- ext/isomorfeus_ferret_ext/frb_search.c
|
174
172
|
- ext/isomorfeus_ferret_ext/frb_store.c
|
175
|
-
- ext/isomorfeus_ferret_ext/frb_threading.h
|
176
173
|
- ext/isomorfeus_ferret_ext/frb_utils.c
|
177
174
|
- ext/isomorfeus_ferret_ext/frt_analysis.c
|
178
175
|
- ext/isomorfeus_ferret_ext/frt_analysis.h
|
@@ -360,7 +357,6 @@ files:
|
|
360
357
|
- lib/isomorfeus/ferret/field_symbol.rb
|
361
358
|
- lib/isomorfeus/ferret/index/field_infos.rb
|
362
359
|
- lib/isomorfeus/ferret/index/index.rb
|
363
|
-
- lib/isomorfeus/ferret/monitor.rb
|
364
360
|
- lib/isomorfeus/ferret/stdlib_patches.rb
|
365
361
|
- lib/isomorfeus/ferret/version.rb
|
366
362
|
homepage: https://isomorfeus.com
|
@@ -1,17 +0,0 @@
|
|
1
|
-
#ifndef FRT_LANG_H
|
2
|
-
#define FRT_LANG_H
|
3
|
-
|
4
|
-
#define RUBY_BINDINGS 1
|
5
|
-
|
6
|
-
#include <stdarg.h>
|
7
|
-
#include <ruby.h>
|
8
|
-
|
9
|
-
#undef close
|
10
|
-
#undef rename
|
11
|
-
#undef read
|
12
|
-
|
13
|
-
#define frt_emalloc xmalloc
|
14
|
-
#define frt_ecalloc(n) xcalloc(n, 1)
|
15
|
-
#define frt_erealloc xrealloc
|
16
|
-
|
17
|
-
#endif
|
@@ -1,29 +0,0 @@
|
|
1
|
-
#ifndef FRT_THREADING_H
|
2
|
-
#define FRT_THREADING_H
|
3
|
-
|
4
|
-
#include "frt_hash.h"
|
5
|
-
#define UNTHREADED 1
|
6
|
-
|
7
|
-
typedef void * frt_mutex_t;
|
8
|
-
typedef struct FrtHash *frt_thread_key_t;
|
9
|
-
typedef int frt_thread_once_t;
|
10
|
-
#define FRT_MUTEX_INITIALIZER NULL
|
11
|
-
#define FRT_THREAD_ONCE_INIT 1;
|
12
|
-
#define frt_mutex_init(a, b)
|
13
|
-
#define frt_mutex_lock(a)
|
14
|
-
#define frt_mutex_trylock(a)
|
15
|
-
#define frt_mutex_unlock(a)
|
16
|
-
#define frt_mutex_destroy(a)
|
17
|
-
#define frt_thread_key_create(a, b) frb_thread_key_create(a, b)
|
18
|
-
#define frt_thread_key_delete(a) frb_thread_key_delete(a)
|
19
|
-
#define frt_thread_setspecific(a, b) frb_thread_setspecific(a, b)
|
20
|
-
#define frt_thread_getspecific(a) frb_thread_getspecific(a)
|
21
|
-
#define frt_thread_once(a, b) frb_thread_once(a, b)
|
22
|
-
|
23
|
-
void frb_thread_once(int *once_control, void (*init_routine)(void));
|
24
|
-
void frb_thread_key_create(frt_thread_key_t *key, frt_free_ft destroy);
|
25
|
-
void frb_thread_key_delete(frt_thread_key_t key);
|
26
|
-
void frb_thread_setspecific(frt_thread_key_t key, const void *pointer);
|
27
|
-
void *frb_thread_getspecific(frt_thread_key_t key);
|
28
|
-
|
29
|
-
#endif
|
@@ -1,323 +0,0 @@
|
|
1
|
-
# frozen_string_literal: false
|
2
|
-
# = monitor.rb
|
3
|
-
#
|
4
|
-
# Copyright (C) 2001 Shugo Maeda <shugo@ruby-lang.org>
|
5
|
-
#
|
6
|
-
# This library is distributed under the terms of the Ruby license.
|
7
|
-
# You can freely distribute/modify this library.
|
8
|
-
#
|
9
|
-
|
10
|
-
#
|
11
|
-
# In concurrent programming, a monitor is an object or module intended to be
|
12
|
-
# used safely by more than one thread. The defining characteristic of a
|
13
|
-
# monitor is that its methods are executed with mutual exclusion. That is, at
|
14
|
-
# each point in time, at most one thread may be executing any of its methods.
|
15
|
-
# This mutual exclusion greatly simplifies reasoning about the implementation
|
16
|
-
# of monitors compared to reasoning about parallel code that updates a data
|
17
|
-
# structure.
|
18
|
-
#
|
19
|
-
# You can read more about the general principles on the Wikipedia page for
|
20
|
-
# Monitors[http://en.wikipedia.org/wiki/Monitor_%28synchronization%29]
|
21
|
-
#
|
22
|
-
# == Examples
|
23
|
-
#
|
24
|
-
# === Simple object.extend
|
25
|
-
#
|
26
|
-
# require 'monitor.rb'
|
27
|
-
#
|
28
|
-
# buf = []
|
29
|
-
# buf.extend(MonitorMixin)
|
30
|
-
# empty_cond = buf.new_cond
|
31
|
-
#
|
32
|
-
# # consumer
|
33
|
-
# Thread.start do
|
34
|
-
# loop do
|
35
|
-
# buf.synchronize do
|
36
|
-
# empty_cond.wait_while { buf.empty? }
|
37
|
-
# print buf.shift
|
38
|
-
# end
|
39
|
-
# end
|
40
|
-
# end
|
41
|
-
#
|
42
|
-
# # producer
|
43
|
-
# while line = ARGF.gets
|
44
|
-
# buf.synchronize do
|
45
|
-
# buf.push(line)
|
46
|
-
# empty_cond.signal
|
47
|
-
# end
|
48
|
-
# end
|
49
|
-
#
|
50
|
-
# The consumer thread waits for the producer thread to push a line to buf
|
51
|
-
# while <tt>buf.empty?</tt>. The producer thread (main thread) reads a
|
52
|
-
# line from ARGF and pushes it into buf then calls <tt>empty_cond.signal</tt>
|
53
|
-
# to notify the consumer thread of new data.
|
54
|
-
#
|
55
|
-
# === Simple Class include
|
56
|
-
#
|
57
|
-
# require 'monitor'
|
58
|
-
#
|
59
|
-
# class SynchronizedArray < Array
|
60
|
-
#
|
61
|
-
# include MonitorMixin
|
62
|
-
#
|
63
|
-
# def initialize(*args)
|
64
|
-
# super(*args)
|
65
|
-
# end
|
66
|
-
#
|
67
|
-
# alias :old_shift :shift
|
68
|
-
# alias :old_unshift :unshift
|
69
|
-
#
|
70
|
-
# def shift(n=1)
|
71
|
-
# self.synchronize do
|
72
|
-
# self.old_shift(n)
|
73
|
-
# end
|
74
|
-
# end
|
75
|
-
#
|
76
|
-
# def unshift(item)
|
77
|
-
# self.synchronize do
|
78
|
-
# self.old_unshift(item)
|
79
|
-
# end
|
80
|
-
# end
|
81
|
-
#
|
82
|
-
# # other methods ...
|
83
|
-
# end
|
84
|
-
#
|
85
|
-
# +SynchronizedArray+ implements an Array with synchronized access to items.
|
86
|
-
# This Class is implemented as subclass of Array which includes the
|
87
|
-
# MonitorMixin module.
|
88
|
-
#
|
89
|
-
module Isomorfeus
|
90
|
-
module Ferret
|
91
|
-
module MonitorMixin
|
92
|
-
#
|
93
|
-
# FIXME: This isn't documented in Nutshell.
|
94
|
-
#
|
95
|
-
# Since MonitorMixin.new_cond returns a ConditionVariable, and the example
|
96
|
-
# above calls while_wait and signal, this class should be documented.
|
97
|
-
#
|
98
|
-
class ConditionVariable
|
99
|
-
class Timeout < Exception; end
|
100
|
-
|
101
|
-
#
|
102
|
-
# Releases the lock held in the associated monitor and waits; reacquires the lock on wakeup.
|
103
|
-
#
|
104
|
-
# If +timeout+ is given, this method returns after +timeout+ seconds passed,
|
105
|
-
# even if no other thread doesn't signal.
|
106
|
-
#
|
107
|
-
def wait(timeout = nil)
|
108
|
-
Thread.handle_interrupt(Exception => :never) do
|
109
|
-
@monitor.__send__(:mon_check_owner)
|
110
|
-
count = @monitor.__send__(:mon_exit_for_cond)
|
111
|
-
begin
|
112
|
-
Thread.handle_interrupt(Exception => :immediate) do
|
113
|
-
@cond.wait(@monitor.instance_variable_get(:@mon_mutex), timeout)
|
114
|
-
end
|
115
|
-
return true
|
116
|
-
ensure
|
117
|
-
@monitor.__send__(:mon_enter_for_cond, count)
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
#
|
123
|
-
# Calls wait repeatedly while the given block yields a truthy value.
|
124
|
-
#
|
125
|
-
def wait_while
|
126
|
-
while yield
|
127
|
-
wait
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
#
|
132
|
-
# Calls wait repeatedly until the given block yields a truthy value.
|
133
|
-
#
|
134
|
-
def wait_until
|
135
|
-
until yield
|
136
|
-
wait
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
#
|
141
|
-
# Wakes up the first thread in line waiting for this lock.
|
142
|
-
#
|
143
|
-
def signal
|
144
|
-
@monitor.__send__(:mon_check_owner)
|
145
|
-
@cond.signal
|
146
|
-
end
|
147
|
-
|
148
|
-
#
|
149
|
-
# Wakes up all threads waiting for this lock.
|
150
|
-
#
|
151
|
-
def broadcast
|
152
|
-
@monitor.__send__(:mon_check_owner)
|
153
|
-
@cond.broadcast
|
154
|
-
end
|
155
|
-
|
156
|
-
private
|
157
|
-
|
158
|
-
def initialize(monitor)
|
159
|
-
@monitor = monitor
|
160
|
-
@cond = Thread::ConditionVariable.new
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
def self.extend_object(obj)
|
165
|
-
super(obj)
|
166
|
-
obj.__send__(:mon_initialize)
|
167
|
-
end
|
168
|
-
|
169
|
-
#
|
170
|
-
# Attempts to enter exclusive section. Returns +false+ if lock fails.
|
171
|
-
#
|
172
|
-
def mon_try_enter
|
173
|
-
if @mon_owner != Thread.current
|
174
|
-
unless @mon_mutex.try_lock
|
175
|
-
return false
|
176
|
-
end
|
177
|
-
@mon_owner = Thread.current
|
178
|
-
@mon_count = 0
|
179
|
-
end
|
180
|
-
@mon_count += 1
|
181
|
-
return true
|
182
|
-
end
|
183
|
-
# For backward compatibility
|
184
|
-
alias try_mon_enter mon_try_enter
|
185
|
-
|
186
|
-
#
|
187
|
-
# Enters exclusive section.
|
188
|
-
#
|
189
|
-
def mon_enter
|
190
|
-
if @mon_owner != Thread.current
|
191
|
-
@mon_mutex.lock
|
192
|
-
@mon_owner = Thread.current
|
193
|
-
@mon_count = 0
|
194
|
-
end
|
195
|
-
@mon_count += 1
|
196
|
-
end
|
197
|
-
|
198
|
-
#
|
199
|
-
# Leaves exclusive section.
|
200
|
-
#
|
201
|
-
def mon_exit
|
202
|
-
mon_check_owner
|
203
|
-
@mon_count -=1
|
204
|
-
if @mon_count == 0
|
205
|
-
@mon_owner = nil
|
206
|
-
@mon_mutex.unlock
|
207
|
-
end
|
208
|
-
end
|
209
|
-
|
210
|
-
#
|
211
|
-
# Returns true if this monitor is locked by any thread
|
212
|
-
#
|
213
|
-
def mon_locked?
|
214
|
-
@mon_mutex.locked?
|
215
|
-
end
|
216
|
-
|
217
|
-
#
|
218
|
-
# Returns true if this monitor is locked by current thread.
|
219
|
-
#
|
220
|
-
def mon_owned?
|
221
|
-
@mon_mutex.locked? && @mon_owner == Thread.current
|
222
|
-
end
|
223
|
-
|
224
|
-
#
|
225
|
-
# Enters exclusive section and executes the block. Leaves the exclusive
|
226
|
-
# section automatically when the block exits. See example under
|
227
|
-
# +MonitorMixin+.
|
228
|
-
#
|
229
|
-
def mon_synchronize
|
230
|
-
# Prevent interrupt on handling interrupts; for example timeout errors
|
231
|
-
# it may break locking state.
|
232
|
-
Thread.handle_interrupt(Exception => :never){ mon_enter }
|
233
|
-
begin
|
234
|
-
yield
|
235
|
-
ensure
|
236
|
-
Thread.handle_interrupt(Exception => :never){ mon_exit }
|
237
|
-
end
|
238
|
-
end
|
239
|
-
alias synchronize mon_synchronize
|
240
|
-
|
241
|
-
#
|
242
|
-
# Creates a new MonitorMixin::ConditionVariable associated with the
|
243
|
-
# receiver.
|
244
|
-
#
|
245
|
-
def new_cond
|
246
|
-
return ConditionVariable.new(self)
|
247
|
-
end
|
248
|
-
|
249
|
-
private
|
250
|
-
|
251
|
-
# Use <tt>extend MonitorMixin</tt> or <tt>include MonitorMixin</tt> instead
|
252
|
-
# of this constructor. Have look at the examples above to understand how to
|
253
|
-
# use this module.
|
254
|
-
def initialize(*args)
|
255
|
-
super
|
256
|
-
mon_initialize
|
257
|
-
end
|
258
|
-
|
259
|
-
# Initializes the MonitorMixin after being included in a class or when an
|
260
|
-
# object has been extended with the MonitorMixin
|
261
|
-
def mon_initialize
|
262
|
-
if defined?(@mon_mutex) && @mon_mutex_owner_object_id == object_id
|
263
|
-
raise ThreadError, "already initialized"
|
264
|
-
end
|
265
|
-
@mon_mutex = Thread::Mutex.new
|
266
|
-
@mon_mutex_owner_object_id = object_id
|
267
|
-
@mon_owner = nil
|
268
|
-
@mon_count = 0
|
269
|
-
end
|
270
|
-
|
271
|
-
def mon_check_owner
|
272
|
-
if @mon_owner != Thread.current
|
273
|
-
raise ThreadError, "current thread not owner"
|
274
|
-
end
|
275
|
-
end
|
276
|
-
|
277
|
-
def mon_enter_for_cond(count)
|
278
|
-
@mon_owner = Thread.current
|
279
|
-
@mon_count = count
|
280
|
-
end
|
281
|
-
|
282
|
-
def mon_exit_for_cond
|
283
|
-
count = @mon_count
|
284
|
-
@mon_owner = nil
|
285
|
-
@mon_count = 0
|
286
|
-
return count
|
287
|
-
end
|
288
|
-
end
|
289
|
-
|
290
|
-
# Use the Monitor class when you want to have a lock object for blocks with
|
291
|
-
# mutual exclusion.
|
292
|
-
#
|
293
|
-
# require 'monitor'
|
294
|
-
#
|
295
|
-
# lock = Monitor.new
|
296
|
-
# lock.synchronize do
|
297
|
-
# # exclusive access
|
298
|
-
# end
|
299
|
-
#
|
300
|
-
class Monitor
|
301
|
-
include MonitorMixin
|
302
|
-
alias try_enter try_mon_enter
|
303
|
-
alias enter mon_enter
|
304
|
-
alias exit mon_exit
|
305
|
-
end
|
306
|
-
end
|
307
|
-
end
|
308
|
-
|
309
|
-
# Documentation comments:
|
310
|
-
# - All documentation comes from Nutshell.
|
311
|
-
# - MonitorMixin.new_cond appears in the example, but is not documented in
|
312
|
-
# Nutshell.
|
313
|
-
# - All the internals (internal modules Accessible and Initializable, class
|
314
|
-
# ConditionVariable) appear in RDoc. It might be good to hide them, by
|
315
|
-
# making them private, or marking them :nodoc:, etc.
|
316
|
-
# - RDoc doesn't recognise aliases, so we have mon_synchronize documented, but
|
317
|
-
# not synchronize.
|
318
|
-
# - mon_owner is in Nutshell, but appears as an accessor in a separate module
|
319
|
-
# here, so is hard/impossible to RDoc. Some other useful accessors
|
320
|
-
# (mon_count and some queue stuff) are also in this module, and don't appear
|
321
|
-
# directly in the RDoc output.
|
322
|
-
# - in short, it may be worth changing the code layout in this file to make the
|
323
|
-
# documentation easier
|