Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: pmahoney/process_shared
base: b6a6c2f241
...
head fork: pmahoney/process_shared
compare: 5aba20cdf7
  • 6 commits
  • 9 files changed
  • 1 commit comment
  • 1 contributor
View
1  .gitignore
@@ -7,4 +7,5 @@ Gemfile.lock
*.bundle
.yardoc
doc
+target
View
24 Rakefile
@@ -1,10 +1,12 @@
+require 'ci/reporter/rake/minitest'
require 'ffi'
+require 'fileutils'
+require 'flog'
require 'rake/extensiontask'
require 'rake/testtask'
require 'rake/version_task'
-require 'rubygems/package_task'
require 'rubygems/gem_runner'
-require 'ci/reporter/rake/minitest'
+require 'rubygems/package_task'
def gemspec
@gemspec ||= Gem::Specification.load('process_shared.gemspec')
@@ -51,3 +53,21 @@ if Version.current.prerelease?
sh %{rake push version:bump:pre}
end
end
+
+desc 'Generate flog reports for all ruby code'
+task :flog do
+ opts = {
+ :all => true,
+ :blame => true,
+ :details => true,
+ :group => true
+ }
+ flog = Flog.new(opts)
+ flog.flog('lib')
+ out = 'target/reports/flog.txt'
+ FileUtils.mkdir_p(File.dirname(out))
+ File.open('target/reports/flog.txt', 'wb') {|io| flog.report io }
+end
+
+desc 'Run test for CI environment with xunit reports and flog'
+task :ci_test => ['ci:setup:minitest', :test, :flog]
View
2  lib/process_shared.rb
@@ -28,4 +28,6 @@ module ProcessShared
require 'process_shared/binary_semaphore'
require 'process_shared/mutex'
require 'process_shared/condition_variable'
+require 'process_shared/monitor'
+require 'process_shared/monitor_mixin'
View
31 lib/process_shared/monitor.rb
@@ -0,0 +1,31 @@
+require 'process_shared'
+require 'process_shared/mutex'
+
+module ProcessShared
+ class Monitor < Mutex
+ def initialize
+ super
+ @lock_count = 0
+ end
+
+ def lock
+ if locked_by == ::Process.pid
+ @lock_count += 1
+ else
+ super
+ end
+ end
+
+ def unlock
+ if locked_by == ::Process.pid
+ if @lock_count > 0
+ @lock_count -= 1
+ else
+ super
+ end
+ else
+ super
+ end
+ end
+ end
+end
View
42 lib/process_shared/monitor_mixin.rb
@@ -0,0 +1,42 @@
+require 'process_shared'
+
+module ProcessShared
+ module MonitorMixin
+ def self.extended(obj)
+ obj.send :mon_initialize
+ end
+
+ def mon_enter
+ @mon_monitor.lock
+ end
+
+ def mon_exit
+ @mon_monitor.unlock
+ end
+
+ def mon_synchronize
+ mon_enter
+ begin
+ yield
+ ensure
+ mon_exit
+ end
+ end
+ alias_method :synchronize, :mon_synchronize
+
+ def mon_try_enter
+ raise NotImplementedError, 'not implemented'
+ end
+ alias_method :try_mon_enter, :mon_try_enter
+
+ def new_cond
+ raise NotImplementedError, 'not implemented'
+ end
+
+ private
+
+ def mon_initialize
+ @mon_monitor = Monitor.new
+ end
+ end
+end
View
11 lib/process_shared/mutex.rb
@@ -94,7 +94,7 @@ def synchronize
end
end
- private
+ protected
def locked_by
with_internal_lock do
@@ -108,13 +108,8 @@ def locked_by=(val)
end
end
- def with_internal_lock
- @internal_sem.wait
- begin
- yield
- ensure
- @internal_sem.post
- end
+ def with_internal_lock(&block)
+ @internal_sem.synchronize &block
end
end
end
View
7 process_shared.gemspec
@@ -14,10 +14,11 @@ Gem::Specification.new do |s|
s.add_dependency('ffi', '~> 1.0')
- s.add_development_dependency('rake')
- s.add_development_dependency('rake-compiler')
+ s.add_development_dependency('ci_reporter')
+ s.add_development_dependency('flog')
s.add_development_dependency('minitest')
s.add_development_dependency('minitest-matchers')
+ s.add_development_dependency('rake')
+ s.add_development_dependency('rake-compiler')
s.add_development_dependency('version')
- s.add_development_dependency('ci_reporter')
end
View
33 spec/process_shared/monitor_mixin_spec.rb
@@ -0,0 +1,33 @@
+require 'spec_helper'
+require 'process_shared'
+
+module ProcessShared
+ describe MonitorMixin do
+
+ before :each do
+ @obj = Object.new
+ @obj.extend(MonitorMixin)
+ end
+
+ it 'raises exception when unlocked by other process' do
+ pid = Kernel.fork do
+ @obj.mon_enter
+ sleep 0.2
+ @obj.mon_exit
+ Kernel.exit!
+ end
+
+ sleep 0.1
+ proc { @obj.mon_exit }.must_raise(ProcessError)
+
+ ::Process.wait(pid)
+ end
+
+ it 'raises nothing with nested lock' do
+ @obj.mon_enter
+ @obj.mon_enter
+ @obj.mon_exit
+ @obj.mon_exit
+ end
+ end
+end
View
34 spec/process_shared/monitor_spec.rb
@@ -0,0 +1,34 @@
+require 'spec_helper'
+require 'process_shared'
+
+module ProcessShared
+ describe Monitor do
+
+ include LockBehavior
+
+ before :each do
+ @lock = Monitor.new
+ end
+
+ it 'raises exception when unlocked by other process' do
+ pid = Kernel.fork do
+ @lock.lock
+ sleep 0.2
+ @lock.unlock
+ Kernel.exit!
+ end
+
+ sleep 0.1
+ proc { @lock.unlock }.must_raise(ProcessError)
+
+ ::Process.wait(pid)
+ end
+
+ it 'raises nothing with nested lock' do
+ @lock.lock
+ @lock.lock
+ @lock.unlock
+ @lock.unlock
+ end
+ end
+end

Showing you all comments on commits in this comparison.

@rdp

I wonder if transactional memory: http://gcc.gnu.org/gcc-4.7/changes.html would be interesting to this project at some point...though probably not necessary :)

Something went wrong with that request. Please try again.