fsdb 0.6.1 → 0.7.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.
- 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
|