process_shared 0.1.0 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/lib/mach.rb CHANGED
@@ -1,12 +1,109 @@
1
- require 'mach/port'
2
- require 'mach/semaphore'
3
- require 'mach/task'
4
- require 'mach/functions'
1
+ require 'ffi'
2
+
3
+ require 'mach/types'
5
4
 
6
5
  module Mach
6
+ extend Mach::Types
7
+
8
+ class MsgHeader < FFI::Struct
9
+ layout(:bits, :mach_msg_bits_t,
10
+ :size, :mach_msg_size_t,
11
+ :remote_port, :mach_port_t,
12
+ :local_port, :mach_port_t,
13
+ :reserved, :mach_msg_size_t,
14
+ :id, :mach_msg_id_t)
15
+ end
16
+
17
+ class MsgBody < FFI::Struct
18
+ layout(:descriptor_count, :mach_msg_size_t)
19
+ end
20
+
21
+ class MsgBase < FFI::Struct
22
+ layout(:header, MsgHeader,
23
+ :body, MsgBody)
24
+ end
25
+
26
+ class MsgTrailer < FFI::Struct
27
+ layout(:type, :mach_msg_trailer_type_t,
28
+ :size, :mach_msg_trailer_size_t)
29
+ end
30
+
31
+ class MsgPortDescriptor < FFI::Struct
32
+ layout(:name, :mach_port_t,
33
+ :pad1, :mach_msg_size_t, # FIXME: leave oout on __LP64__
34
+ :pad2, :uint16, # :uint
35
+ :disposition, :uint8, # :mach_msg_type_name_t
36
+ :type, :uint8) # :mach_msg_descriptor_type_t
37
+ end
38
+
39
+ SyncPolicy = enum( :fifo, 0x0,
40
+ :fixed_priority, 0x1,
41
+ :reversed, 0x2,
42
+ :order_mask, 0x3,
43
+ :lifo, 0x0 | 0x2, # um...
44
+ :max, 0x7 )
45
+
46
+ PortRight = enum( :send, 0,
47
+ :receive,
48
+ :send_once,
49
+ :port_set,
50
+ :dead_name,
51
+ :labelh,
52
+ :number )
53
+
54
+ # port type macro
55
+ def self.pt(*syms)
56
+ acc = 0
57
+ syms.each do |sym|
58
+ acc |= (1 << (PortRight[sym] + 16))
59
+ end
60
+ acc
61
+ end
62
+
63
+ PORT_NULL = 0
64
+ MSG_TIMEOUT_NONE = 0
65
+
66
+ PortType =
67
+ enum(:none, 0,
68
+ :send, pt(:send),
69
+ :receive, pt(:receive),
70
+ :send_once, pt(:send_once),
71
+ :port_set, pt(:port_set),
72
+ :dead_name, pt(:dead_name),
73
+ :labelh, pt(:labelh),
74
+
75
+ :send_receive, pt(:send, :receive),
76
+ :send_rights, pt(:send, :send_once),
77
+ :port_rights, pt(:send, :send_once, :receive),
78
+ :port_or_dead, pt(:send, :send_once, :receive, :dead_name),
79
+ :all_rights, pt(:send, :send_once, :receive, :dead_name, :port_set))
80
+
81
+ MsgType =
82
+ enum( :move_receive, 16, # must hold receive rights
83
+ :move_send, # must hold send rights
84
+ :move_send_once, # must hold sendonce rights
85
+ :copy_send, # must hold send rights
86
+ :make_send, # must hold receive rights
87
+ :make_send_once, # must hold receive rights
88
+ :copy_receive ) # must hold receive rights
89
+
90
+ SpecialPort =
91
+ enum( :kernel, 1,
92
+ :host,
93
+ :name,
94
+ :bootstrap )
95
+
96
+ KERN_SUCCESS = 0
97
+
98
+
7
99
  # @return [Port] the original bootstrap port; different from that
8
100
  # affected by {get,set}_special_port
9
101
  def self.bootstrap_port
10
102
  @bootstrap_port ||= Mach::Port.new(:port => Mach::Functions::bootstrap_port)
11
103
  end
12
104
  end
105
+
106
+ require 'mach/port'
107
+ require 'mach/semaphore'
108
+ require 'mach/task'
109
+ require 'mach/functions'
@@ -1,5 +1,6 @@
1
1
  require 'ffi'
2
2
 
3
+ require 'mach/types'
3
4
  require 'mach/time_spec'
4
5
 
5
6
  module Mach
@@ -7,134 +8,10 @@ module Mach
7
8
  # specific).
8
9
  module Functions
9
10
  extend FFI::Library
11
+ extend Types
10
12
 
11
13
  ffi_lib 'c'
12
14
 
13
- typedef :__darwin_mach_port_t, :mach_port_t
14
- typedef :__darwin_natural_t, :natural_t
15
-
16
- typedef :int, :integer_t
17
- typedef :int, :kern_return_t # true for 64 bit??
18
- typedef :int, :mach_error_t
19
- typedef :int, :sync_policy_t # SyncPolicy
20
- typedef :int, :clock_id_t
21
- typedef :int, :clock_res_t
22
-
23
- typedef :string, :name_t
24
-
25
- typedef :mach_port_t, :host_t
26
- typedef :mach_port_t, :task_t
27
- typedef :mach_port_t, :ipc_space_t
28
- typedef :mach_port_t, :semaphore_t
29
- typedef :pointer, :mach_port_pointer_t
30
-
31
- typedef :natural_t, :mach_port_name_t
32
- typedef :natural_t, :mach_port_right_t # MachPortRight
33
- typedef :pointer, :mach_port_name_array_t
34
- typedef :pointer, :mach_port_name_pointer_t
35
-
36
- typedef :uint, :mach_msg_type_name_t
37
- typedef :uint, :mach_msg_bits_t
38
- typedef :uint, :mach_msg_trailer_type_t
39
- typedef :uint, :mach_msg_trailer_size_t
40
- typedef :uint, :mach_msg_descriptor_type_t
41
- typedef :natural_t, :mach_msg_timeout_t
42
-
43
- typedef :natural_t, :mach_msg_size_t
44
- typedef :integer_t, :mach_msg_id_t
45
- typedef :integer_t, :mach_msg_options_t
46
- typedef :integer_t, :mach_msg_option_t
47
-
48
- class MsgHeader < FFI::Struct
49
- layout(:bits, :mach_msg_bits_t,
50
- :size, :mach_msg_size_t,
51
- :remote_port, :mach_port_t,
52
- :local_port, :mach_port_t,
53
- :reserved, :mach_msg_size_t,
54
- :id, :mach_msg_id_t)
55
- end
56
-
57
- class MsgBody < FFI::Struct
58
- layout(:descriptor_count, :mach_msg_size_t)
59
- end
60
-
61
- class MsgBase < FFI::Struct
62
- layout(:header, MsgHeader,
63
- :body, MsgBody)
64
- end
65
-
66
- class MsgTrailer < FFI::Struct
67
- layout(:type, :mach_msg_trailer_type_t,
68
- :size, :mach_msg_trailer_size_t)
69
- end
70
-
71
- class MsgPortDescriptor < FFI::Struct
72
- layout(:name, :mach_port_t,
73
- :pad1, :mach_msg_size_t, # FIXME: leave oout on __LP64__
74
- :pad2, :uint16, # :uint
75
- :disposition, :uint8, # :mach_msg_type_name_t
76
- :type, :uint8) # :mach_msg_descriptor_type_t
77
- end
78
-
79
- SyncPolicy = enum( :fifo, 0x0,
80
- :fixed_priority, 0x1,
81
- :reversed, 0x2,
82
- :order_mask, 0x3,
83
- :lifo, 0x0 | 0x2, # um...
84
- :max, 0x7 )
85
-
86
- MachPortRight = enum( :send, 0,
87
- :receive,
88
- :send_once,
89
- :port_set,
90
- :dead_name,
91
- :labelh,
92
- :number )
93
-
94
- # port type
95
- def self.pt(*syms)
96
- acc = 0
97
- syms.each do |sym|
98
- acc |= (1 << (MachPortRight[sym] + 16))
99
- end
100
- acc
101
- end
102
-
103
- MACH_PORT_NULL = 0
104
- MACH_MSG_TIMEOUT_NONE = 0
105
-
106
- MachPortType =
107
- enum(:none, 0,
108
- :send, pt(:send),
109
- :receive, pt(:receive),
110
- :send_once, pt(:send_once),
111
- :port_set, pt(:port_set),
112
- :dead_name, pt(:dead_name),
113
- :labelh, pt(:labelh),
114
-
115
- :send_receive, pt(:send, :receive),
116
- :send_rights, pt(:send, :send_once),
117
- :port_rights, pt(:send, :send_once, :receive),
118
- :port_or_dead, pt(:send, :send_once, :receive, :dead_name),
119
- :all_rights, pt(:send, :send_once, :receive, :dead_name, :port_set))
120
-
121
- MachMsgType =
122
- enum( :move_receive, 16, # must hold receive rights
123
- :move_send, # must hold send rights
124
- :move_send_once, # must hold sendonce rights
125
- :copy_send, # must hold send rights
126
- :make_send, # must hold receive rights
127
- :make_send_once, # must hold receive rights
128
- :copy_receive ) # must hold receive rights
129
-
130
- MachSpecialPort =
131
- enum( :kernel, 1,
132
- :host,
133
- :name,
134
- :bootstrap )
135
-
136
- KERN_SUCCESS = 0
137
-
138
15
  # Replace methods in +syms+ with error checking wrappers that
139
16
  # invoke the original method and raise a {SystemCallError}.
140
17
  #
@@ -232,7 +109,7 @@ module Mach
232
109
 
233
110
  attach_mach_function(:mach_port_allocate,
234
111
  [:ipc_space_t,
235
- MachPortRight,
112
+ PortRight,
236
113
  :mach_port_name_pointer_t],
237
114
  :kern_return_t)
238
115
 
@@ -250,7 +127,7 @@ module Mach
250
127
  [:ipc_space_t,
251
128
  :mach_port_name_t,
252
129
  :mach_port_t,
253
- MachMsgType],
130
+ MsgType],
254
131
  :kern_return_t)
255
132
 
256
133
  ##################
@@ -271,13 +148,13 @@ module Mach
271
148
 
272
149
  attach_mach_function(:task_get_special_port,
273
150
  [:task_t,
274
- MachSpecialPort,
151
+ SpecialPort,
275
152
  :mach_port_pointer_t],
276
153
  :kern_return_t)
277
154
 
278
155
  attach_mach_function(:task_set_special_port,
279
156
  [:task_t,
280
- MachSpecialPort,
157
+ SpecialPort,
281
158
  :mach_port_t],
282
159
  :kern_return_t)
283
160
 
data/lib/mach/port.rb CHANGED
@@ -76,7 +76,7 @@ module Mach
76
76
  # Insert +right+ into another ipc space. The current task must
77
77
  # have sufficient rights to insert the requested right.
78
78
  #
79
- # @param [MachMsgType] right
79
+ # @param [MsgType] right
80
80
  #
81
81
  # @param [Hash] opts
82
82
  #
@@ -100,9 +100,9 @@ module Mach
100
100
 
101
101
  msg[:header].tap do |h|
102
102
  h[:remote_port] = remote_port.to_i
103
- h[:local_port] = MACH_PORT_NULL
103
+ h[:local_port] = PORT_NULL
104
104
  h[:bits] =
105
- (MachMsgType[right] | (0 << 8)) | 0x80000000 # MACH_MSGH_BITS_COMPLEX
105
+ (MsgType[right] | (0 << 8)) | 0x80000000 # MACH_MSGH_BITS_COMPLEX
106
106
  h[:size] = 40 # msg.size
107
107
  end
108
108
 
@@ -110,8 +110,8 @@ module Mach
110
110
 
111
111
  msg[:port].tap do |p|
112
112
  p[:name] = port
113
- p[:disposition] = MachMsgType[right]
114
- p[:type] = 0 # MACH_MSG_PORT_DESCRIPTOR;
113
+ p[:disposition] = MsgType[right]
114
+ p[:type] = 0 # MSG_PORT_DESCRIPTOR;
115
115
  end
116
116
 
117
117
  mach_msg_send msg
@@ -130,12 +130,12 @@ module Mach
130
130
  msg = ReceiveRightMsg.new
131
131
 
132
132
  mach_msg(msg,
133
- 2, # MACH_RCV_MSG,
133
+ 2, # RCV_MSG,
134
134
  0,
135
135
  msg.size,
136
136
  port,
137
- MACH_MSG_TIMEOUT_NONE,
138
- MACH_PORT_NULL)
137
+ MSG_TIMEOUT_NONE,
138
+ PORT_NULL)
139
139
 
140
140
  self.class.new :port => msg[:port][:name]
141
141
  end
data/lib/mach/types.rb ADDED
@@ -0,0 +1,54 @@
1
+ require 'ffi'
2
+
3
+ module Mach
4
+ module Types
5
+ extend FFI::Library
6
+
7
+ typedef :__darwin_mach_port_t, :mach_port_t
8
+ typedef :__darwin_natural_t, :natural_t
9
+
10
+ typedef :int, :integer_t
11
+ typedef :int, :kern_return_t # true for 64 bit??
12
+ typedef :int, :mach_error_t
13
+ typedef :int, :sync_policy_t # SyncPolicy
14
+ typedef :int, :clock_id_t
15
+ typedef :int, :clock_res_t
16
+
17
+ typedef :string, :name_t
18
+
19
+ typedef :mach_port_t, :host_t
20
+ typedef :mach_port_t, :task_t
21
+ typedef :mach_port_t, :ipc_space_t
22
+ typedef :mach_port_t, :semaphore_t
23
+ typedef :pointer, :mach_port_pointer_t
24
+
25
+ typedef :natural_t, :mach_port_name_t
26
+ typedef :natural_t, :mach_port_right_t # MachPortRight
27
+ typedef :pointer, :mach_port_name_array_t
28
+ typedef :pointer, :mach_port_name_pointer_t
29
+
30
+ typedef :uint, :mach_msg_type_name_t
31
+ typedef :uint, :mach_msg_bits_t
32
+ typedef :uint, :mach_msg_trailer_type_t
33
+ typedef :uint, :mach_msg_trailer_size_t
34
+ typedef :uint, :mach_msg_descriptor_type_t
35
+ typedef :natural_t, :mach_msg_timeout_t
36
+
37
+ typedef :natural_t, :mach_msg_size_t
38
+ typedef :integer_t, :mach_msg_id_t
39
+ typedef :integer_t, :mach_msg_options_t
40
+ typedef :integer_t, :mach_msg_option_t
41
+
42
+ def self.typedefs
43
+ @ffi_typedefs
44
+ end
45
+
46
+ def find_type(t)
47
+ Mach::Types.find_type(t) || super
48
+ end
49
+
50
+ def enum(*args)
51
+ Mach::Types.enum(*args)
52
+ end
53
+ end
54
+ end
@@ -3,39 +3,29 @@ require 'ffi'
3
3
  if RUBY_VERSION =~ /^1.8/
4
4
  require 'process_shared/define_singleton_method'
5
5
 
6
- module ProcessShared
7
- module PSem
8
- extend DefineSingletonMethod
9
- end
10
-
11
- module RT
12
- extend DefineSingletonMethod
13
- end
14
-
15
- module LibC
16
- extend DefineSingletonMethod
17
- end
6
+ class Module
7
+ include ProcessShared::DefineSingletonMethod
18
8
  end
19
9
  end
20
10
 
21
- require 'process_shared/semaphore'
22
- require 'process_shared/binary_semaphore'
23
- require 'process_shared/mutex'
24
- require 'process_shared/shared_memory'
25
-
26
11
  module ProcessShared
27
12
  case FFI::Platform::OS
28
13
  when 'linux'
29
14
  require 'process_shared/posix/shared_memory'
30
15
  require 'process_shared/posix/semaphore'
31
16
 
32
- SharedMemory.impl = Posix::SharedMemory
33
- Semaphore.impl = Posix::Semaphore
17
+ SharedMemory = Posix::SharedMemory
18
+ Semaphore = Posix::Semaphore
34
19
  when 'darwin'
35
20
  require 'process_shared/posix/shared_memory'
36
21
  require 'process_shared/mach/semaphore'
37
22
 
38
- SharedMemory.impl = Posix::SharedMemory
39
- Semaphore.impl = Mach::Semaphore
23
+ SharedMemory = Posix::SharedMemory
24
+ Semaphore = Mach::Semaphore
40
25
  end
41
26
  end
27
+
28
+ require 'process_shared/binary_semaphore'
29
+ require 'process_shared/mutex'
30
+ require 'process_shared/condition_variable'
31
+
@@ -1,8 +1,7 @@
1
1
  require 'forwardable'
2
2
 
3
3
  require 'process_shared'
4
- require 'process_shared/with_self'
5
- require 'process_shared/semaphore'
4
+ require 'process_shared/open_with_self'
6
5
  require 'process_shared/process_error'
7
6
 
8
7
  module ProcessShared
@@ -14,14 +13,10 @@ module ProcessShared
14
13
  # This is identical to a Semaphore but with extra error checking.
15
14
  class BinarySemaphore
16
15
  extend Forwardable
17
- include ProcessShared::WithSelf
16
+ extend ProcessShared::OpenWithSelf
18
17
 
19
18
  def_delegators :@sem, :wait, :try_wait, :synchronize, :value, :close
20
19
 
21
- def self.open(value = 1, &block)
22
- new(value).with_self(&block)
23
- end
24
-
25
20
  # Create a new semaphore with initial value +value+. After
26
21
  # {Kernel#fork}, the semaphore will be shared across two (or more)
27
22
  # processes. The semaphore must be closed with {#close} in each
@@ -1,4 +1,4 @@
1
- require 'process_shared/semaphore'
1
+ require 'process_shared'
2
2
 
3
3
  module ProcessShared
4
4
  class ConditionVariable
@@ -46,6 +46,10 @@ end
46
46
 
47
47
  module Kernel
48
48
  # Override to call Process::fork.
49
+ def self.fork(*args, &block)
50
+ Process.fork(*args, &block)
51
+ end
52
+
49
53
  def fork(*args, &block)
50
54
  Process.fork(*args, &block)
51
55
  end
@@ -2,12 +2,15 @@ require 'mach'
2
2
  require 'mach/error'
3
3
 
4
4
  require 'process_shared/mach'
5
+ require 'process_shared/open_with_self'
6
+ require 'process_shared/synchronizable_semaphore'
5
7
 
6
8
  module ProcessShared
7
9
  module Mach
8
10
  # Extends ::Mach::Semaphore to be compatible with ProcessShared::Semaphore
9
11
  class Semaphore < ::Mach::Semaphore
10
- include ProcessShared::Semaphore
12
+ extend ProcessShared::OpenWithSelf
13
+ include ProcessShared::SynchronizableSemaphore
11
14
 
12
15
  def initialize(value = 1)
13
16
  super(:value => value)
@@ -1,6 +1,5 @@
1
- require 'process_shared/semaphore'
2
- require 'process_shared/with_self'
3
- require 'process_shared/shared_memory'
1
+ require 'process_shared'
2
+ require 'process_shared/open_with_self'
4
3
  require 'process_shared/process_error'
5
4
 
6
5
  module ProcessShared
@@ -20,11 +19,7 @@ module ProcessShared
20
19
  # release its {Semaphore} and {SharedMemory} resources. For now,
21
20
  # rely on the object finalizers of those objects...
22
21
  class Mutex
23
- # include WithSelf
24
-
25
- # def self.open(&block)
26
- # new.with_self(&block)
27
- # end
22
+ extend OpenWithSelf
28
23
 
29
24
  def initialize
30
25
  @internal_sem = Semaphore.new
@@ -1,23 +1,9 @@
1
- require 'process_shared/with_self'
2
1
  require 'process_shared/shared_memory_io'
3
2
 
4
3
  module ProcessShared
5
- # Memory block shared across processes.
6
- module SharedMemory
7
- include ProcessShared::WithSelf
8
-
9
- class << self
10
- attr_accessor :impl
11
-
12
- def new(*args)
13
- impl.new(*args)
14
- end
15
-
16
- def open(size, &block)
17
- new(size).with_self(&block)
18
- end
19
- end
20
-
4
+ # Provides reading and writing of serialized objects from a memory
5
+ # buffer.
6
+ module ObjectBuffer
21
7
  # Write the serialization of +obj+ (using Marshal.dump) to this
22
8
  # shared memory object at +offset+ (in bytes).
23
9
  #
@@ -0,0 +1,20 @@
1
+ module ProcessShared
2
+ module OpenWithSelf
3
+ # Like #new but if the optional code block is given, it will be
4
+ # passed the new object as an argument, and the object will
5
+ # automatically be closed (by invoking +close+) when the block
6
+ # terminates. In this instance, value of the block is returned.
7
+ def open(*args, &block)
8
+ obj = new(*args)
9
+ if block_given?
10
+ begin
11
+ yield obj
12
+ ensure
13
+ obj.close
14
+ end
15
+ else
16
+ obj
17
+ end
18
+ end
19
+ end
20
+ end
@@ -1,4 +1,5 @@
1
- require 'process_shared/semaphore'
1
+ require 'process_shared/synchronizable_semaphore'
2
+ require 'process_shared/open_with_self'
2
3
 
3
4
  require 'process_shared/posix/errno'
4
5
  require 'process_shared/posix/libc'
@@ -34,8 +35,9 @@ module ProcessShared
34
35
  :sem_timedwait)
35
36
  end
36
37
 
38
+ extend ProcessShared::OpenWithSelf
37
39
  include Foreign
38
- include ProcessShared::Semaphore
40
+ include ProcessShared::SynchronizableSemaphore
39
41
 
40
42
  # Make a Proc suitable for use as a finalizer that will call
41
43
  # +shm_unlink+ on +sem+.
@@ -2,7 +2,8 @@ require 'ffi'
2
2
 
3
3
  require 'process_shared/posix/errno'
4
4
  require 'process_shared/posix/libc'
5
- require 'process_shared/shared_memory'
5
+ require 'process_shared/object_buffer'
6
+ require 'process_shared/open_with_self'
6
7
 
7
8
  module ProcessShared
8
9
  module Posix
@@ -25,10 +26,10 @@ module ProcessShared
25
26
  error_check :shm_open, :shm_unlink
26
27
  end
27
28
 
29
+ extend ProcessShared::OpenWithSelf
28
30
  include SharedMemory::Foreign
29
31
  include LibC
30
-
31
- include ProcessShared::SharedMemory
32
+ include ProcessShared::ObjectBuffer
32
33
 
33
34
  attr_reader :size, :type, :type_size, :count, :fd
34
35
 
@@ -1,7 +1,7 @@
1
1
  require 'process_shared'
2
2
 
3
3
  module ProcessShared
4
- class SharedArray < SharedMemory.impl
4
+ class SharedArray < SharedMemory
5
5
  include Enumerable
6
6
 
7
7
  # A fixed-size array in shared memory. Processes forked from this
@@ -0,0 +1,16 @@
1
+ module ProcessShared
2
+ module SynchronizableSemaphore
3
+ # Yield the block after decrementing the semaphore, ensuring that
4
+ # the semaphore is incremented.
5
+ #
6
+ # @return [Object] the value of the block
7
+ def synchronize
8
+ wait
9
+ begin
10
+ yield
11
+ ensure
12
+ post
13
+ end
14
+ end
15
+ end
16
+ end
@@ -30,31 +30,41 @@ module Mach
30
30
  end
31
31
 
32
32
  it 'coordinates access to shared resource between two tasks' do
33
- sem = Semaphore.new(:value => 0)
33
+ begin
34
+ sem = Semaphore.new(:value => 0)
34
35
 
35
- port = Port.new
36
- port.insert_right(:make_send)
37
- Task.self.set_bootstrap_port(port)
38
-
39
- child = fork do
40
- parent_port = Task.self.get_bootstrap_port
41
- Task.self.copy_send(parent_port)
42
- # parent will copy send rights to sem into child task
43
- sleep 0.5
44
- sem.signal
45
- Kernel.exit!
46
- end
36
+ port = Port.new
37
+ port.insert_right(:make_send)
38
+ Task.self.set_bootstrap_port(port)
47
39
 
48
- child_task_port = port.receive_right
40
+ method = if Process.respond_to?(:__mach_original_fork__)
41
+ :__mach_original_fork__
42
+ else
43
+ :fork
44
+ end
49
45
 
50
- start = Time.now.to_f
51
- sem.insert_right(:copy_send, :ipc_space => child_task_port)
52
- sem.wait
53
- elapsed = Time.now.to_f - start
46
+ child = Process.send(method) do
47
+ parent_port = Task.self.get_bootstrap_port
48
+ Task.self.copy_send(parent_port)
49
+ # parent will copy send rights to sem into child task
50
+ sleep 0.5
51
+ sem.signal
52
+ Kernel.exit!
53
+ end
54
54
 
55
- Process.wait child
55
+ child_task_port = port.receive_right
56
56
 
57
- elapsed.must be_gt(0.4)
57
+ start = Time.now.to_f
58
+ sem.insert_right(:copy_send, :ipc_space => child_task_port)
59
+ sem.timedwait(1)
60
+ elapsed = Time.now.to_f - start
61
+
62
+ Process.wait child
63
+
64
+ elapsed.must be_gt(0.4)
65
+ ensure
66
+ Task.self.set_bootstrap_port(Mach::Functions.bootstrap_port)
67
+ end
58
68
  end
59
69
  end
60
70
  end
@@ -1,6 +1,5 @@
1
1
  require 'spec_helper'
2
- require 'process_shared/mutex'
3
- require 'process_shared/shared_memory'
2
+ require 'process_shared'
4
3
 
5
4
  module ProcessShared
6
5
  describe Mutex do
@@ -1,8 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  require 'ffi'
4
- require 'process_shared/semaphore'
5
- require 'process_shared/shared_memory'
4
+ require 'process_shared'
6
5
 
7
6
  module ProcessShared
8
7
  describe Semaphore do
@@ -16,7 +15,7 @@ module ProcessShared
16
15
  begin
17
16
  val = mem.get_int(0)
18
17
  # ensure other procs have a chance to interfere
19
- sleep 0.001 if rand(100) == 0
18
+ sleep 0.002 if rand(50) == 0
20
19
  mem.put_int(0, val + 1)
21
20
  rescue => e
22
21
  "#{Process.pid} die'ing because #{e}"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: process_shared
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-02 00:00:00.000000000Z
12
+ date: 2012-02-09 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ffi
16
- requirement: &13298820 !ruby/object:Gem::Requirement
16
+ requirement: &14966860 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '1.0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *13298820
24
+ version_requirements: *14966860
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rake
27
- requirement: &13297880 !ruby/object:Gem::Requirement
27
+ requirement: &14906760 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *13297880
35
+ version_requirements: *14906760
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rake-compiler
38
- requirement: &13297020 !ruby/object:Gem::Requirement
38
+ requirement: &14905460 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *13297020
46
+ version_requirements: *14905460
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: minitest
49
- requirement: &13296040 !ruby/object:Gem::Requirement
49
+ requirement: &14903860 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *13296040
57
+ version_requirements: *14903860
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: minitest-matchers
60
- requirement: &13295120 !ruby/object:Gem::Requirement
60
+ requirement: &14897460 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,7 +65,18 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *13295120
68
+ version_requirements: *14897460
69
+ - !ruby/object:Gem::Dependency
70
+ name: version
71
+ requirement: &14854820 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *14854820
69
80
  description: FFI wrapper around portable semaphore library with mutex and condition
70
81
  vars built on top.
71
82
  email: pat@polycrystal.org
@@ -88,12 +99,16 @@ files:
88
99
  - lib/mach/time_spec.rb
89
100
  - lib/mach/error.rb
90
101
  - lib/mach/port.rb
102
+ - lib/mach/types.rb
91
103
  - lib/mach/task.rb
104
+ - lib/process_shared/synchronizable_semaphore.rb
92
105
  - lib/process_shared/abstract_semaphore.rb
93
106
  - lib/process_shared/posix_call.rb
94
107
  - lib/process_shared/mach.rb
108
+ - lib/process_shared/object_buffer.rb
95
109
  - lib/process_shared/process_error.rb
96
110
  - lib/process_shared/thread.rb
111
+ - lib/process_shared/open_with_self.rb
97
112
  - lib/process_shared/posix/errno.rb
98
113
  - lib/process_shared/posix/semaphore.rb
99
114
  - lib/process_shared/posix/time_spec.rb
@@ -103,16 +118,13 @@ files:
103
118
  - lib/process_shared/posix/shared_memory.rb
104
119
  - lib/process_shared/mutex.rb
105
120
  - lib/process_shared/shared_memory_io.rb
106
- - lib/process_shared/semaphore.rb
107
121
  - lib/process_shared/time_spec.rb
108
122
  - lib/process_shared/rt.rb
109
123
  - lib/process_shared/mach/semaphore.rb
110
124
  - lib/process_shared/shared_array.rb
111
125
  - lib/process_shared/binary_semaphore.rb
112
- - lib/process_shared/with_self.rb
113
126
  - lib/process_shared/define_singleton_method.rb
114
127
  - lib/process_shared/condition_variable.rb
115
- - lib/process_shared/shared_memory.rb
116
128
  - ext/pthread_sync_helper/pthread_sync_helper.c
117
129
  - ext/semaphore.c
118
130
  - ext/helper/helper.c
@@ -128,7 +140,6 @@ files:
128
140
  - spec/process_shared/condition_variable_spec.rb
129
141
  - spec/process_shared/mutex_spec.rb
130
142
  - spec/process_shared/shared_array_spec.rb
131
- - spec/process_shared/scratch.rb
132
143
  - spec/process_shared/semaphore_spec.rb
133
144
  - spec/spec_helper.rb
134
145
  - README.rdoc
@@ -148,7 +159,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
148
159
  version: '0'
149
160
  segments:
150
161
  - 0
151
- hash: -4219144460365832731
162
+ hash: 282066855112542022
152
163
  required_rubygems_version: !ruby/object:Gem::Requirement
153
164
  none: false
154
165
  requirements:
@@ -157,7 +168,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
157
168
  version: '0'
158
169
  segments:
159
170
  - 0
160
- hash: -4219144460365832731
171
+ hash: 282066855112542022
161
172
  requirements: []
162
173
  rubyforge_project:
163
174
  rubygems_version: 1.8.10
@@ -1,37 +0,0 @@
1
- require 'process_shared/with_self'
2
-
3
- module ProcessShared
4
- module Semaphore
5
- include ProcessShared::WithSelf
6
-
7
- class << self
8
- # the implementation to use to create semaphores. impl is set
9
- # based on the platform in 'process_shared'
10
- attr_accessor :impl
11
-
12
- def new(*args)
13
- impl.new(*args)
14
- end
15
-
16
- # With no associated block, open is a synonym for
17
- # Semaphore.new. If the optional code block is given, it will be
18
- # passed +sem+ as an argument, and the Semaphore object will
19
- # automatically be closed when the block terminates. In this
20
- # instance, Semaphore.open returns the value of the block.
21
- #
22
- # @param [Integer] value the initial semaphore value
23
- def open(value = 1, &block)
24
- new(value).with_self(&block)
25
- end
26
- end
27
-
28
- def synchronize
29
- wait
30
- begin
31
- yield
32
- ensure
33
- post
34
- end
35
- end
36
- end
37
- end
@@ -1,20 +0,0 @@
1
- module ProcessShared
2
- module WithSelf
3
- # With no associated block, return self. If the optional code
4
- # block is given, it will be passed `self` as an argument, and the
5
- # self object will automatically be closed (by invoking +close+ on
6
- # +self+) when the block terminates. In this instance, value of
7
- # the block is returned.
8
- def with_self
9
- if block_given?
10
- begin
11
- yield self
12
- ensure
13
- self.close
14
- end
15
- else
16
- self
17
- end
18
- end
19
- end
20
- end
@@ -1,21 +0,0 @@
1
- require 'spec_helper'
2
- require 'process_shared'
3
-
4
- module ProcessShared
5
- describe Semaphore2 do
6
- it 'does stuff' do
7
- sem = Semaphore2.new(0)
8
- puts ProcessShared::Mach.shared_ports.inspect
9
- fork do
10
- puts "child: #{Process.pid}"
11
- sleep 2
12
- puts "child signaling sem"
13
- sem.post
14
- end
15
-
16
- puts "parent waiting..."
17
- sem.wait
18
- puts "parent woke up"
19
- end
20
- end
21
- end