posix-semaphore 0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README +11 -0
- data/ext/extconf.rb +11 -0
- data/ext/posix-semaphore.c +128 -0
- data/lib/posix-semaphore.rb +3 -0
- data/lib/posix/semaphore.rb +66 -0
- data/lib/posix/semaphore/mutex.rb +51 -0
- data/posix-semaphore.gemspec +29 -0
- metadata +52 -0
data/README
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
.. /\
|
2
|
+
||/ /
|
3
|
+
| /
|
4
|
+
| /
|
5
|
+
___ ___ ___ _____ ___ _ ___ _
|
6
|
+
| _ \/ _ \/ __|_ _\ \/ (_|_) __| ___ _ __ __ _ _ __| |_ ___ _ _ ___
|
7
|
+
| _/ (_) \__ \| | > < _ _\__ \/ -_) ' \/ _` | '_ \ ' \/ _ \ '_/ -_)
|
8
|
+
|_| \___/|___/___/_/\_(_|_)___/\___|_|_|_\__,_| .__/_||_\___/_| \___|
|
9
|
+
|_|
|
10
|
+
|
11
|
+
Currently only named semaphores are supported.
|
data/ext/extconf.rb
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
|
2
|
+
#include "ruby.h"
|
3
|
+
#include <semaphore.h>
|
4
|
+
#include <time.h>
|
5
|
+
#include <errno.h>
|
6
|
+
|
7
|
+
VALUE mPOSIX = Qnil;
|
8
|
+
|
9
|
+
void Init_posix_semaphore_ext();
|
10
|
+
VALUE method_sem_open(int argc, VALUE* argv, VALUE self);
|
11
|
+
VALUE method_sem_wait(VALUE self, VALUE semid);
|
12
|
+
VALUE method_sem_trywait(VALUE self, VALUE semid);
|
13
|
+
VALUE method_sem_timedwait(VALUE self, VALUE semid, VALUE timeout);
|
14
|
+
VALUE method_sem_post(VALUE self, VALUE semid);
|
15
|
+
VALUE method_sem_close(VALUE self, VALUE semid);
|
16
|
+
// VALUE method_sem_getvalue(VALUE self, VALUE semid);
|
17
|
+
VALUE method_sem_unlink(VALUE self, VALUE semid);
|
18
|
+
|
19
|
+
void Init_posix_semaphore_ext() {
|
20
|
+
mPOSIX = rb_define_module("POSIX");
|
21
|
+
rb_define_singleton_method(mPOSIX, "sem_open", method_sem_open, -1);
|
22
|
+
rb_define_singleton_method(mPOSIX, "sem_wait", method_sem_wait, 1);
|
23
|
+
rb_define_singleton_method(mPOSIX, "sem_trywait", method_sem_trywait, 1);
|
24
|
+
rb_define_singleton_method(mPOSIX, "sem_timedwait", method_sem_timedwait, 2);
|
25
|
+
rb_define_singleton_method(mPOSIX, "sem_post", method_sem_post, 1);
|
26
|
+
rb_define_singleton_method(mPOSIX, "sem_close", method_sem_close, 1);
|
27
|
+
// rb_define_singleton_method(mPOSIX, "sem_getvalue", method_sem_getvalue, 1);
|
28
|
+
rb_define_singleton_method(mPOSIX, "sem_unlink", method_sem_unlink, 1);
|
29
|
+
}
|
30
|
+
|
31
|
+
VALUE method_sem_open(int argc, VALUE *argv, VALUE self) {
|
32
|
+
if (argc < 2 || argc > 4) {
|
33
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%d for 2..4)", argc);
|
34
|
+
}
|
35
|
+
VALUE name = argv[0];
|
36
|
+
VALUE oflag = argv[1];
|
37
|
+
Check_Type(name, T_STRING);
|
38
|
+
Check_Type(oflag, T_FIXNUM);
|
39
|
+
sem_t* semaphore;
|
40
|
+
|
41
|
+
if (argc == 2) {
|
42
|
+
semaphore = sem_open(StringValueCStr(name), FIX2INT(oflag));
|
43
|
+
} else {
|
44
|
+
VALUE mode = argv[2];
|
45
|
+
VALUE value;
|
46
|
+
if (argc == 4) {
|
47
|
+
value = argv[3];
|
48
|
+
} else {
|
49
|
+
value = INT2FIX(1);
|
50
|
+
}
|
51
|
+
Check_Type(mode, T_FIXNUM);
|
52
|
+
Check_Type(value, T_FIXNUM);
|
53
|
+
semaphore = sem_open(StringValueCStr(name), FIX2INT(oflag), FIX2INT(mode), FIX2INT(value));
|
54
|
+
}
|
55
|
+
|
56
|
+
if (semaphore == SEM_FAILED) {
|
57
|
+
rb_sys_fail(0);
|
58
|
+
}
|
59
|
+
|
60
|
+
return INT2FIX(semaphore);
|
61
|
+
}
|
62
|
+
|
63
|
+
VALUE method_sem_wait(VALUE self, VALUE semid) {
|
64
|
+
Check_Type(semid, T_FIXNUM);
|
65
|
+
|
66
|
+
int result = sem_wait((sem_t*) FIX2LONG(semid));
|
67
|
+
if (result < 0) rb_sys_fail(0);
|
68
|
+
|
69
|
+
return INT2FIX(result);
|
70
|
+
}
|
71
|
+
|
72
|
+
VALUE method_sem_trywait(VALUE self, VALUE semid) {
|
73
|
+
Check_Type(semid, T_FIXNUM);
|
74
|
+
|
75
|
+
int result = sem_trywait((sem_t*) FIX2LONG(semid));
|
76
|
+
if (result < 0) rb_sys_fail(0);
|
77
|
+
|
78
|
+
return INT2FIX(result);
|
79
|
+
}
|
80
|
+
|
81
|
+
VALUE method_sem_timedwait(VALUE self, VALUE semid, VALUE timeout) {
|
82
|
+
Check_Type(semid, T_FIXNUM);
|
83
|
+
|
84
|
+
struct timespec ts = rb_time_timespec(timeout);
|
85
|
+
|
86
|
+
int result = sem_timedwait((sem_t*) FIX2LONG(semid), &ts);
|
87
|
+
if (result < 0) rb_sys_fail(0);
|
88
|
+
|
89
|
+
return INT2FIX(result);
|
90
|
+
}
|
91
|
+
|
92
|
+
VALUE method_sem_post(VALUE self, VALUE semid) {
|
93
|
+
Check_Type(semid, T_FIXNUM);
|
94
|
+
|
95
|
+
int result = sem_post((sem_t*) FIX2LONG(semid));
|
96
|
+
if (result < 0) rb_sys_fail(0);
|
97
|
+
|
98
|
+
return INT2FIX(result);
|
99
|
+
}
|
100
|
+
|
101
|
+
VALUE method_sem_close(VALUE self, VALUE semid) {
|
102
|
+
Check_Type(semid, T_FIXNUM);
|
103
|
+
|
104
|
+
int result = sem_close((sem_t*) FIX2LONG(semid));
|
105
|
+
if (result < 0) rb_sys_fail(0);
|
106
|
+
|
107
|
+
return INT2FIX(result);
|
108
|
+
}
|
109
|
+
|
110
|
+
// diked out, too buggy
|
111
|
+
// VALUE method_sem_getvalue(VALUE self, VALUE semid) {
|
112
|
+
// Check_Type(semid, T_FIXNUM);
|
113
|
+
// int sval;
|
114
|
+
//
|
115
|
+
// int result = sem_getvalue((sem_t*) FIX2LONG(semid), &sval);
|
116
|
+
// if (result < 0) rb_sys_fail(0);
|
117
|
+
//
|
118
|
+
// return INT2FIX(sval);
|
119
|
+
// }
|
120
|
+
|
121
|
+
VALUE method_sem_unlink(VALUE self, VALUE name) {
|
122
|
+
Check_Type(name, T_STRING);
|
123
|
+
|
124
|
+
int result = sem_unlink(StringValueCStr(name));
|
125
|
+
if (result < 0) rb_sys_fail(0);
|
126
|
+
|
127
|
+
return INT2FIX(result);
|
128
|
+
}
|
@@ -0,0 +1,66 @@
|
|
1
|
+
|
2
|
+
require 'posix_semaphore_ext'
|
3
|
+
require 'posix/semaphore/mutex'
|
4
|
+
|
5
|
+
module POSIX
|
6
|
+
class Semaphore
|
7
|
+
attr_reader :id, :name
|
8
|
+
|
9
|
+
def initialize name, mode=File::CREAT, perms=0611, value=1
|
10
|
+
@id = POSIX.sem_open name, mode, perms, value
|
11
|
+
@name = name
|
12
|
+
end
|
13
|
+
|
14
|
+
def wait timeout=nil
|
15
|
+
if timeout.nil?
|
16
|
+
POSIX.sem_wait @id
|
17
|
+
true
|
18
|
+
else
|
19
|
+
begin
|
20
|
+
if timeout.is_a? Numeric
|
21
|
+
timeout = Time.now + timeout
|
22
|
+
elsif defined? DateTime and timeout.is_a? DateTime
|
23
|
+
timeout = timeout.to_time
|
24
|
+
end
|
25
|
+
POSIX.sem_timedwait @id, timeout
|
26
|
+
rescue Errno::ETIMEDOUT
|
27
|
+
return false
|
28
|
+
rescue
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
def wait_nonblock
|
33
|
+
POSIX.sem_trywait @id
|
34
|
+
end
|
35
|
+
|
36
|
+
def post
|
37
|
+
POSIX.sem_post @id
|
38
|
+
end
|
39
|
+
|
40
|
+
def close
|
41
|
+
POSIX.sem_close @id
|
42
|
+
end
|
43
|
+
def unlink
|
44
|
+
self.class.unlink @name
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.unlink name
|
48
|
+
POSIX.sem_unlink name
|
49
|
+
end
|
50
|
+
|
51
|
+
def zero?
|
52
|
+
begin
|
53
|
+
wait_nonblock
|
54
|
+
rescue Errno::EAGAIN
|
55
|
+
return true
|
56
|
+
end
|
57
|
+
post
|
58
|
+
return false
|
59
|
+
end
|
60
|
+
alias locked? zero?
|
61
|
+
|
62
|
+
def inspect
|
63
|
+
"#<#{self.class.name}:#@id name:#{@name.inspect}>"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
|
2
|
+
module POSIX
|
3
|
+
class Semaphore
|
4
|
+
# Mutex provides a simple wrapper to provide a POSIX-based version
|
5
|
+
# of Ruby's built-in Mutex class.
|
6
|
+
#
|
7
|
+
# All you need to do to switch from using Ruby's Mutex to using this
|
8
|
+
# is change Mutex.new to POSIX::Semaphore::Mutex.new, providing
|
9
|
+
# options that are the same as those to POSIX::Semaphore.new.
|
10
|
+
class Mutex
|
11
|
+
def initialize *args
|
12
|
+
@semaphore = Semaphore.new *args
|
13
|
+
@have_lock = false
|
14
|
+
end
|
15
|
+
|
16
|
+
def lock *a
|
17
|
+
raise ThreadError, 'this mutex is already locked to us' if @have_lock
|
18
|
+
@semaphore.wait *a
|
19
|
+
@have_lock = true
|
20
|
+
end
|
21
|
+
def locked?
|
22
|
+
@have_lock or @semaphore.locked?
|
23
|
+
end
|
24
|
+
|
25
|
+
def synchronize *a
|
26
|
+
lock *a
|
27
|
+
begin
|
28
|
+
yield
|
29
|
+
ensure
|
30
|
+
unlock
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def try_lock
|
35
|
+
raise ThreadError, 'this mutex is already locked to us' if @have_lock
|
36
|
+
begin
|
37
|
+
@semaphore.wait_nonblock
|
38
|
+
rescue Errno::EAGAIN
|
39
|
+
return false
|
40
|
+
end
|
41
|
+
return (@have_lock = true)
|
42
|
+
end
|
43
|
+
|
44
|
+
def unlock
|
45
|
+
@semaphore.post
|
46
|
+
@have_lock = false
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
Gem::Specification.new do |s|
|
3
|
+
s.name = 'posix-semaphore'
|
4
|
+
s.version = '0.5'
|
5
|
+
|
6
|
+
s.summary = 'Access to the POSIX semaphore APIs in Ruby'
|
7
|
+
s.description = 'Cross-thread, cross-process synchronisation made tolerably easy'
|
8
|
+
|
9
|
+
s.homepage = 'http://github.com/dpkendal/posix-semaphore'
|
10
|
+
|
11
|
+
s.authors = ['David Kendal']
|
12
|
+
|
13
|
+
s.extensions = ['ext/extconf.rb']
|
14
|
+
s.require_paths = ['lib']
|
15
|
+
|
16
|
+
s.files = %w{
|
17
|
+
ext
|
18
|
+
ext/extconf.rb
|
19
|
+
ext/posix-semaphore.c
|
20
|
+
lib
|
21
|
+
lib/posix
|
22
|
+
lib/posix/semaphore
|
23
|
+
lib/posix/semaphore/mutex.rb
|
24
|
+
lib/posix/semaphore.rb
|
25
|
+
lib/posix-semaphore.rb
|
26
|
+
posix-semaphore.gemspec
|
27
|
+
README
|
28
|
+
}
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: posix-semaphore
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.5'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- David Kendal
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-01-02 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Cross-thread, cross-process synchronisation made tolerably easy
|
15
|
+
email:
|
16
|
+
executables: []
|
17
|
+
extensions:
|
18
|
+
- ext/extconf.rb
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- ext/extconf.rb
|
22
|
+
- ext/posix-semaphore.c
|
23
|
+
- lib/posix/semaphore/mutex.rb
|
24
|
+
- lib/posix/semaphore.rb
|
25
|
+
- lib/posix-semaphore.rb
|
26
|
+
- posix-semaphore.gemspec
|
27
|
+
- README
|
28
|
+
homepage: http://github.com/dpkendal/posix-semaphore
|
29
|
+
licenses: []
|
30
|
+
post_install_message:
|
31
|
+
rdoc_options: []
|
32
|
+
require_paths:
|
33
|
+
- lib
|
34
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
35
|
+
none: false
|
36
|
+
requirements:
|
37
|
+
- - ! '>='
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
requirements: []
|
47
|
+
rubyforge_project:
|
48
|
+
rubygems_version: 1.8.6
|
49
|
+
signing_key:
|
50
|
+
specification_version: 3
|
51
|
+
summary: Access to the POSIX semaphore APIs in Ruby
|
52
|
+
test_files: []
|