Refactor class hierarchy, implementation selection details.
This commit is contained in:
		
							parent
							
								
									64b746a98c
								
							
						
					
					
						commit
						15fe2e5057
					
				|  | @ -3,25 +3,10 @@ require 'ffi' | ||||||
| if RUBY_VERSION =~ /^1.8/ | if RUBY_VERSION =~ /^1.8/ | ||||||
|   require 'process_shared/define_singleton_method' |   require 'process_shared/define_singleton_method' | ||||||
|    |    | ||||||
|   module ProcessShared |   class Module | ||||||
|     module PSem |     include ProcessShared::DefineSingletonMethod | ||||||
|       extend DefineSingletonMethod |  | ||||||
|     end |  | ||||||
| 
 |  | ||||||
|     module RT |  | ||||||
|       extend DefineSingletonMethod |  | ||||||
|     end |  | ||||||
| 
 |  | ||||||
|     module LibC |  | ||||||
|       extend DefineSingletonMethod |  | ||||||
|   end |   end | ||||||
| end | end | ||||||
| end |  | ||||||
| 
 |  | ||||||
| require 'process_shared/semaphore' |  | ||||||
| require 'process_shared/binary_semaphore' |  | ||||||
| require 'process_shared/mutex' |  | ||||||
| require 'process_shared/shared_memory' |  | ||||||
| 
 | 
 | ||||||
| module ProcessShared | module ProcessShared | ||||||
|   case FFI::Platform::OS |   case FFI::Platform::OS | ||||||
|  | @ -29,13 +14,18 @@ module ProcessShared | ||||||
|     require 'process_shared/posix/shared_memory' |     require 'process_shared/posix/shared_memory' | ||||||
|     require 'process_shared/posix/semaphore' |     require 'process_shared/posix/semaphore' | ||||||
| 
 | 
 | ||||||
|     SharedMemory.impl = Posix::SharedMemory |     SharedMemory = Posix::SharedMemory | ||||||
|     Semaphore.impl = Posix::Semaphore |     Semaphore = Posix::Semaphore | ||||||
|   when 'darwin' |   when 'darwin' | ||||||
|     require 'process_shared/posix/shared_memory' |     require 'process_shared/posix/shared_memory' | ||||||
|     require 'process_shared/mach/semaphore' |     require 'process_shared/mach/semaphore' | ||||||
| 
 | 
 | ||||||
|     SharedMemory.impl = Posix::SharedMemory |     SharedMemory = Posix::SharedMemory | ||||||
|     Semaphore.impl = Mach::Semaphore |     Semaphore = Mach::Semaphore | ||||||
|   end |   end | ||||||
| end | end | ||||||
|  | 
 | ||||||
|  | require 'process_shared/binary_semaphore' | ||||||
|  | require 'process_shared/mutex' | ||||||
|  | require 'process_shared/condition_variable' | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  | @ -1,8 +1,7 @@ | ||||||
| require 'forwardable' | require 'forwardable' | ||||||
| 
 | 
 | ||||||
| require 'process_shared' | require 'process_shared' | ||||||
| require 'process_shared/with_self' | require 'process_shared/open_with_self' | ||||||
| require 'process_shared/semaphore' |  | ||||||
| require 'process_shared/process_error' | require 'process_shared/process_error' | ||||||
| 
 | 
 | ||||||
| module ProcessShared | module ProcessShared | ||||||
|  | @ -14,14 +13,10 @@ module ProcessShared | ||||||
|   # This is identical to a Semaphore but with extra error checking. |   # This is identical to a Semaphore but with extra error checking. | ||||||
|   class BinarySemaphore |   class BinarySemaphore | ||||||
|     extend Forwardable |     extend Forwardable | ||||||
|     include ProcessShared::WithSelf |     extend ProcessShared::OpenWithSelf | ||||||
| 
 | 
 | ||||||
|     def_delegators :@sem, :wait, :try_wait, :synchronize, :value, :close |     def_delegators :@sem, :wait, :try_wait, :synchronize, :value, :close | ||||||
| 
 | 
 | ||||||
|     def self.open(value = 1, &block) |  | ||||||
|       new(value).with_self(&block) |  | ||||||
|     end |  | ||||||
| 
 |  | ||||||
|     # Create a new semaphore with initial value +value+.  After |     # Create a new semaphore with initial value +value+.  After | ||||||
|     # {Kernel#fork}, the semaphore will be shared across two (or more) |     # {Kernel#fork}, the semaphore will be shared across two (or more) | ||||||
|     # processes. The semaphore must be closed with {#close} in each |     # processes. The semaphore must be closed with {#close} in each | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| require 'process_shared/semaphore' | require 'process_shared' | ||||||
| 
 | 
 | ||||||
| module ProcessShared | module ProcessShared | ||||||
|   class ConditionVariable |   class ConditionVariable | ||||||
|  |  | ||||||
|  | @ -2,12 +2,15 @@ require 'mach' | ||||||
| require 'mach/error' | require 'mach/error' | ||||||
| 
 | 
 | ||||||
| require 'process_shared/mach' | require 'process_shared/mach' | ||||||
|  | require 'process_shared/open_with_self' | ||||||
|  | require 'process_shared/synchronizable_semaphore' | ||||||
| 
 | 
 | ||||||
| module ProcessShared | module ProcessShared | ||||||
|   module Mach |   module Mach | ||||||
|     # Extends ::Mach::Semaphore to be compatible with ProcessShared::Semaphore |     # Extends ::Mach::Semaphore to be compatible with ProcessShared::Semaphore | ||||||
|     class Semaphore < ::Mach::Semaphore |     class Semaphore < ::Mach::Semaphore | ||||||
|       include ProcessShared::Semaphore |       extend ProcessShared::OpenWithSelf | ||||||
|  |       include ProcessShared::SynchronizableSemaphore | ||||||
| 
 | 
 | ||||||
|       def initialize(value = 1) |       def initialize(value = 1) | ||||||
|         super(:value => value) |         super(:value => value) | ||||||
|  |  | ||||||
|  | @ -1,6 +1,5 @@ | ||||||
| require 'process_shared/semaphore' | require 'process_shared' | ||||||
| require 'process_shared/with_self' | require 'process_shared/open_with_self' | ||||||
| require 'process_shared/shared_memory' |  | ||||||
| require 'process_shared/process_error' | require 'process_shared/process_error' | ||||||
| 
 | 
 | ||||||
| module ProcessShared | module ProcessShared | ||||||
|  | @ -20,11 +19,7 @@ module ProcessShared | ||||||
|   # release its {Semaphore} and {SharedMemory} resources.  For now, |   # release its {Semaphore} and {SharedMemory} resources.  For now, | ||||||
|   # rely on the object finalizers of those objects... |   # rely on the object finalizers of those objects... | ||||||
|   class Mutex |   class Mutex | ||||||
|     # include WithSelf |     extend OpenWithSelf | ||||||
| 
 |  | ||||||
|     # def self.open(&block) |  | ||||||
|     #   new.with_self(&block) |  | ||||||
|     # end |  | ||||||
| 
 | 
 | ||||||
|     def initialize |     def initialize | ||||||
|       @internal_sem = Semaphore.new |       @internal_sem = Semaphore.new | ||||||
|  |  | ||||||
|  | @ -1,23 +1,9 @@ | ||||||
| require 'process_shared/with_self' |  | ||||||
| require 'process_shared/shared_memory_io' | require 'process_shared/shared_memory_io' | ||||||
| 
 | 
 | ||||||
| module ProcessShared | module ProcessShared | ||||||
|   # Memory block shared across processes. |   # Provides reading and writing of serialized objects from a memory | ||||||
|   module SharedMemory |   # buffer. | ||||||
|     include ProcessShared::WithSelf |   module ObjectBuffer | ||||||
| 
 |  | ||||||
|     class << self |  | ||||||
|       attr_accessor :impl |  | ||||||
| 
 |  | ||||||
|       def new(*args) |  | ||||||
|         impl.new(*args) |  | ||||||
|       end |  | ||||||
| 
 |  | ||||||
|       def open(size, &block) |  | ||||||
|         new(size).with_self(&block) |  | ||||||
|       end |  | ||||||
|     end |  | ||||||
| 
 |  | ||||||
|     # Write the serialization of +obj+ (using Marshal.dump) to this |     # Write the serialization of +obj+ (using Marshal.dump) to this | ||||||
|     # shared memory object at +offset+ (in bytes). |     # shared memory object at +offset+ (in bytes). | ||||||
|     # |     # | ||||||
|  | @ -0,0 +1,20 @@ | ||||||
|  | module ProcessShared | ||||||
|  |   module OpenWithSelf | ||||||
|  |     # Like #new but if the optional code block is given, it will be | ||||||
|  |     # passed the new object as an argument, and the object will | ||||||
|  |     # automatically be closed (by invoking +close+) when the block | ||||||
|  |     # terminates. In this instance, value of the block is returned. | ||||||
|  |     def open(*args, &block) | ||||||
|  |       obj = new(*args) | ||||||
|  |       if block_given? | ||||||
|  |         begin | ||||||
|  |           yield obj | ||||||
|  |         ensure | ||||||
|  |           obj.close | ||||||
|  |         end | ||||||
|  |       else | ||||||
|  |         obj | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| require 'process_shared/semaphore' | require 'process_shared/synchronizable_semaphore' | ||||||
|  | require 'process_shared/open_with_self' | ||||||
| 
 | 
 | ||||||
| require 'process_shared/posix/errno' | require 'process_shared/posix/errno' | ||||||
| require 'process_shared/posix/libc' | require 'process_shared/posix/libc' | ||||||
|  | @ -34,8 +35,9 @@ module ProcessShared | ||||||
|                     :sem_timedwait) |                     :sem_timedwait) | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|  |       extend ProcessShared::OpenWithSelf | ||||||
|       include Foreign |       include Foreign | ||||||
|       include ProcessShared::Semaphore |       include ProcessShared::SynchronizableSemaphore | ||||||
| 
 | 
 | ||||||
|       # Make a Proc suitable for use as a finalizer that will call |       # Make a Proc suitable for use as a finalizer that will call | ||||||
|       # +shm_unlink+ on +sem+. |       # +shm_unlink+ on +sem+. | ||||||
|  |  | ||||||
|  | @ -2,7 +2,8 @@ require 'ffi' | ||||||
| 
 | 
 | ||||||
| require 'process_shared/posix/errno' | require 'process_shared/posix/errno' | ||||||
| require 'process_shared/posix/libc' | require 'process_shared/posix/libc' | ||||||
| require 'process_shared/shared_memory' | require 'process_shared/object_buffer' | ||||||
|  | require 'process_shared/open_with_self' | ||||||
| 
 | 
 | ||||||
| module ProcessShared | module ProcessShared | ||||||
|   module Posix |   module Posix | ||||||
|  | @ -25,10 +26,10 @@ module ProcessShared | ||||||
|         error_check :shm_open, :shm_unlink |         error_check :shm_open, :shm_unlink | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|  |       extend ProcessShared::OpenWithSelf | ||||||
|       include SharedMemory::Foreign |       include SharedMemory::Foreign | ||||||
|       include LibC |       include LibC | ||||||
|        |       include ProcessShared::ObjectBuffer | ||||||
|       include ProcessShared::SharedMemory |  | ||||||
| 
 | 
 | ||||||
|       attr_reader :size, :type, :type_size, :count, :fd |       attr_reader :size, :type, :type_size, :count, :fd | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,37 +0,0 @@ | ||||||
| require 'process_shared/with_self' |  | ||||||
| 
 |  | ||||||
| module ProcessShared |  | ||||||
|   module Semaphore |  | ||||||
|     include ProcessShared::WithSelf |  | ||||||
| 
 |  | ||||||
|     class << self |  | ||||||
|       # the implementation to use to create semaphores.  impl is set |  | ||||||
|       # based on the platform in 'process_shared' |  | ||||||
|       attr_accessor :impl |  | ||||||
|        |  | ||||||
|       def new(*args) |  | ||||||
|         impl.new(*args) |  | ||||||
|       end |  | ||||||
| 
 |  | ||||||
|       # With no associated block, open is a synonym for |  | ||||||
|       # Semaphore.new. If the optional code block is given, it will be |  | ||||||
|       # passed +sem+ as an argument, and the Semaphore object will |  | ||||||
|       # automatically be closed when the block terminates. In this |  | ||||||
|       # instance, Semaphore.open returns the value of the block. |  | ||||||
|       # |  | ||||||
|       # @param [Integer] value the initial semaphore value |  | ||||||
|       def open(value = 1, &block) |  | ||||||
|         new(value).with_self(&block) |  | ||||||
|       end |  | ||||||
|     end |  | ||||||
| 
 |  | ||||||
|     def synchronize |  | ||||||
|       wait |  | ||||||
|       begin |  | ||||||
|         yield |  | ||||||
|       ensure |  | ||||||
|         post |  | ||||||
|       end |  | ||||||
|     end |  | ||||||
|   end |  | ||||||
| end |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| require 'process_shared' | require 'process_shared' | ||||||
| 
 | 
 | ||||||
| module ProcessShared | module ProcessShared | ||||||
|   class SharedArray < SharedMemory.impl |   class SharedArray < SharedMemory | ||||||
|     include Enumerable |     include Enumerable | ||||||
| 
 | 
 | ||||||
|     # A fixed-size array in shared memory.  Processes forked from this |     # A fixed-size array in shared memory.  Processes forked from this | ||||||
|  |  | ||||||
|  | @ -0,0 +1,16 @@ | ||||||
|  | module ProcessShared | ||||||
|  |   module SynchronizableSemaphore | ||||||
|  |     # Yield the block after decrementing the semaphore, ensuring that | ||||||
|  |     # the semaphore is incremented. | ||||||
|  |     # | ||||||
|  |     # @return [Object] the value of the block | ||||||
|  |     def synchronize | ||||||
|  |       wait | ||||||
|  |       begin | ||||||
|  |         yield | ||||||
|  |       ensure | ||||||
|  |         post | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -1,20 +0,0 @@ | ||||||
| module ProcessShared |  | ||||||
|   module WithSelf |  | ||||||
|     # With no associated block, return self.  If the optional code |  | ||||||
|     # block is given, it will be passed `self` as an argument, and the |  | ||||||
|     # self object will automatically be closed (by invoking +close+ on |  | ||||||
|     # +self+) when the block terminates. In this instance, value of |  | ||||||
|     # the block is returned. |  | ||||||
|     def with_self |  | ||||||
|       if block_given? |  | ||||||
|         begin |  | ||||||
|           yield self |  | ||||||
|         ensure |  | ||||||
|           self.close |  | ||||||
|         end |  | ||||||
|       else |  | ||||||
|         self |  | ||||||
|       end |  | ||||||
|     end |  | ||||||
|   end |  | ||||||
| end |  | ||||||
|  | @ -30,6 +30,7 @@ module Mach | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|     it 'coordinates access to shared resource between two tasks' do |     it 'coordinates access to shared resource between two tasks' do | ||||||
|  |       begin | ||||||
|         sem = Semaphore.new(:value => 0) |         sem = Semaphore.new(:value => 0) | ||||||
| 
 | 
 | ||||||
|         port = Port.new |         port = Port.new | ||||||
|  | @ -55,6 +56,9 @@ module Mach | ||||||
|         Process.wait child |         Process.wait child | ||||||
| 
 | 
 | ||||||
|         elapsed.must be_gt(0.4) |         elapsed.must be_gt(0.4) | ||||||
|  |       ensure | ||||||
|  |         Task.self.set_bootstrap_port(Mach::Functions.bootstrap_port) | ||||||
|  |       end | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
| end | end | ||||||
|  |  | ||||||
|  | @ -1,6 +1,5 @@ | ||||||
| require 'spec_helper' | require 'spec_helper' | ||||||
| require 'process_shared/mutex' | require 'process_shared' | ||||||
| require 'process_shared/shared_memory' |  | ||||||
| 
 | 
 | ||||||
| module ProcessShared | module ProcessShared | ||||||
|   describe Mutex do |   describe Mutex do | ||||||
|  | @ -60,9 +59,9 @@ module ProcessShared | ||||||
| 
 | 
 | ||||||
|       pid = Kernel.fork do |       pid = Kernel.fork do | ||||||
|         mutex.lock |         mutex.lock | ||||||
|         sleep 0.2 |         # sleep 0.2 | ||||||
|         mutex.unlock |         # mutex.unlock | ||||||
|         Kernel.exit! |         # Kernel.exit! | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       sleep 0.1 |       sleep 0.1 | ||||||
|  |  | ||||||
|  | @ -1,8 +1,7 @@ | ||||||
| require 'spec_helper' | require 'spec_helper' | ||||||
| 
 | 
 | ||||||
| require 'ffi' | require 'ffi' | ||||||
| require 'process_shared/semaphore' | require 'process_shared' | ||||||
| require 'process_shared/shared_memory' |  | ||||||
| 
 | 
 | ||||||
| module ProcessShared | module ProcessShared | ||||||
|   describe Semaphore do |   describe Semaphore do | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue