isomorfeus-ferret 0.13.2 → 0.13.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a1a8509c12f5d180d38944adb53291958a9f8327a8b1706def9fecd7f9c60e73
4
- data.tar.gz: fbbd38e08dd1992cd93663b1b04cc4b666b6a6dc59104414b75515bc2ec4d54d
3
+ metadata.gz: 1f2a4a6ea097a25d4d32a958c730fffca81ded61133f37ef4c86ca5b78ecef77
4
+ data.tar.gz: 7be1f98b64559be5f02e39d7a74894476046fef3fdd46d1e69ee3079c74c9681
5
5
  SHA512:
6
- metadata.gz: 7158cdc3f7a0624d35b668b31287d489ee3d389f17a2ab1b58235a7c2be639b6a7bbb3a8c0efee6d168804128fa5c0d7955c00f860b653a76f23d6421fc84c5d
7
- data.tar.gz: 60c62db42081291a52e66be4b7e1b4c46eb12a458b0838f3d8793ffaeb013aff27a37aca06ab4831157d1dd65330395bfdaa2fa7924a278261f1187295592042
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
- ### Sring Encoding support
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 Filters
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
- The benefit is, that Filters, Stemmers or anything else working with Tokens only needs to support UTF-8 encoding,
45
- greatly simplifying things and ensuring consistent query results.
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
- FRT_RAISE(FRT_UNSUPPORTED_ERROR, "gettimeofday failed\n");
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
- FRT_RAISE(FRT_UNSUPPORTED_ERROR, "gettimeofday failed\n");
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 fi->rfi;
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 fis->rfis;
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
- frb_iw_field_infos(VALUE self)
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
- frb_ir_field_infos(VALUE self)
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
 
@@ -19,7 +19,6 @@ const char *const ERROR_TYPES[] = {
19
19
  "Lock Error"
20
20
  };
21
21
 
22
- bool frt_x_do_logging = false;
23
22
  bool frt_x_abort_on_exception = true;
24
23
  bool frt_x_has_aborted = false;
25
24
  FILE *frt_x_exception_stream = NULL;
@@ -418,9 +418,7 @@ static void fs_close_lock_i(FrtLock *lock)
418
418
 
419
419
  static FrtHash *stores = NULL;
420
420
 
421
- #ifndef UNTHREADED
422
421
  static frt_mutex_t stores_mutex = FRT_MUTEX_INITIALIZER;
423
- #endif
424
422
 
425
423
  static void fs_close_i(FrtStore *store)
426
424
  {
@@ -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
- /* void micro_sleep(const int micro_seconds)
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);
@@ -5,7 +5,7 @@
5
5
  #include "frt_global.h"
6
6
  #include "frt_hash.h"
7
7
  #include "frt_hashset.h"
8
- #include "frb_threading.h"
8
+ #include "frt_threading.h"
9
9
 
10
10
  #define FRT_LOCK_PREFIX "ferret-"
11
11
  #define FRT_LOCK_EXT ".lck"
@@ -4,8 +4,8 @@
4
4
  #include "frt_except.h"
5
5
  #include "frt_hash.h"
6
6
  #include "frt_hashset.h"
7
- #include "frb_threading.h"
8
- #include "frb_lang.h"
7
+ #include "frt_threading.h"
8
+ #include "ruby.h"
9
9
 
10
10
  /* IDs */
11
11
  ID id_new;
@@ -1,10 +1,9 @@
1
1
  #ifndef __FERRET_H_
2
2
  #define __FERRET_H_
3
- #include <ruby.h>
4
3
  #include "frt_global.h"
5
4
  #include "frt_hashset.h"
6
5
  #include "frt_document.h"
7
- #include "frb_lang.h"
6
+ #include <ruby.h>
8
7
 
9
8
  /* IDs */
10
9
  extern ID id_new;
@@ -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
- // tst_run_test(suite, test_threading, index);
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 Isomorfeus::Ferret::MonitorMixin
7
+ include MonitorMixin
8
8
  include Isomorfeus::Ferret::Store
9
9
  include Isomorfeus::Ferret::Search
10
10
 
@@ -1,5 +1,5 @@
1
1
  module Isomorfeus
2
2
  module Ferret
3
- VERSION = '0.13.2'
3
+ VERSION = '0.13.5'
4
4
  end
5
5
  end
@@ -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 'isomorfeus/ferret/monitor'
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.2
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-18 00:00:00.000000000 Z
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,9 +0,0 @@
1
- #include "frt_except.h"
2
- #include "frb_lang.h"
3
-
4
- struct timeval rb_time_interval _((VALUE));
5
-
6
- extern void frt_micro_sleep(const int micro_seconds)
7
- {
8
- rb_thread_wait_for(rb_time_interval(rb_float_new((double)micro_seconds/1000000.0)));
9
- }
@@ -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