fsdb 0.6.1 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +10 -0
- data/{README.txt → README.markdown} +137 -126
- data/bench/bench.rb +1 -1
- data/examples/forks.rb +43 -0
- data/lib/fsdb/database.rb +5 -16
- data/lib/fsdb/file-lock.rb +15 -58
- data/lib/fsdb/modex.rb +39 -42
- data/test/test-concurrency.rb +2 -2
- data/test/test-concurrency/init.rb +0 -4
- data/test/test-formats.rb +1 -1
- data/test/test-fsdb.rb +3 -1
- data/test/test-modex.rb +64 -20
- data/test/test.rb +1 -7
- metadata +56 -98
- data/ext/fsdb/MANIFEST +0 -1
- data/ext/fsdb/extconf.rb +0 -9
- data/ext/fsdb/fcntl-lock.c +0 -112
- data/lib/fsdb/compat.rb +0 -42
- data/lib/fsdb/faster-modex.rb +0 -223
- data/lib/fsdb/faster-mutex.rb +0 -138
- data/lib/fsdb/mutex.rb +0 -137
- data/rakefile +0 -41
- data/tasks/ann.rake +0 -80
- data/tasks/bones.rake +0 -20
- data/tasks/gem.rake +0 -201
- data/tasks/git.rake +0 -40
- data/tasks/notes.rake +0 -27
- data/tasks/post_load.rake +0 -34
- data/tasks/rdoc.rake +0 -51
- data/tasks/rubyforge.rake +0 -55
- data/tasks/setup.rb +0 -292
- data/tasks/spec.rake +0 -54
- data/tasks/svn.rake +0 -47
- data/tasks/test.rake +0 -40
- data/tasks/zentest.rake +0 -36
- data/test/err.txt +0 -31
- data/test/test-mutex.rb +0 -33
data/test/test.rb
CHANGED
@@ -8,15 +8,9 @@ $stderr.sync = true
|
|
8
8
|
|
9
9
|
Thread.abort_on_exception = true
|
10
10
|
|
11
|
-
if ARGV.delete("--fcntl-lock")
|
12
|
-
lock_type = :fcntl_lock
|
13
|
-
puts "Using fcntl lock"
|
14
|
-
require 'fcntl_lock'
|
15
|
-
end
|
16
|
-
|
17
11
|
tmp_dir = ENV['TMPDIR'] || ENV['TMP'] || 'tmp'
|
18
12
|
dir = File.join(tmp_dir, 'fsdb')
|
19
|
-
$db = Database.new(dir
|
13
|
+
$db = Database.new(dir)
|
20
14
|
|
21
15
|
mk_ext_pat = proc { |a| /\.(?:#{a.join("|")})$/i }
|
22
16
|
|
metadata
CHANGED
@@ -1,137 +1,95 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: fsdb
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.7.0
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
|
-
authors:
|
7
|
+
authors:
|
7
8
|
- Joel VanderWerf
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
12
|
+
date: 2011-12-06 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: ! 'A file system data base. Provides a thread-safe, process-safe Database
|
15
|
+
class.
|
11
16
|
|
12
|
-
date: 2009-07-18 00:00:00 -07:00
|
13
|
-
default_executable:
|
14
|
-
dependencies:
|
15
|
-
- !ruby/object:Gem::Dependency
|
16
|
-
name: bones
|
17
|
-
type: :development
|
18
|
-
version_requirement:
|
19
|
-
version_requirements: !ruby/object:Gem::Requirement
|
20
|
-
requirements:
|
21
|
-
- - ">="
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version: 2.5.1
|
24
|
-
version:
|
25
|
-
description: |
|
26
|
-
A file system data base. Provides a thread-safe, process-safe Database class.
|
27
17
|
Each entry is a separate file referenced by its relative path. Allows multiple
|
18
|
+
|
28
19
|
file formats and serialization methods. Pure ruby and very light weight.
|
29
20
|
|
21
|
+
'
|
30
22
|
email: vjoel@users.sourceforge.net
|
31
23
|
executables: []
|
32
|
-
|
33
|
-
|
34
|
-
- ext/fsdb/extconf.rb
|
35
|
-
extra_rdoc_files:
|
24
|
+
extensions: []
|
25
|
+
extra_rdoc_files:
|
36
26
|
- History.txt
|
37
|
-
- README.
|
38
|
-
|
39
|
-
files:
|
27
|
+
- README.markdown
|
28
|
+
files:
|
40
29
|
- History.txt
|
41
|
-
- README.
|
30
|
+
- README.markdown
|
42
31
|
- bench/bench.rb
|
43
|
-
- examples/client.rb
|
44
|
-
- examples/flat.rb
|
45
|
-
- examples/formats.rb
|
46
|
-
- examples/fsdb-example.rb
|
47
|
-
- examples/fsdb-examples.rb
|
48
32
|
- examples/indexes.rb
|
49
33
|
- examples/rbformat.rb
|
50
|
-
- examples/
|
51
|
-
- examples/simple.rb
|
34
|
+
- examples/formats.rb
|
52
35
|
- examples/yaml.rb
|
36
|
+
- examples/client.rb
|
37
|
+
- examples/forks.rb
|
38
|
+
- examples/flat.rb
|
39
|
+
- examples/simple.rb
|
53
40
|
- examples/yaml2.rb
|
54
|
-
-
|
55
|
-
-
|
56
|
-
-
|
41
|
+
- examples/server.rb
|
42
|
+
- examples/fsdb-examples.rb
|
43
|
+
- examples/fsdb-example.rb
|
57
44
|
- lib/fsdb.rb
|
58
|
-
- lib/fsdb/compat.rb
|
59
|
-
- lib/fsdb/database.rb
|
60
|
-
- lib/fsdb/delegatable.rb
|
61
|
-
- lib/fsdb/faster-modex.rb
|
62
|
-
- lib/fsdb/faster-mutex.rb
|
63
|
-
- lib/fsdb/file-lock.rb
|
64
|
-
- lib/fsdb/formats.rb
|
65
45
|
- lib/fsdb/formats/yaml.rb
|
66
46
|
- lib/fsdb/modex.rb
|
67
|
-
- lib/fsdb/
|
47
|
+
- lib/fsdb/read-write-object.rb
|
48
|
+
- lib/fsdb/formats.rb
|
49
|
+
- lib/fsdb/file-lock.rb
|
68
50
|
- lib/fsdb/nonpersistent-attr.rb
|
69
51
|
- lib/fsdb/persistent.rb
|
52
|
+
- lib/fsdb/util.rb
|
53
|
+
- lib/fsdb/delegatable.rb
|
70
54
|
- lib/fsdb/platform.rb
|
71
|
-
- lib/fsdb/
|
55
|
+
- lib/fsdb/database.rb
|
72
56
|
- lib/fsdb/server.rb
|
73
|
-
- lib/fsdb/util.rb
|
74
|
-
- rakefile
|
75
|
-
- tasks/ann.rake
|
76
|
-
- tasks/bones.rake
|
77
|
-
- tasks/gem.rake
|
78
|
-
- tasks/git.rake
|
79
|
-
- tasks/notes.rake
|
80
|
-
- tasks/post_load.rake
|
81
|
-
- tasks/rdoc.rake
|
82
|
-
- tasks/rubyforge.rake
|
83
|
-
- tasks/setup.rb
|
84
|
-
- tasks/spec.rake
|
85
|
-
- tasks/svn.rake
|
86
|
-
- tasks/test.rake
|
87
|
-
- tasks/zentest.rake
|
88
|
-
- test/err.txt
|
89
|
-
- test/runs.rb
|
90
|
-
- test/test-all.rb
|
91
|
-
- test/test-concurrency.rb
|
92
|
-
- test/test-concurrency/init.rb
|
93
|
-
- test/test-concurrency/test-object.rb
|
94
|
-
- test/test-file-lock.rb
|
95
|
-
- test/test-formats.rb
|
96
57
|
- test/test-fsdb.rb
|
97
|
-
- test/test-
|
98
|
-
- test/test-mutex.rb
|
58
|
+
- test/test-file-lock.rb
|
99
59
|
- test/test-util.rb
|
100
|
-
- test/test.rb
|
60
|
+
- test/test-modex.rb
|
101
61
|
- test/trap.rb
|
102
|
-
|
62
|
+
- test/test.rb
|
63
|
+
- test/test-concurrency/init.rb
|
64
|
+
- test/test-concurrency/test-object.rb
|
65
|
+
- test/test-formats.rb
|
66
|
+
- test/runs.rb
|
67
|
+
- test/test-concurrency.rb
|
68
|
+
- test/test-all.rb
|
103
69
|
homepage: http://rubyforge.org/projects/fsdb/
|
104
70
|
licenses: []
|
105
|
-
|
106
71
|
post_install_message:
|
107
|
-
rdoc_options:
|
72
|
+
rdoc_options:
|
108
73
|
- --main
|
109
|
-
- README.
|
110
|
-
require_paths:
|
74
|
+
- README.markdown
|
75
|
+
require_paths:
|
111
76
|
- lib
|
112
|
-
|
113
|
-
|
114
|
-
requirements:
|
115
|
-
- -
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version:
|
118
|
-
|
119
|
-
|
120
|
-
requirements:
|
121
|
-
- -
|
122
|
-
- !ruby/object:Gem::Version
|
123
|
-
version:
|
124
|
-
version:
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
none: false
|
79
|
+
requirements:
|
80
|
+
- - ! '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ! '>='
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
125
89
|
requirements: []
|
126
|
-
|
127
90
|
rubyforge_project: fsdb
|
128
|
-
rubygems_version: 1.
|
91
|
+
rubygems_version: 1.8.11
|
129
92
|
signing_key:
|
130
93
|
specification_version: 3
|
131
94
|
summary: File System Database
|
132
|
-
test_files:
|
133
|
-
- test/test-formats.rb
|
134
|
-
- test/test-concurrency.rb
|
135
|
-
- test/test-fsdb.rb
|
136
|
-
- test/test-modex.rb
|
137
|
-
- test/test-mutex.rb
|
95
|
+
test_files: []
|
data/ext/fsdb/MANIFEST
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
fcntl-lock.c
|
data/ext/fsdb/extconf.rb
DELETED
@@ -1,9 +0,0 @@
|
|
1
|
-
require 'mkmf'
|
2
|
-
|
3
|
-
if have_func("flock")
|
4
|
-
create_makefile 'fcntl_lock'
|
5
|
-
else
|
6
|
-
puts "fcntl_lock option not available on this platform. Please ignore"
|
7
|
-
puts "the error message after running 'ruby intall.rb setup' and"
|
8
|
-
puts "proceed to the installation step, 'ruby install.rb install'."
|
9
|
-
end
|
data/ext/fsdb/fcntl-lock.c
DELETED
@@ -1,112 +0,0 @@
|
|
1
|
-
// Copyright (c) 2003 Ara Howard. Ruby license, I assume?
|
2
|
-
|
3
|
-
#ifdef _WIN32
|
4
|
-
#include "missing/file.h"
|
5
|
-
#endif
|
6
|
-
|
7
|
-
#include "ruby.h"
|
8
|
-
#include "rubyio.h"
|
9
|
-
#include "rubysig.h"
|
10
|
-
|
11
|
-
#ifdef HAVE_UNISTD_H
|
12
|
-
#include <unistd.h>
|
13
|
-
#endif
|
14
|
-
|
15
|
-
#ifdef HAVE_FCNTL_H
|
16
|
-
#include <fcntl.h>
|
17
|
-
#endif
|
18
|
-
|
19
|
-
#include <errno.h>
|
20
|
-
|
21
|
-
extern VALUE rb_cFile;
|
22
|
-
|
23
|
-
# ifndef LOCK_SH
|
24
|
-
# define LOCK_SH 1
|
25
|
-
# endif
|
26
|
-
# ifndef LOCK_EX
|
27
|
-
# define LOCK_EX 2
|
28
|
-
# endif
|
29
|
-
# ifndef LOCK_NB
|
30
|
-
# define LOCK_NB 4
|
31
|
-
# endif
|
32
|
-
# ifndef LOCK_UN
|
33
|
-
# define LOCK_UN 8
|
34
|
-
# endif
|
35
|
-
|
36
|
-
static int
|
37
|
-
fcntl_lock (fd, operation)
|
38
|
-
int fd;
|
39
|
-
int operation;
|
40
|
-
{
|
41
|
-
struct flock lock;
|
42
|
-
|
43
|
-
switch (operation & ~LOCK_NB)
|
44
|
-
{
|
45
|
-
case LOCK_SH:
|
46
|
-
lock.l_type = F_RDLCK;
|
47
|
-
break;
|
48
|
-
case LOCK_EX:
|
49
|
-
lock.l_type = F_WRLCK;
|
50
|
-
break;
|
51
|
-
case LOCK_UN:
|
52
|
-
lock.l_type = F_UNLCK;
|
53
|
-
break;
|
54
|
-
default:
|
55
|
-
errno = EINVAL;
|
56
|
-
return -1;
|
57
|
-
}
|
58
|
-
lock.l_whence = SEEK_SET;
|
59
|
-
lock.l_start = lock.l_len = 0L;
|
60
|
-
return fcntl (fd, (operation & LOCK_NB) ? F_SETLK : F_SETLKW, &lock);
|
61
|
-
}
|
62
|
-
|
63
|
-
|
64
|
-
static VALUE
|
65
|
-
rb_file_fcntl_lock (obj, operation)
|
66
|
-
VALUE obj;
|
67
|
-
VALUE operation;
|
68
|
-
{
|
69
|
-
#ifndef __CHECKER__
|
70
|
-
OpenFile *fptr;
|
71
|
-
int ret;
|
72
|
-
|
73
|
-
rb_secure (2);
|
74
|
-
GetOpenFile (obj, fptr);
|
75
|
-
|
76
|
-
if (fptr->mode & FMODE_WRITABLE)
|
77
|
-
{
|
78
|
-
fflush (GetWriteFile (fptr));
|
79
|
-
}
|
80
|
-
retry:
|
81
|
-
TRAP_BEG;
|
82
|
-
ret = fcntl_lock (fileno (fptr->f), NUM2INT (operation));
|
83
|
-
TRAP_END;
|
84
|
-
if (ret < 0)
|
85
|
-
{
|
86
|
-
switch (errno)
|
87
|
-
{
|
88
|
-
case EAGAIN:
|
89
|
-
case EACCES:
|
90
|
-
#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
|
91
|
-
case EWOULDBLOCK:
|
92
|
-
#endif
|
93
|
-
return Qfalse;
|
94
|
-
case EINTR:
|
95
|
-
#if defined(ERESTART)
|
96
|
-
case ERESTART:
|
97
|
-
#endif
|
98
|
-
goto retry;
|
99
|
-
}
|
100
|
-
rb_sys_fail (fptr->path);
|
101
|
-
}
|
102
|
-
#endif
|
103
|
-
|
104
|
-
return INT2FIX (0);
|
105
|
-
}
|
106
|
-
|
107
|
-
|
108
|
-
void
|
109
|
-
Init_fcntl_lock()
|
110
|
-
{
|
111
|
-
rb_define_method(rb_cFile, "fcntl_lock", rb_file_fcntl_lock, 1);
|
112
|
-
}
|
data/lib/fsdb/compat.rb
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
unless defined? Process.times
|
2
|
-
def Process.times; Time.times; end
|
3
|
-
end
|
4
|
-
|
5
|
-
unless defined? [].any?
|
6
|
-
module Enumerable
|
7
|
-
def any?
|
8
|
-
each {|x| return true if yield x}
|
9
|
-
false
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
unless defined? [].inject
|
15
|
-
module Enumerable
|
16
|
-
def inject n
|
17
|
-
each { |i|
|
18
|
-
n = yield n, i
|
19
|
-
}
|
20
|
-
n
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
unless Dir.chdir {:worked} == :worked
|
26
|
-
class << Dir
|
27
|
-
alias old_chdir chdir
|
28
|
-
def chdir(*args)
|
29
|
-
if block_given?
|
30
|
-
begin
|
31
|
-
old_dir = Dir.pwd
|
32
|
-
old_chdir(*args)
|
33
|
-
yield
|
34
|
-
ensure
|
35
|
-
old_chdir(old_dir)
|
36
|
-
end
|
37
|
-
else
|
38
|
-
old_chdir(*args)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
data/lib/fsdb/faster-modex.rb
DELETED
@@ -1,223 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
### only use this if you can ensure Thread.critical is not already set!
|
4
|
-
|
5
|
-
# Make sure we use the fast definition, not the thread.rb one!
|
6
|
-
class Thread # :nodoc:
|
7
|
-
def self.exclusive
|
8
|
-
old = critical
|
9
|
-
self.critical = true
|
10
|
-
yield
|
11
|
-
ensure
|
12
|
-
self.critical = old
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
class Thread
|
17
|
-
def self.nonexclusive
|
18
|
-
old = critical
|
19
|
-
self.critical = false
|
20
|
-
yield
|
21
|
-
ensure
|
22
|
-
self.critical = old
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
module FSDB
|
27
|
-
|
28
|
-
# Modex is a modal exclusion semaphore, like in syncronizer.rb.
|
29
|
-
# The two modes are shared (SH) and exclusive (EX).
|
30
|
-
# Modex is not nestable.
|
31
|
-
#
|
32
|
-
class Modex
|
33
|
-
SH = :SH
|
34
|
-
EX = :EX
|
35
|
-
|
36
|
-
def initialize
|
37
|
-
@waiting = []
|
38
|
-
@locked = []
|
39
|
-
@mode = nil
|
40
|
-
@first = true
|
41
|
-
end
|
42
|
-
|
43
|
-
def try_lock mode
|
44
|
-
Thread.critical = true
|
45
|
-
thread = Thread.current
|
46
|
-
if @locked.include?(thread)
|
47
|
-
Thread.critical = false
|
48
|
-
raise ThreadError
|
49
|
-
end
|
50
|
-
|
51
|
-
if @mode == mode and mode == SH and @waiting.empty? # strict queue
|
52
|
-
@locked << thread
|
53
|
-
rslt = true
|
54
|
-
elsif not @mode
|
55
|
-
@mode = mode
|
56
|
-
@locked << thread
|
57
|
-
rslt = true
|
58
|
-
end
|
59
|
-
Thread.critical = false
|
60
|
-
rslt
|
61
|
-
end
|
62
|
-
|
63
|
-
# the block is executed in the exclusive context
|
64
|
-
def lock mode
|
65
|
-
Thread.critical = true
|
66
|
-
thread = Thread.current
|
67
|
-
if @locked.include?(thread)
|
68
|
-
Thread.critical = false
|
69
|
-
raise ThreadError
|
70
|
-
end
|
71
|
-
|
72
|
-
if @mode == mode and mode == SH and @waiting.empty? # strict queue
|
73
|
-
@locked << thread
|
74
|
-
elsif not @mode
|
75
|
-
@mode = mode
|
76
|
-
@locked << thread
|
77
|
-
else
|
78
|
-
@waiting << thread << mode
|
79
|
-
Thread.stop
|
80
|
-
Thread.critical = true
|
81
|
-
end
|
82
|
-
|
83
|
-
yield if block_given?
|
84
|
-
|
85
|
-
# if @mode != mode
|
86
|
-
# raise "@mode == #{@mode} but mode == #{mode}"
|
87
|
-
# end
|
88
|
-
#
|
89
|
-
# if @mode == EX and @locked.size > 1
|
90
|
-
# raise "@mode == EX but @locked.size == #{@locked.size}"
|
91
|
-
# end
|
92
|
-
|
93
|
-
Thread.critical = false
|
94
|
-
self
|
95
|
-
end
|
96
|
-
|
97
|
-
# the block is executed in the exclusive context
|
98
|
-
def unlock
|
99
|
-
raise ThreadError unless @mode
|
100
|
-
|
101
|
-
Thread.critical = true
|
102
|
-
yield if block_given?
|
103
|
-
@locked.delete Thread.current
|
104
|
-
wake_next_waiter if @locked.empty?
|
105
|
-
Thread.critical = false
|
106
|
-
|
107
|
-
self
|
108
|
-
end
|
109
|
-
|
110
|
-
def synchronize mode, do_when_first = nil, do_when_last = nil, arg = nil
|
111
|
-
lock mode do
|
112
|
-
if @first
|
113
|
-
@first = false
|
114
|
-
|
115
|
-
if do_when_first
|
116
|
-
if mode == SH
|
117
|
-
@mode = EX
|
118
|
-
end
|
119
|
-
|
120
|
-
Thread.critical = false; do_when_first[arg]; Thread.critical = true
|
121
|
-
|
122
|
-
if mode == SH
|
123
|
-
@mode = SH
|
124
|
-
wake_waiting_sharers
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
yield
|
131
|
-
|
132
|
-
ensure
|
133
|
-
unlock do
|
134
|
-
if @locked.size == 1
|
135
|
-
if do_when_last
|
136
|
-
@mode = EX
|
137
|
-
Thread.critical = false; do_when_last[arg]; Thread.critical = true
|
138
|
-
end
|
139
|
-
@first = true
|
140
|
-
end
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
def remove_dead # :nodoc:
|
145
|
-
Thread.exclusive do
|
146
|
-
waiting = @waiting; @waiting = []
|
147
|
-
until waiting.empty?
|
148
|
-
|
149
|
-
t = waiting.shift; m = waiting.shift
|
150
|
-
@waiting << t << m if t.alive?
|
151
|
-
end
|
152
|
-
|
153
|
-
@locked = @locked.select {|t| t.alive?}
|
154
|
-
wake_next_waiter if @locked.empty?
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
private
|
159
|
-
def wake_next_waiter
|
160
|
-
first = @waiting.shift; @mode = @waiting.shift && EX
|
161
|
-
if first
|
162
|
-
first.wakeup
|
163
|
-
@locked << first
|
164
|
-
end
|
165
|
-
first
|
166
|
-
rescue ThreadError
|
167
|
-
retry
|
168
|
-
end
|
169
|
-
|
170
|
-
def wake_waiting_sharers
|
171
|
-
while @waiting[1] == SH # note strict queue order
|
172
|
-
t = @waiting.shift; @waiting.shift
|
173
|
-
@locked << t
|
174
|
-
t.wakeup
|
175
|
-
end
|
176
|
-
rescue ThreadError
|
177
|
-
retry
|
178
|
-
end
|
179
|
-
|
180
|
-
module ForkSafely
|
181
|
-
def fork # :nodoc:
|
182
|
-
super do
|
183
|
-
ObjectSpace.each_object(Modex) { |m| m.remove_dead }
|
184
|
-
yield
|
185
|
-
end
|
186
|
-
end
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
# FSDB users who fork should include ForkSafely or FSDB itself. (The reason for
|
191
|
-
# this is that the fork may inherit some dead threads from the parent, and if
|
192
|
-
# they hold any locks, you may get a deadlock. ForkSafely modifies fork so that
|
193
|
-
# these dead threads are cleared. If you use modexes (outside of those in FSDB),
|
194
|
-
# they should be FSDB::Modexes.
|
195
|
-
module ForkSafely
|
196
|
-
include Modex::ForkSafely
|
197
|
-
end
|
198
|
-
include ForkSafely
|
199
|
-
|
200
|
-
end # module FSDB
|
201
|
-
|
202
|
-
|
203
|
-
if __FILE__ == $0
|
204
|
-
# Stress test is in fsdb/test/test-modex.rb. This is just to show fork usage.
|
205
|
-
|
206
|
-
include FSDB::ForkSafely
|
207
|
-
|
208
|
-
m = FSDB::Modex.new
|
209
|
-
|
210
|
-
SH = FSDB::Modex::SH
|
211
|
-
|
212
|
-
Thread.new { m.synchronize(SH) { sleep 1 } }
|
213
|
-
|
214
|
-
fork do
|
215
|
-
m.synchronize(SH) do
|
216
|
-
puts "Didn't get here if you used standard mutex or fork."
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
m.synchronize(SH) { puts "Got here." }
|
221
|
-
|
222
|
-
Process.wait
|
223
|
-
end
|