process_shared 0.1.0 → 0.1.2

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/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