synchronizable 0.0.1

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.
@@ -0,0 +1,5 @@
1
+ .idea/*
2
+ *.gem
3
+ .bundle
4
+ Gemfile.lock
5
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+ gemspec
3
+
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Ryan LeCompte
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,59 @@
1
+ = Synchronizable
2
+
3
+ Synchronizable is a gem that provides an easy module-based mechanism
4
+ for making any object thread-safe with an instance-level lock. This
5
+ gem was originally inspired from Mike Perham's dalli gem, which provides
6
+ a ThreadSafe module for his memcached client. However, that solution
7
+ is not currently generic. This gem attempts to provide a generic solution
8
+ that can work with any object (including classes/modules) in your system.
9
+
10
+ == Installation
11
+
12
+ Synchronizable is available as a RubyGem:
13
+
14
+ gem install synchronizable
15
+
16
+ == Examples
17
+
18
+ class Foo
19
+ def bar
20
+ end
21
+
22
+ def baz
23
+ end
24
+ end
25
+
26
+ foo = Foo.new
27
+ # the foo instance now has all methods synchronized / thread-safe
28
+ foo.extend(Synchronizable)
29
+
30
+ # note that classes are objects in Ruby and can also be synchronized
31
+ class Bar
32
+ def self.foo
33
+ end
34
+ end
35
+
36
+ # only class/singleton methods will become synchronized
37
+ Bar.extend(Synchronizable)
38
+
39
+ == Note on Patches/Pull Requests
40
+
41
+ * Fork the project.
42
+ * Make your feature addition or bug fix.
43
+ * Add tests for it. This is important so I don't break it in a future version unintentionally.
44
+ * Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
45
+ * Send me a pull request. Bonus points for topic branches.
46
+
47
+ == Authors
48
+
49
+ * Ryan LeCompte
50
+
51
+ == Credits
52
+
53
+ * Mike Perham (inspired from ThreadSafety module in https://github.com/mperham/dalli)
54
+
55
+ == Copyright
56
+
57
+ Copyright (c) 2011 Ryan LeCompte. See LICENSE for
58
+ further details.
59
+
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,30 @@
1
+ require 'thread'
2
+ require 'synchronizable/version'
3
+
4
+ # Synchronizable is intended to be injected into objects via Object#extend.
5
+ # After Object#extend(Synchronizable) is performed, the object's original
6
+ # methods will become synchronized via a per-instance lock.
7
+ module Synchronizable
8
+ IGNORABLE_METHOD_OWNERS = [Object, Kernel, BasicObject]
9
+
10
+ def self.extended(obj)
11
+ # immediately create object-level lock
12
+ obj.send(:__lock)
13
+
14
+ # redefine all user-defined methods to utilize lock
15
+ obj.methods.each do |m|
16
+ next if IGNORABLE_METHOD_OWNERS.include?(obj.method(m).owner)
17
+ obj.define_singleton_method(m) do |*args, &block|
18
+ __lock.synchronize do
19
+ super(*args, &block)
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def __lock
28
+ @__lock ||= Mutex.new
29
+ end
30
+ end
@@ -0,0 +1,3 @@
1
+ module Synchronizable
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,8 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'rspec'
4
+ require 'synchronizable'
5
+
6
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
7
+ RSpec.configure do |config|
8
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe Synchronizable do
4
+ context "when extended by an object" do
5
+ let(:object) { String.new }
6
+
7
+ it "creates an instance-level lock" do
8
+ object.instance_variables.should_not include(:@__lock)
9
+ object.extend(Synchronizable)
10
+ object.instance_variables.should include(:@__lock)
11
+ end
12
+
13
+ it "creates a locked version of each original method" do
14
+ class TestLock
15
+ attr_reader :sync_invoked
16
+
17
+ def initialize
18
+ @sync_invoked = false
19
+ end
20
+
21
+ def synchronize(&block)
22
+ @sync_invoked = true
23
+ end
24
+ end
25
+
26
+ lock = TestLock.new
27
+ object.extend(Synchronizable)
28
+ object.instance_variable_set(:@__lock, lock)
29
+
30
+ # methods from Object not wrapped
31
+ object.object_id
32
+ lock.sync_invoked.should == false
33
+
34
+ # class-defined methods should be wrapped
35
+ object.size
36
+ lock.sync_invoked.should == true
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "synchronizable/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "synchronizable"
7
+ s.version = Synchronizable::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Ryan LeCompte"]
10
+ s.email = ["lecompte@gmail.com"]
11
+ s.homepage = "http://github.com/ryanlecompte/synchronizable"
12
+ s.summary = %q{Synchronizable is a generic way to provide per-object thread safety}
13
+ s.description = %q{Synchronizable is a generic way to provide per-object thread safety}
14
+
15
+ s.rubyforge_project = "synchronizable"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- spec/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_development_dependency("rspec", "~> 2.5.0")
23
+ end
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: synchronizable
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Ryan LeCompte
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-07-28 00:00:00 -04:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rspec
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 2
30
+ - 5
31
+ - 0
32
+ version: 2.5.0
33
+ type: :development
34
+ version_requirements: *id001
35
+ description: Synchronizable is a generic way to provide per-object thread safety
36
+ email:
37
+ - lecompte@gmail.com
38
+ executables: []
39
+
40
+ extensions: []
41
+
42
+ extra_rdoc_files: []
43
+
44
+ files:
45
+ - .gitignore
46
+ - Gemfile
47
+ - LICENSE
48
+ - README.rdoc
49
+ - Rakefile
50
+ - lib/synchronizable.rb
51
+ - lib/synchronizable/version.rb
52
+ - spec/spec_helper.rb
53
+ - spec/synchronizable/synchronizable_spec.rb
54
+ - synchronizable.gemspec
55
+ has_rdoc: true
56
+ homepage: http://github.com/ryanlecompte/synchronizable
57
+ licenses: []
58
+
59
+ post_install_message:
60
+ rdoc_options: []
61
+
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ segments:
70
+ - 0
71
+ version: "0"
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ segments:
78
+ - 0
79
+ version: "0"
80
+ requirements: []
81
+
82
+ rubyforge_project: synchronizable
83
+ rubygems_version: 1.3.7
84
+ signing_key:
85
+ specification_version: 3
86
+ summary: Synchronizable is a generic way to provide per-object thread safety
87
+ test_files:
88
+ - spec/spec_helper.rb
89
+ - spec/synchronizable/synchronizable_spec.rb