process_shared 0.0.4 → 0.1.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/ext/helper/extconf.rb +14 -0
- data/ext/helper/helper.c +70 -0
- data/lib/mach.rb +12 -0
- data/lib/mach/clock.rb +24 -0
- data/lib/mach/error.rb +56 -0
- data/lib/mach/functions.rb +342 -0
- data/lib/mach/host.rb +28 -0
- data/lib/mach/port.rb +143 -0
- data/lib/mach/semaphore.rb +74 -0
- data/lib/mach/task.rb +42 -0
- data/lib/mach/time_spec.rb +16 -0
- data/lib/process_shared.rb +17 -1
- data/lib/process_shared/binary_semaphore.rb +18 -7
- data/lib/process_shared/mach.rb +93 -0
- data/lib/process_shared/mach/semaphore.rb +39 -0
- data/lib/process_shared/posix/errno.rb +40 -0
- data/lib/process_shared/posix/libc.rb +78 -0
- data/lib/process_shared/posix/semaphore.rb +125 -0
- data/lib/process_shared/posix/shared_array.rb +71 -0
- data/lib/process_shared/posix/shared_memory.rb +82 -0
- data/lib/process_shared/posix/time_spec.rb +13 -0
- data/lib/process_shared/posix/time_val.rb +23 -0
- data/lib/process_shared/semaphore.rb +26 -73
- data/lib/process_shared/shared_array.rb +3 -1
- data/lib/process_shared/shared_memory.rb +10 -52
- data/lib/process_shared/time_spec.rb +22 -0
- data/spec/mach/port_spec.rb +21 -0
- data/spec/mach/scratch.rb +67 -0
- data/spec/mach/scratch2.rb +78 -0
- data/spec/mach/semaphore_spec.rb +60 -0
- data/spec/mach/task_spec.rb +31 -0
- data/spec/process_shared/scratch.rb +21 -0
- data/spec/process_shared/semaphore_spec.rb +12 -11
- data/spec/process_shared/shared_memory_spec.rb +1 -1
- metadata +46 -36
- data/ext/libpsem/bsem.c +0 -188
- data/ext/libpsem/bsem.h +0 -32
- data/ext/libpsem/constants.c +0 -22
- data/ext/libpsem/constants.h +0 -18
- data/ext/libpsem/extconf.rb +0 -40
- data/ext/libpsem/mempcpy.c +0 -7
- data/ext/libpsem/mempcpy.h +0 -13
- data/ext/libpsem/mutex.c +0 -15
- data/ext/libpsem/mutex.h +0 -14
- data/ext/libpsem/psem.c +0 -15
- data/ext/libpsem/psem.h +0 -45
- data/ext/libpsem/psem_error.c +0 -46
- data/ext/libpsem/psem_error.h +0 -11
- data/ext/libpsem/psem_posix.c +0 -160
- data/ext/libpsem/psem_posix.h +0 -10
- data/lib/process_shared/bounded_semaphore.rb +0 -46
- data/lib/process_shared/libc.rb +0 -36
- data/lib/process_shared/libpsem.bundle +0 -0
- data/lib/process_shared/libpsem.so +0 -0
- data/lib/process_shared/psem.rb +0 -113
- data/spec/process_shared/bounded_semaphore_spec.rb +0 -48
- data/spec/process_shared/libc_spec.rb +0 -9
- data/spec/process_shared/psem_spec.rb +0 -136
data/ext/libpsem/psem_posix.h
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
require 'process_shared/psem'
|
2
|
-
require 'process_shared/semaphore'
|
3
|
-
|
4
|
-
module ProcessShared
|
5
|
-
# BoundedSemaphore is identical to Semaphore except that its value
|
6
|
-
# is not permitted to rise above a maximum. When the value is at
|
7
|
-
# the maximum, calls to #post will have no effect.
|
8
|
-
class BoundedSemaphore < Semaphore
|
9
|
-
# With no associated block, open is a synonym for
|
10
|
-
# Semaphore.new. If the optional code block is given, it will be
|
11
|
-
# passed +sem+ as an argument, and the Semaphore object will
|
12
|
-
# automatically be closed when the block terminates. In this
|
13
|
-
# instance, BoundedSemaphore.open returns the value of the block.
|
14
|
-
#
|
15
|
-
# @param [Integer] value the initial semaphore value
|
16
|
-
# @param [String] name not currently supported
|
17
|
-
def self.open(maxvalue, value = 1, name = nil, &block)
|
18
|
-
new(maxvalue, value, name).with_self(&block)
|
19
|
-
end
|
20
|
-
|
21
|
-
# Create a new semaphore with initial value +value+. After
|
22
|
-
# {Kernel#fork}, the semaphore will be shared across two (or more)
|
23
|
-
# processes. The semaphore must be closed with {#close} in each
|
24
|
-
# process that no longer needs the semaphore.
|
25
|
-
#
|
26
|
-
# (An object finalizer is registered that will close the semaphore
|
27
|
-
# to avoid memory leaks, but this should be considered a last
|
28
|
-
# resort).
|
29
|
-
#
|
30
|
-
# @param [Integer] value the initial semaphore value
|
31
|
-
# @param [String] name not currently supported
|
32
|
-
def initialize(maxvalue, value = 1, name = nil)
|
33
|
-
init(PSem.sizeof_bsem_t, 'bsem', name) do |sem_name|
|
34
|
-
bsem_open(sem, sem_name, maxvalue, value, err)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
protected
|
39
|
-
|
40
|
-
alias_method :psem_unlink, :bsem_unlink
|
41
|
-
alias_method :psem_close, :bsem_close
|
42
|
-
alias_method :psem_wait, :bsem_wait
|
43
|
-
alias_method :psem_post, :bsem_post
|
44
|
-
alias_method :psem_getvalue, :bsem_getvalue
|
45
|
-
end
|
46
|
-
end
|
data/lib/process_shared/libc.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
require 'ffi'
|
2
|
-
|
3
|
-
require 'process_shared/posix_call'
|
4
|
-
require 'process_shared/psem'
|
5
|
-
|
6
|
-
module ProcessShared
|
7
|
-
module LibC
|
8
|
-
extend FFI::Library
|
9
|
-
extend PosixCall
|
10
|
-
|
11
|
-
ffi_lib FFI::Library::LIBC
|
12
|
-
|
13
|
-
MAP_FAILED = FFI::Pointer.new(-1)
|
14
|
-
MAP_SHARED = PSem.map_shared
|
15
|
-
MAP_PRIVATE = PSem.map_private
|
16
|
-
|
17
|
-
PROT_READ = PSem.prot_read
|
18
|
-
PROT_WRITE = PSem.prot_write
|
19
|
-
PROT_EXEC = PSem.prot_exec
|
20
|
-
PROT_NONE = PSem.prot_none
|
21
|
-
|
22
|
-
O_RDWR = PSem.o_rdwr
|
23
|
-
O_CREAT = PSem.o_creat
|
24
|
-
O_EXCL = PSem.o_excl
|
25
|
-
|
26
|
-
attach_variable :errno, :int
|
27
|
-
|
28
|
-
attach_function :mmap, [:pointer, :size_t, :int, :int, :int, :off_t], :pointer
|
29
|
-
attach_function :munmap, [:pointer, :size_t], :int
|
30
|
-
attach_function :ftruncate, [:int, :off_t], :int
|
31
|
-
attach_function :close, [:int], :int
|
32
|
-
|
33
|
-
error_check(:mmap) { |v| v == MAP_FAILED }
|
34
|
-
error_check(:munmap, :ftruncate, :close)
|
35
|
-
end
|
36
|
-
end
|
Binary file
|
Binary file
|
data/lib/process_shared/psem.rb
DELETED
@@ -1,113 +0,0 @@
|
|
1
|
-
require 'ffi'
|
2
|
-
|
3
|
-
module ProcessShared
|
4
|
-
module PSem
|
5
|
-
class Error < FFI::Struct
|
6
|
-
layout(:source, :int,
|
7
|
-
:errno, :int)
|
8
|
-
end
|
9
|
-
|
10
|
-
extend FFI::Library
|
11
|
-
|
12
|
-
# Workaround FFI dylib/bundle issue. See https://github.com/ffi/ffi/issues/42
|
13
|
-
suffix = if FFI::Platform.mac?
|
14
|
-
'bundle'
|
15
|
-
else
|
16
|
-
FFI::Platform::LIBSUFFIX
|
17
|
-
end
|
18
|
-
|
19
|
-
ffi_lib File.join(File.expand_path(File.dirname(__FILE__)),
|
20
|
-
'libpsem.' + suffix)
|
21
|
-
|
22
|
-
class << self
|
23
|
-
# Replace methods in `syms` with error checking wrappers that
|
24
|
-
# invoke the original psem method and raise an appropriate
|
25
|
-
# error.
|
26
|
-
#
|
27
|
-
# The last argument is assumed to be a pointer to a pointer
|
28
|
-
# where either a psem error or NULL will be stored.
|
29
|
-
def psem_error_check(*syms)
|
30
|
-
syms.each do |sym|
|
31
|
-
method = self.method(sym)
|
32
|
-
|
33
|
-
block = lambda do |*args|
|
34
|
-
if method.call(*args) < 0
|
35
|
-
errp = args[-1]
|
36
|
-
unless errp.nil?
|
37
|
-
begin
|
38
|
-
err = Error.new(errp.read_pointer)
|
39
|
-
errp.write_pointer(nil)
|
40
|
-
if err[:source] == PSem.e_source_system
|
41
|
-
raise SystemCallError.new("error in #{sym}", err[:errno])
|
42
|
-
else
|
43
|
-
raise "error in #{sym}: #{err.get_integer(1)}"
|
44
|
-
end
|
45
|
-
ensure
|
46
|
-
psem_error_free(err)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
define_method(sym, &block)
|
53
|
-
define_singleton_method(sym, &block)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
# Generic constants
|
59
|
-
|
60
|
-
int_consts = [:o_rdwr,
|
61
|
-
:o_creat,
|
62
|
-
:o_excl,
|
63
|
-
|
64
|
-
:prot_read,
|
65
|
-
:prot_write,
|
66
|
-
:prot_exec,
|
67
|
-
:prot_none,
|
68
|
-
|
69
|
-
:map_shared,
|
70
|
-
:map_private]
|
71
|
-
int_consts.each { |sym| attach_variable sym, :int }
|
72
|
-
|
73
|
-
# Other constants, functions
|
74
|
-
|
75
|
-
attach_function :psem_error_free, :error_free, [:pointer], :void
|
76
|
-
|
77
|
-
attach_variable :e_source_system, :E_SOURCE_SYSTEM, :int
|
78
|
-
attach_variable :e_source_psem, :E_SOURCE_PSEM, :int
|
79
|
-
|
80
|
-
attach_variable :e_name_too_long, :E_NAME_TOO_LONG, :int
|
81
|
-
|
82
|
-
attach_variable :sizeof_psem_t, :size_t
|
83
|
-
attach_variable :sizeof_bsem_t, :size_t
|
84
|
-
|
85
|
-
# PSem functions
|
86
|
-
|
87
|
-
attach_function :psem_open, [:pointer, :string, :uint, :pointer], :int
|
88
|
-
attach_function :psem_close, [:pointer, :pointer], :int
|
89
|
-
attach_function :psem_unlink, [:string, :pointer], :int
|
90
|
-
attach_function :psem_post, [:pointer, :pointer], :int
|
91
|
-
attach_function :psem_wait, [:pointer, :pointer], :int
|
92
|
-
attach_function :psem_trywait, [:pointer, :pointer], :int
|
93
|
-
attach_function :psem_timedwait, [:pointer, :float, :pointer], :int
|
94
|
-
attach_function :psem_getvalue, [:pointer, :pointer, :pointer], :int
|
95
|
-
|
96
|
-
psem_error_check(:psem_open, :psem_close, :psem_unlink, :psem_post,
|
97
|
-
:psem_wait, :psem_trywait, :psem_timedwait, :psem_getvalue)
|
98
|
-
|
99
|
-
# BSem functions
|
100
|
-
|
101
|
-
attach_function :bsem_open, [:pointer, :string, :uint, :uint, :pointer], :int
|
102
|
-
attach_function :bsem_close, [:pointer, :pointer], :int
|
103
|
-
attach_function :bsem_unlink, [:string, :pointer], :int
|
104
|
-
attach_function :bsem_post, [:pointer, :pointer], :int
|
105
|
-
attach_function :bsem_wait, [:pointer, :pointer], :int
|
106
|
-
attach_function :bsem_trywait, [:pointer, :pointer], :int
|
107
|
-
attach_function :bsem_timedwait, [:pointer, :float, :pointer], :int
|
108
|
-
attach_function :bsem_getvalue, [:pointer, :pointer, :pointer], :int
|
109
|
-
|
110
|
-
psem_error_check(:bsem_open, :bsem_close, :bsem_unlink, :bsem_post,
|
111
|
-
:bsem_wait, :bsem_trywait, :bsem_timedwait, :bsem_getvalue)
|
112
|
-
end
|
113
|
-
end
|
@@ -1,48 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'process_shared/bounded_semaphore'
|
3
|
-
|
4
|
-
module ProcessShared
|
5
|
-
describe BoundedSemaphore do
|
6
|
-
it 'never rises above its max value' do
|
7
|
-
max = 10
|
8
|
-
BoundedSemaphore.open(max) do |sem|
|
9
|
-
pids = []
|
10
|
-
10.times do |i|
|
11
|
-
pids << fork do
|
12
|
-
100.times do
|
13
|
-
if rand(3) == 0
|
14
|
-
sem.wait
|
15
|
-
else
|
16
|
-
sem.post
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
exit i
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
100.times do
|
25
|
-
sem.value.must be_lte(max)
|
26
|
-
end
|
27
|
-
|
28
|
-
pids.each { |pid| Process.wait(pid) }
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
describe '#post and #wait' do
|
33
|
-
it 'increments and decrements the value' do
|
34
|
-
Semaphore.open(0) do |sem|
|
35
|
-
10.times do |i|
|
36
|
-
sem.post
|
37
|
-
sem.value.must_equal(i + 1)
|
38
|
-
end
|
39
|
-
|
40
|
-
10.times do |i|
|
41
|
-
sem.wait
|
42
|
-
sem.value.must_equal(10 - i - 1)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
@@ -1,136 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'process_shared/psem'
|
3
|
-
|
4
|
-
module ProcessShared
|
5
|
-
describe PSem do
|
6
|
-
before do
|
7
|
-
extend PSem
|
8
|
-
end
|
9
|
-
|
10
|
-
before(:each) do
|
11
|
-
@err = FFI::MemoryPointer.new(:pointer)
|
12
|
-
end
|
13
|
-
|
14
|
-
describe '.psem_open' do
|
15
|
-
it 'opens a psem' do
|
16
|
-
psem = FFI::MemoryPointer.new(PSem.sizeof_psem_t)
|
17
|
-
psem_open(psem, "psem-test", 1, @err)
|
18
|
-
psem_unlink("psem-test", @err)
|
19
|
-
end
|
20
|
-
|
21
|
-
it 'raises excpetion if name alredy exists' do
|
22
|
-
psem1 = FFI::MemoryPointer.new(PSem.sizeof_psem_t)
|
23
|
-
psem2 = FFI::MemoryPointer.new(PSem.sizeof_psem_t)
|
24
|
-
psem_open(psem1, "psem-test", 1, @err)
|
25
|
-
proc { psem_open(psem2, "psem-test", 1, @err) }.must_raise(Errno::EEXIST)
|
26
|
-
|
27
|
-
psem_unlink("psem-test", @err)
|
28
|
-
psem_open(psem2, "psem-test", 1, @err)
|
29
|
-
psem_unlink("psem-test", @err)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
describe '.psem_wait' do
|
34
|
-
before(:each) do
|
35
|
-
@psem = FFI::MemoryPointer.new(PSem.sizeof_psem_t)
|
36
|
-
psem_open(@psem, 'psem-test', 1, @err)
|
37
|
-
psem_unlink('psem-test', @err)
|
38
|
-
|
39
|
-
@int = FFI::MemoryPointer.new(:int)
|
40
|
-
end
|
41
|
-
|
42
|
-
after(:each) do
|
43
|
-
#psem_close(@psem, @err)
|
44
|
-
end
|
45
|
-
|
46
|
-
def value
|
47
|
-
psem_getvalue(@psem, @int, @err)
|
48
|
-
@int.get_int(0)
|
49
|
-
end
|
50
|
-
|
51
|
-
it 'decrements psem value' do
|
52
|
-
value.must_equal 1
|
53
|
-
psem_wait(@psem, @err)
|
54
|
-
value.must_equal(0)
|
55
|
-
end
|
56
|
-
|
57
|
-
it 'waits until another process posts' do
|
58
|
-
psem_wait(@psem, @err)
|
59
|
-
|
60
|
-
# child exits with ~ time spent waiting
|
61
|
-
child = fork do
|
62
|
-
start = Time.now
|
63
|
-
psem_wait(@psem, @err)
|
64
|
-
exit (Time.now - start).ceil
|
65
|
-
end
|
66
|
-
|
67
|
-
t = 1.5
|
68
|
-
sleep t
|
69
|
-
psem_post(@psem, @err)
|
70
|
-
_pid, status = Process.wait2(child)
|
71
|
-
status.exitstatus.must_equal 2
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
describe '.bsem_open' do
|
76
|
-
it 'opens a bsem' do
|
77
|
-
bsem = FFI::MemoryPointer.new(PSem.sizeof_bsem_t)
|
78
|
-
bsem_open(bsem, "bsem-test", 1, 1, @err)
|
79
|
-
bsem_unlink("bsem-test", @err)
|
80
|
-
end
|
81
|
-
|
82
|
-
it 'raises excpetion if name alredy exists' do
|
83
|
-
bsem1 = FFI::MemoryPointer.new(PSem.sizeof_bsem_t)
|
84
|
-
bsem2 = FFI::MemoryPointer.new(PSem.sizeof_bsem_t)
|
85
|
-
bsem_open(bsem1, "bsem-test", 1, 1, @err)
|
86
|
-
proc { bsem_open(bsem2, "bsem-test", 1, 1, @err) }.must_raise(Errno::EEXIST)
|
87
|
-
|
88
|
-
bsem_unlink("bsem-test", @err)
|
89
|
-
bsem_open(bsem2, "bsem-test", 1, 1, @err)
|
90
|
-
bsem_unlink("bsem-test", @err)
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
describe '.bsem_wait' do
|
95
|
-
before(:each) do
|
96
|
-
@bsem = FFI::MemoryPointer.new(PSem.sizeof_bsem_t)
|
97
|
-
bsem_open(@bsem, 'bsem-test', 1, 1, @err)
|
98
|
-
bsem_unlink('bsem-test', @err)
|
99
|
-
|
100
|
-
@int = FFI::MemoryPointer.new(:int)
|
101
|
-
end
|
102
|
-
|
103
|
-
after do
|
104
|
-
#bsem_close(@bsem, @err)
|
105
|
-
end
|
106
|
-
|
107
|
-
def value
|
108
|
-
bsem_getvalue(@bsem, @int, @err)
|
109
|
-
@int.get_int(0)
|
110
|
-
end
|
111
|
-
|
112
|
-
it 'decrements bsem value' do
|
113
|
-
value.must_equal 1
|
114
|
-
bsem_wait(@bsem, @err)
|
115
|
-
value.must_equal 0
|
116
|
-
end
|
117
|
-
|
118
|
-
it 'waits until another process posts' do
|
119
|
-
bsem_wait(@bsem, @err)
|
120
|
-
|
121
|
-
# child exits with ~ time spent waiting
|
122
|
-
child = fork do
|
123
|
-
start = Time.now
|
124
|
-
bsem_wait(@bsem, @err)
|
125
|
-
exit (Time.now - start).ceil
|
126
|
-
end
|
127
|
-
|
128
|
-
t = 1.5
|
129
|
-
sleep t
|
130
|
-
bsem_post(@bsem, @err)
|
131
|
-
_pid, status = Process.wait2(child)
|
132
|
-
status.exitstatus.must_equal 2
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|