posix-semaphore 0.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.
- 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: []
|