sync_attr 0.0.1 → 0.1.0
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/Rakefile +1 -1
- data/examples/class_attribute.rb +6 -7
- data/examples/instance_attribute.rb +35 -0
- data/lib/sync_attr.rb +4 -2
- data/lib/sync_attr/class_attributes.rb +39 -21
- data/lib/sync_attr/instance_attributes.rb +101 -0
- data/lib/sync_attr/version.rb +1 -1
- data/test/class_attributes_test.rb +33 -21
- data/test/instance_attributes_test.rb +88 -0
- metadata +32 -29
- data/nbproject/private/config.properties +0 -0
- data/nbproject/private/private.properties +0 -4
- data/nbproject/private/private.xml +0 -4
- data/nbproject/private/rake-d.txt +0 -0
- data/nbproject/project.properties +0 -10
- data/nbproject/project.xml +0 -16
data/Rakefile
CHANGED
@@ -18,7 +18,7 @@ task :gem do |t|
|
|
18
18
|
s.date = Date.today.to_s
|
19
19
|
s.summary = "Thread safe accessors for Ruby class and instance attributes. Supports thread safe lazy loading of attributes"
|
20
20
|
s.description = "SyncAttr is a mixin to read, write and lazy initialize both class and instance variables in a multi-threaded environment when the attribute could be modified by two threads at the same time, written in Ruby."
|
21
|
-
s.files = FileList[
|
21
|
+
s.files = FileList['**/*'].exclude('*.gem', /nbproject/)
|
22
22
|
s.has_rdoc = true
|
23
23
|
end
|
24
24
|
Gem::Builder.new(gemspec).build
|
data/examples/class_attribute.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
require 'sync_attr'
|
4
4
|
|
5
5
|
# Sample class with lazy initialized Synchronized Class Attributes
|
6
|
-
|
6
|
+
class Person
|
7
7
|
include SyncAttr
|
8
8
|
|
9
9
|
# Thread safe Class Attribute reader for name
|
@@ -20,12 +20,11 @@ def Person
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
person
|
24
|
-
puts "The person is #{person.name} with age #{person.age}"
|
23
|
+
puts "The person is #{Person.name} with age #{Person.age}"
|
25
24
|
|
26
|
-
|
27
|
-
puts "The person is #{
|
25
|
+
Person.age = 22
|
26
|
+
puts "The person is #{Person.name} now has age #{Person.age}"
|
28
27
|
|
29
|
-
|
30
|
-
puts "The person is #{
|
28
|
+
Person.age = Proc.new {|age| age += 1 }
|
29
|
+
puts "The person is #{Person.name} now has age #{Person.age}"
|
31
30
|
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# Class Attribute Example
|
2
|
+
#
|
3
|
+
require 'sync_attr'
|
4
|
+
|
5
|
+
# Sample class with lazy initialized Synchronized Class Attributes
|
6
|
+
class Person
|
7
|
+
include SyncAttr
|
8
|
+
|
9
|
+
# Thread safe Instance Attribute reader for name
|
10
|
+
# Sets :name only when it is first called
|
11
|
+
# Ideal for when name is loaded after startup from a database or config file
|
12
|
+
sync_attr_reader :name do
|
13
|
+
"Joe Bloggs"
|
14
|
+
end
|
15
|
+
|
16
|
+
# Thread safe Instance Attribute reader and writer for age
|
17
|
+
# Sets :age only when it is first called
|
18
|
+
sync_attr_accessor :age do
|
19
|
+
21
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
person = Person.new
|
24
|
+
puts "The person is #{person.name} with age #{person.age}"
|
25
|
+
|
26
|
+
person.age = 22
|
27
|
+
puts "The person is #{person.name} now has age #{person.age}"
|
28
|
+
|
29
|
+
person.age = Proc.new {|age| age += 1 }
|
30
|
+
puts "The person is #{person.name} now has age #{person.age}"
|
31
|
+
|
32
|
+
# Changes to person above do not affect any changes to second_person
|
33
|
+
# Also, the initial value that is lazy loaded into name is unaffected by person above
|
34
|
+
second_person = Person.new
|
35
|
+
puts "The second person is #{second_person.name} with age #{second_person.age}"
|
data/lib/sync_attr.rb
CHANGED
@@ -22,12 +22,14 @@
|
|
22
22
|
require 'sync'
|
23
23
|
require 'sync_attr/version'
|
24
24
|
require 'sync_attr/class_attributes'
|
25
|
-
|
25
|
+
require 'sync_attr/instance_attributes'
|
26
26
|
|
27
27
|
module SyncAttr
|
28
28
|
# Add class methods and initialize mixin
|
29
29
|
def self.included(base)
|
30
30
|
base.extend(SyncAttr::ClassAttributes::ClassMethods)
|
31
|
-
base.
|
31
|
+
base.extend(SyncAttr::InstanceAttributes::ClassMethods)
|
32
|
+
base.send(:sync_cattr_init)
|
33
|
+
base.send(:sync_attr_init)
|
32
34
|
end
|
33
35
|
end
|
@@ -25,19 +25,26 @@ module SyncAttr
|
|
25
25
|
# end
|
26
26
|
def sync_cattr_reader(*attributes, &block)
|
27
27
|
attributes.each do |attribute|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
# Now that we have exclusive access make sure that another thread has
|
36
|
-
# not just initialized this attribute
|
37
|
-
if class_variable_defined?(var_name)
|
38
|
-
class_variable_get(var_name)
|
28
|
+
metaclass.instance_eval do
|
29
|
+
define_method(attribute.to_sym) do
|
30
|
+
var_name = "@@#{attribute}".to_sym
|
31
|
+
if class_variable_defined?(var_name)
|
32
|
+
# If there is no writer then it is not necessary to protect reads
|
33
|
+
if self.respond_to?("#{attribute}=".to_sym, true)
|
34
|
+
sync_cattr_sync.synchronize(:SH) { class_variable_get(var_name) }
|
39
35
|
else
|
40
|
-
|
36
|
+
class_variable_get(var_name)
|
37
|
+
end
|
38
|
+
else
|
39
|
+
return nil unless block
|
40
|
+
sync_cattr_sync.synchronize(:EX) do
|
41
|
+
# Now that we have exclusive access make sure that another thread has
|
42
|
+
# not just initialized this attribute
|
43
|
+
if class_variable_defined?(var_name)
|
44
|
+
class_variable_get(var_name)
|
45
|
+
else
|
46
|
+
class_variable_set(var_name, class_eval(&block))
|
47
|
+
end
|
41
48
|
end
|
42
49
|
end
|
43
50
|
end
|
@@ -52,7 +59,7 @@ module SyncAttr
|
|
52
59
|
attributes.each do |attribute|
|
53
60
|
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
54
61
|
def self.#{attribute}=(value)
|
55
|
-
|
62
|
+
sync_cattr_sync.synchronize(:EX) do
|
56
63
|
if value.is_a?(Proc)
|
57
64
|
current_value = @@#{attribute} if defined?(@@#{attribute})
|
58
65
|
@@#{attribute} = value.call(current_value)
|
@@ -67,21 +74,32 @@ module SyncAttr
|
|
67
74
|
|
68
75
|
# Generate a class reader and writer for the attribute
|
69
76
|
def sync_cattr_accessor(*attributes, &block)
|
70
|
-
sync_cattr_reader(*attributes, &block)
|
71
77
|
sync_cattr_writer(*attributes)
|
78
|
+
sync_cattr_reader(*attributes, &block)
|
72
79
|
end
|
73
80
|
|
74
|
-
|
81
|
+
# Returns the metaclass or eigenclass so that we
|
82
|
+
# can dynamically generate class methods
|
83
|
+
# With thanks, see: https://gist.github.com/1199817
|
84
|
+
def metaclass
|
85
|
+
class << self;
|
86
|
+
self
|
87
|
+
end
|
88
|
+
end
|
75
89
|
|
76
|
-
#
|
77
|
-
|
78
|
-
|
90
|
+
# Returns the sync used by the included class to synchronize access to the
|
91
|
+
# class attributes
|
92
|
+
def sync_cattr_sync
|
93
|
+
@sync_cattr_sync
|
79
94
|
end
|
80
95
|
|
81
|
-
|
82
|
-
|
96
|
+
protected
|
97
|
+
|
98
|
+
# Give each class that this module is mixed into it's own Sync
|
99
|
+
def sync_cattr_init
|
100
|
+
@sync_cattr_sync = ::Sync.new
|
83
101
|
end
|
84
102
|
|
85
103
|
end
|
86
104
|
end
|
87
|
-
end
|
105
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
puts "Loaded sync_attr_reader"
|
2
|
+
# Synchronize access and lazy initialize one or more attributes
|
3
|
+
#
|
4
|
+
# Author: Reid Morrison <reidmo@gmail.com>
|
5
|
+
module SyncAttr
|
6
|
+
module InstanceAttributes
|
7
|
+
module ClassMethods
|
8
|
+
# Lazy load the specific attribute by calling the supplied block when
|
9
|
+
# the attribute is first read and then return the same value for all subsequent
|
10
|
+
# calls to the variable
|
11
|
+
#
|
12
|
+
# An optional block can be supplied to initialize the attribute
|
13
|
+
# when first read. Acts as a thread safe lazy initializer. The block will only
|
14
|
+
# be called once even if several threads call the reader at the same time
|
15
|
+
#
|
16
|
+
# Example:
|
17
|
+
# class MyClass
|
18
|
+
# include SyncAttr
|
19
|
+
#
|
20
|
+
# # Generates a reader for the class attribute 'hello'
|
21
|
+
# # and Lazy initializes the value to 'hello world' only on the first
|
22
|
+
# # call to the reader
|
23
|
+
# sync_attr_reader :hello do
|
24
|
+
# 'hello world'
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
def sync_attr_reader(*attributes, &block)
|
28
|
+
attributes.each do |attribute|
|
29
|
+
self.send(:define_method, attribute.to_sym) do
|
30
|
+
var_name = "@#{attribute}".to_sym
|
31
|
+
if instance_variable_defined?(var_name)
|
32
|
+
self.sync_attr_sync.synchronize(:SH) { instance_variable_get(var_name) }
|
33
|
+
# If there is no writer then it is not necessary to protect reads
|
34
|
+
if self.respond_to?("#{attribute}=".to_sym, true)
|
35
|
+
self.sync_attr_sync.synchronize(:SH) { instance_variable_get(var_name) }
|
36
|
+
else
|
37
|
+
instance_variable_get(var_name)
|
38
|
+
end
|
39
|
+
else
|
40
|
+
return nil unless block
|
41
|
+
self.sync_attr_sync.synchronize(:EX) do
|
42
|
+
# Now that we have exclusive access make sure that another thread has
|
43
|
+
# not just initialized this attribute
|
44
|
+
if instance_variable_defined?(var_name)
|
45
|
+
instance_variable_get(var_name)
|
46
|
+
else
|
47
|
+
instance_variable_set(var_name, instance_eval(&block))
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Generates a writer to set a synchronized attribute
|
56
|
+
# Supply a Proc ensure an attribute is not being updated by another thread:
|
57
|
+
# my_object.count = Proc.new {|count| (count||0) + 1}
|
58
|
+
def sync_attr_writer(*attributes)
|
59
|
+
attributes.each do |attribute|
|
60
|
+
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
61
|
+
def #{attribute}=(value)
|
62
|
+
self.sync_attr_sync.synchronize(:EX) do
|
63
|
+
if value.is_a?(Proc)
|
64
|
+
current_value = @#{attribute} if defined?(@#{attribute})
|
65
|
+
@#{attribute} = value.call(current_value)
|
66
|
+
else
|
67
|
+
@#{attribute} = value
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
EOS
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Generate a reader and writer for the attribute
|
76
|
+
def sync_attr_accessor(*attributes, &block)
|
77
|
+
sync_attr_reader(*attributes, &block)
|
78
|
+
sync_attr_writer(*attributes)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Give every object instance that this module is mixed into it's own Sync
|
82
|
+
# I.e. At an object level, not class level
|
83
|
+
def sync_attr_init
|
84
|
+
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
85
|
+
def sync_attr_sync
|
86
|
+
return @sync_attr_sync if @sync_attr_sync
|
87
|
+
# Use class sync_cattr_sync to ensure multiple @sync_attr_sync instances
|
88
|
+
# are not created when two or more threads call this method for the
|
89
|
+
# first time at the same time
|
90
|
+
self.class.sync_cattr_sync.synchronize(:EX) do
|
91
|
+
# In case another thread already created the sync
|
92
|
+
return @sync_attr_sync if @sync_attr_sync
|
93
|
+
@sync_attr_sync = ::Sync::new
|
94
|
+
end
|
95
|
+
end
|
96
|
+
EOS
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
data/lib/sync_attr/version.rb
CHANGED
@@ -6,10 +6,10 @@ require 'test/unit'
|
|
6
6
|
require 'shoulda'
|
7
7
|
require 'sync_attr'
|
8
8
|
|
9
|
-
class
|
9
|
+
class SyncCAttrExample
|
10
10
|
include SyncAttr
|
11
11
|
|
12
|
-
sync_cattr_reader :
|
12
|
+
sync_cattr_reader :test1 do
|
13
13
|
'hello world'
|
14
14
|
end
|
15
15
|
sync_cattr_reader :test2
|
@@ -21,11 +21,11 @@ class SynchAttrExample
|
|
21
21
|
sync_cattr_accessor :test5
|
22
22
|
end
|
23
23
|
|
24
|
-
class
|
24
|
+
class SyncCAttrExample2
|
25
25
|
include SyncAttr
|
26
26
|
|
27
|
-
sync_cattr_reader :
|
28
|
-
'
|
27
|
+
sync_cattr_reader :test1 do
|
28
|
+
'another world'
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
@@ -33,43 +33,55 @@ class ClassAttributesTest < Test::Unit::TestCase
|
|
33
33
|
context "with example" do
|
34
34
|
|
35
35
|
should 'lazy initialize class attribute' do
|
36
|
-
assert_equal 'hello world',
|
36
|
+
assert_equal 'hello world', SyncCAttrExample.test1
|
37
37
|
end
|
38
38
|
|
39
39
|
should 'return nil on class attribute without initializer' do
|
40
|
-
assert_nil
|
40
|
+
assert_nil SyncCAttrExample.test2
|
41
41
|
end
|
42
42
|
|
43
43
|
should 'set and then return a value for a class attribute without an initializer' do
|
44
|
-
assert_nil
|
45
|
-
assert_equal 'test3', (
|
46
|
-
assert_equal 'test3',
|
44
|
+
assert_nil SyncCAttrExample.test3
|
45
|
+
assert_equal 'test3', (SyncCAttrExample.test3 = 'test3')
|
46
|
+
assert_equal 'test3', SyncCAttrExample.test3
|
47
47
|
end
|
48
48
|
|
49
49
|
should 'lazy initialize class attribute and also have writer' do
|
50
|
-
assert_equal 'hello world 4',
|
51
|
-
assert_equal 'test4', (
|
52
|
-
assert_equal 'test4',
|
50
|
+
assert_equal 'hello world 4', SyncCAttrExample.test4
|
51
|
+
assert_equal 'test4', (SyncCAttrExample.test4 = 'test4')
|
52
|
+
assert_equal 'test4', SyncCAttrExample.test4
|
53
53
|
end
|
54
54
|
|
55
55
|
should 'support setting a Proc within a synch block' do
|
56
|
-
assert_nil
|
56
|
+
assert_nil SyncCAttrExample.test5
|
57
57
|
|
58
58
|
# Returns the Proc
|
59
|
-
|
60
|
-
assert_equal 1,
|
59
|
+
SyncCAttrExample.test5 = Proc.new {|val| (val||0) + 1}
|
60
|
+
assert_equal 1, SyncCAttrExample.test5
|
61
61
|
|
62
|
-
|
63
|
-
assert_equal 2,
|
62
|
+
SyncCAttrExample.test5 = Proc.new {|val| (val||0) + 1}
|
63
|
+
assert_equal 2, SyncCAttrExample.test5
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
67
67
|
context "with example2" do
|
68
68
|
|
69
69
|
should 'ensure that different classes have their own synch instances' do
|
70
|
-
assert ex1 =
|
71
|
-
assert ex2 =
|
72
|
-
assert ex1.class.send(:
|
70
|
+
assert ex1 = SyncCAttrExample.new
|
71
|
+
assert ex2 = SyncCAttrExample2.new
|
72
|
+
assert ex1.class.send(:sync_cattr_sync).object_id != ex2.class.send(:sync_cattr_sync).object_id
|
73
|
+
end
|
74
|
+
|
75
|
+
should 'ensure that different classes have their own class attributes' do
|
76
|
+
assert ex1 = SyncCAttrExample.new
|
77
|
+
assert_equal 'hello world', ex1.class.test1
|
78
|
+
assert ex2 = SyncCAttrExample2.new
|
79
|
+
assert_equal 'another world', ex2.class.test1
|
80
|
+
assert_equal 'hello world', ex1.class.test1
|
81
|
+
|
82
|
+
assert !defined? ex2.class.test2
|
83
|
+
assert !defined? ex2.class.test3
|
84
|
+
assert !defined? ex2.class.test4
|
73
85
|
end
|
74
86
|
end
|
75
87
|
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# Allow examples to be run in-place without requiring a gem install
|
2
|
+
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'test/unit'
|
6
|
+
require 'shoulda'
|
7
|
+
require 'sync_attr'
|
8
|
+
|
9
|
+
class SyncAttrExample
|
10
|
+
include SyncAttr
|
11
|
+
|
12
|
+
sync_attr_reader :test1 do
|
13
|
+
'hello world'
|
14
|
+
end
|
15
|
+
sync_attr_reader :test2
|
16
|
+
sync_attr_accessor :test3
|
17
|
+
sync_attr_accessor :test4 do
|
18
|
+
'hello world 4'
|
19
|
+
end
|
20
|
+
|
21
|
+
sync_attr_accessor :test5
|
22
|
+
end
|
23
|
+
|
24
|
+
# Ensure that class and instance attributes are distinct
|
25
|
+
class SyncAttrExample2
|
26
|
+
include SyncAttr
|
27
|
+
|
28
|
+
sync_attr_reader :test1 do
|
29
|
+
'hello world instance'
|
30
|
+
end
|
31
|
+
sync_cattr_reader :test1 do
|
32
|
+
'hello world class'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class InstanceAttributesTest < Test::Unit::TestCase
|
37
|
+
context "with example" do
|
38
|
+
|
39
|
+
should 'lazy initialize attribute' do
|
40
|
+
assert_equal 'hello world', SyncAttrExample.new.test1
|
41
|
+
end
|
42
|
+
|
43
|
+
should 'return nil on attribute without initializer' do
|
44
|
+
assert_nil SyncAttrExample.new.test2
|
45
|
+
end
|
46
|
+
|
47
|
+
should 'set and then return a value for a class attribute without an initializer' do
|
48
|
+
assert example = SyncAttrExample.new
|
49
|
+
assert_nil example.test3
|
50
|
+
assert_equal 'test3', (example.test3 = 'test3')
|
51
|
+
assert_equal 'test3', example.test3
|
52
|
+
end
|
53
|
+
|
54
|
+
should 'lazy initialize attribute and also have writer' do
|
55
|
+
assert example = SyncAttrExample.new
|
56
|
+
assert_equal 'hello world 4', example.test4
|
57
|
+
assert_equal 'test4', (example.test4 = 'test4')
|
58
|
+
assert_equal 'test4', example.test4
|
59
|
+
end
|
60
|
+
|
61
|
+
should 'support setting a Proc within a synch block' do
|
62
|
+
assert example = SyncAttrExample.new
|
63
|
+
assert_nil example.test5
|
64
|
+
|
65
|
+
# Returns the Proc
|
66
|
+
example.test5 = Proc.new {|val| (val||0) + 1}
|
67
|
+
assert_equal 1, example.test5
|
68
|
+
|
69
|
+
example.test5 = Proc.new {|val| (val||0) + 1}
|
70
|
+
assert_equal 2, example.test5
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context "with example2" do
|
75
|
+
|
76
|
+
should 'have distinct class and instance attributes when they have the same name' do
|
77
|
+
assert s = SyncAttrExample2.new
|
78
|
+
assert_equal 'hello world instance', s.test1
|
79
|
+
assert_equal 'hello world class', s.class.test1
|
80
|
+
end
|
81
|
+
|
82
|
+
should 'ensure that different classes have their own synch instances' do
|
83
|
+
assert ex1 = SyncAttrExample.new
|
84
|
+
assert ex2 = SyncAttrExample2.new
|
85
|
+
assert ex1.class.send(:sync_cattr_sync).object_id != ex2.class.send(:sync_cattr_sync).object_id
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
metadata
CHANGED
@@ -1,22 +1,26 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sync_attr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
5
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: 0.1.0
|
6
10
|
platform: ruby
|
7
11
|
authors:
|
8
|
-
|
12
|
+
- Reid Morrison
|
9
13
|
autorequire:
|
10
14
|
bindir: bin
|
11
15
|
cert_chain: []
|
12
16
|
|
13
|
-
date: 2012-
|
17
|
+
date: 2012-03-05 00:00:00 -05:00
|
14
18
|
default_executable:
|
15
19
|
dependencies: []
|
16
20
|
|
17
21
|
description: SyncAttr is a mixin to read, write and lazy initialize both class and instance variables in a multi-threaded environment when the attribute could be modified by two threads at the same time, written in Ruby.
|
18
22
|
email:
|
19
|
-
|
23
|
+
- reidmo@gmail.com
|
20
24
|
executables: []
|
21
25
|
|
22
26
|
extensions: []
|
@@ -24,20 +28,17 @@ extensions: []
|
|
24
28
|
extra_rdoc_files: []
|
25
29
|
|
26
30
|
files:
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
- nbproject/private/private.xml
|
39
|
-
- nbproject/private/rake-d.txt
|
40
|
-
- test/class_attributes_test.rb
|
31
|
+
- examples/class_attribute.rb
|
32
|
+
- examples/instance_attribute.rb
|
33
|
+
- lib/sync_attr/class_attributes.rb
|
34
|
+
- lib/sync_attr/instance_attributes.rb
|
35
|
+
- lib/sync_attr/version.rb
|
36
|
+
- lib/sync_attr.rb
|
37
|
+
- LICENSE.txt
|
38
|
+
- Rakefile
|
39
|
+
- README.md
|
40
|
+
- test/class_attributes_test.rb
|
41
|
+
- test/instance_attributes_test.rb
|
41
42
|
has_rdoc: true
|
42
43
|
homepage: https://github.com/ClarityServices/sync_attr
|
43
44
|
licenses: []
|
@@ -46,23 +47,25 @@ post_install_message:
|
|
46
47
|
rdoc_options: []
|
47
48
|
|
48
49
|
require_paths:
|
49
|
-
|
50
|
+
- lib
|
50
51
|
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
-
none: false
|
52
52
|
requirements:
|
53
|
-
|
54
|
-
|
55
|
-
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
segments:
|
56
|
+
- 0
|
57
|
+
version: "0"
|
56
58
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
59
|
requirements:
|
59
|
-
|
60
|
-
|
61
|
-
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
segments:
|
63
|
+
- 0
|
64
|
+
version: "0"
|
62
65
|
requirements: []
|
63
66
|
|
64
67
|
rubyforge_project:
|
65
|
-
rubygems_version: 1.
|
68
|
+
rubygems_version: 1.3.6
|
66
69
|
signing_key:
|
67
70
|
specification_version: 3
|
68
71
|
summary: Thread safe accessors for Ruby class and instance attributes. Supports thread safe lazy loading of attributes
|
File without changes
|
File without changes
|
@@ -1,10 +0,0 @@
|
|
1
|
-
file.reference.synch_attr-examples=examples
|
2
|
-
file.reference.synch_attr-lib=lib
|
3
|
-
file.reference.synch_attr-test=test
|
4
|
-
javac.classpath=
|
5
|
-
main.file=
|
6
|
-
platform.active=JRuby_0
|
7
|
-
source.encoding=UTF-8
|
8
|
-
src.examples.dir=examples
|
9
|
-
src.lib.dir=lib
|
10
|
-
test.test.dir=test
|
data/nbproject/project.xml
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
-
<project xmlns="http://www.netbeans.org/ns/project/1">
|
3
|
-
<type>org.netbeans.modules.ruby.rubyproject</type>
|
4
|
-
<configuration>
|
5
|
-
<data xmlns="http://www.netbeans.org/ns/ruby-project/1">
|
6
|
-
<name>sync_attr</name>
|
7
|
-
<source-roots>
|
8
|
-
<root id="src.lib.dir" name="Source Files"/>
|
9
|
-
<root id="src.examples.dir" name="Examples"/>
|
10
|
-
</source-roots>
|
11
|
-
<test-roots>
|
12
|
-
<root id="test.test.dir" name="Test Files"/>
|
13
|
-
</test-roots>
|
14
|
-
</data>
|
15
|
-
</configuration>
|
16
|
-
</project>
|