garcun 0.0.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.
Files changed (139) hide show
  1. checksums.yaml +7 -0
  2. data/.gitattributes +17 -0
  3. data/.gitignore +197 -0
  4. data/.rspec +2 -0
  5. data/Gemfile +22 -0
  6. data/LICENSE +201 -0
  7. data/README.md +521 -0
  8. data/Rakefile +47 -0
  9. data/garcun.gemspec +83 -0
  10. data/lib/garcon.rb +290 -0
  11. data/lib/garcon/chef/chef_helpers.rb +343 -0
  12. data/lib/garcon/chef/coerce/coercer.rb +134 -0
  13. data/lib/garcon/chef/coerce/coercions/boolean_definitions.rb +34 -0
  14. data/lib/garcon/chef/coerce/coercions/date_definitions.rb +32 -0
  15. data/lib/garcon/chef/coerce/coercions/date_time_definitions.rb +32 -0
  16. data/lib/garcon/chef/coerce/coercions/fixnum_definitions.rb +34 -0
  17. data/lib/garcon/chef/coerce/coercions/float_definitions.rb +32 -0
  18. data/lib/garcon/chef/coerce/coercions/hash_definitions.rb +29 -0
  19. data/lib/garcon/chef/coerce/coercions/integer_definitions.rb +31 -0
  20. data/lib/garcon/chef/coerce/coercions/string_definitions.rb +45 -0
  21. data/lib/garcon/chef/coerce/coercions/time_definitions.rb +32 -0
  22. data/lib/garcon/chef/handler/devreporter.rb +127 -0
  23. data/lib/garcon/chef/log.rb +64 -0
  24. data/lib/garcon/chef/node.rb +100 -0
  25. data/lib/garcon/chef/provider/civilize.rb +209 -0
  26. data/lib/garcon/chef/provider/development.rb +159 -0
  27. data/lib/garcon/chef/provider/download.rb +420 -0
  28. data/lib/garcon/chef/provider/house_keeping.rb +265 -0
  29. data/lib/garcon/chef/provider/node_cache.rb +31 -0
  30. data/lib/garcon/chef/provider/partial.rb +183 -0
  31. data/lib/garcon/chef/provider/recovery.rb +80 -0
  32. data/lib/garcon/chef/provider/zip_file.rb +271 -0
  33. data/lib/garcon/chef/resource/attribute.rb +52 -0
  34. data/lib/garcon/chef/resource/base_dsl.rb +174 -0
  35. data/lib/garcon/chef/resource/blender.rb +140 -0
  36. data/lib/garcon/chef/resource/lazy_eval.rb +66 -0
  37. data/lib/garcon/chef/resource/resource_name.rb +109 -0
  38. data/lib/garcon/chef/secret_bag.rb +204 -0
  39. data/lib/garcon/chef/validations.rb +76 -0
  40. data/lib/garcon/chef_inclusions.rb +151 -0
  41. data/lib/garcon/configuration.rb +138 -0
  42. data/lib/garcon/core_ext.rb +39 -0
  43. data/lib/garcon/core_ext/array.rb +27 -0
  44. data/lib/garcon/core_ext/binding.rb +64 -0
  45. data/lib/garcon/core_ext/boolean.rb +66 -0
  46. data/lib/garcon/core_ext/duration.rb +271 -0
  47. data/lib/garcon/core_ext/enumerable.rb +34 -0
  48. data/lib/garcon/core_ext/file.rb +127 -0
  49. data/lib/garcon/core_ext/filetest.rb +62 -0
  50. data/lib/garcon/core_ext/hash.rb +279 -0
  51. data/lib/garcon/core_ext/kernel.rb +159 -0
  52. data/lib/garcon/core_ext/lazy.rb +222 -0
  53. data/lib/garcon/core_ext/method_access.rb +243 -0
  54. data/lib/garcon/core_ext/module.rb +92 -0
  55. data/lib/garcon/core_ext/nil.rb +53 -0
  56. data/lib/garcon/core_ext/numeric.rb +44 -0
  57. data/lib/garcon/core_ext/object.rb +342 -0
  58. data/lib/garcon/core_ext/pathname.rb +152 -0
  59. data/lib/garcon/core_ext/process.rb +41 -0
  60. data/lib/garcon/core_ext/random.rb +497 -0
  61. data/lib/garcon/core_ext/string.rb +312 -0
  62. data/lib/garcon/core_ext/struct.rb +49 -0
  63. data/lib/garcon/core_ext/symbol.rb +170 -0
  64. data/lib/garcon/core_ext/time.rb +234 -0
  65. data/lib/garcon/exceptions.rb +101 -0
  66. data/lib/garcon/inflections.rb +237 -0
  67. data/lib/garcon/inflections/defaults.rb +79 -0
  68. data/lib/garcon/inflections/inflections.rb +182 -0
  69. data/lib/garcon/inflections/rules_collection.rb +37 -0
  70. data/lib/garcon/secret.rb +271 -0
  71. data/lib/garcon/stash/format.rb +114 -0
  72. data/lib/garcon/stash/journal.rb +226 -0
  73. data/lib/garcon/stash/queue.rb +83 -0
  74. data/lib/garcon/stash/serializer.rb +86 -0
  75. data/lib/garcon/stash/store.rb +435 -0
  76. data/lib/garcon/task.rb +31 -0
  77. data/lib/garcon/task/atomic.rb +151 -0
  78. data/lib/garcon/task/atomic_boolean.rb +127 -0
  79. data/lib/garcon/task/condition.rb +99 -0
  80. data/lib/garcon/task/copy_on_notify_observer_set.rb +154 -0
  81. data/lib/garcon/task/copy_on_write_observer_set.rb +153 -0
  82. data/lib/garcon/task/count_down_latch.rb +92 -0
  83. data/lib/garcon/task/delay.rb +196 -0
  84. data/lib/garcon/task/dereferenceable.rb +144 -0
  85. data/lib/garcon/task/event.rb +119 -0
  86. data/lib/garcon/task/executor.rb +275 -0
  87. data/lib/garcon/task/executor_options.rb +59 -0
  88. data/lib/garcon/task/future.rb +107 -0
  89. data/lib/garcon/task/immediate_executor.rb +84 -0
  90. data/lib/garcon/task/ivar.rb +171 -0
  91. data/lib/garcon/task/lazy_reference.rb +74 -0
  92. data/lib/garcon/task/monotonic_time.rb +69 -0
  93. data/lib/garcon/task/obligation.rb +256 -0
  94. data/lib/garcon/task/observable.rb +101 -0
  95. data/lib/garcon/task/priority_queue.rb +234 -0
  96. data/lib/garcon/task/processor_count.rb +128 -0
  97. data/lib/garcon/task/read_write_lock.rb +304 -0
  98. data/lib/garcon/task/safe_task_executor.rb +58 -0
  99. data/lib/garcon/task/single_thread_executor.rb +97 -0
  100. data/lib/garcon/task/thread_pool/cached.rb +71 -0
  101. data/lib/garcon/task/thread_pool/executor.rb +294 -0
  102. data/lib/garcon/task/thread_pool/fixed.rb +61 -0
  103. data/lib/garcon/task/thread_pool/worker.rb +90 -0
  104. data/lib/garcon/task/timer.rb +44 -0
  105. data/lib/garcon/task/timer_set.rb +194 -0
  106. data/lib/garcon/task/timer_task.rb +377 -0
  107. data/lib/garcon/task/waitable_list.rb +58 -0
  108. data/lib/garcon/utility/ansi.rb +199 -0
  109. data/lib/garcon/utility/at_random.rb +77 -0
  110. data/lib/garcon/utility/crypto.rb +292 -0
  111. data/lib/garcon/utility/equalizer.rb +146 -0
  112. data/lib/garcon/utility/faker/extensions/array.rb +22 -0
  113. data/lib/garcon/utility/faker/extensions/symbol.rb +9 -0
  114. data/lib/garcon/utility/faker/faker.rb +164 -0
  115. data/lib/garcon/utility/faker/faker/company.rb +17 -0
  116. data/lib/garcon/utility/faker/faker/hacker.rb +30 -0
  117. data/lib/garcon/utility/faker/faker/version.rb +3 -0
  118. data/lib/garcon/utility/faker/locales/en-US.yml +83 -0
  119. data/lib/garcon/utility/faker/locales/en.yml +21 -0
  120. data/lib/garcon/utility/file_helper.rb +170 -0
  121. data/lib/garcon/utility/hookers.rb +178 -0
  122. data/lib/garcon/utility/interpolation.rb +90 -0
  123. data/lib/garcon/utility/memstash.rb +364 -0
  124. data/lib/garcon/utility/misc.rb +54 -0
  125. data/lib/garcon/utility/msg_from_god.rb +62 -0
  126. data/lib/garcon/utility/retry.rb +238 -0
  127. data/lib/garcon/utility/timeout.rb +58 -0
  128. data/lib/garcon/utility/uber/builder.rb +91 -0
  129. data/lib/garcon/utility/uber/callable.rb +7 -0
  130. data/lib/garcon/utility/uber/delegates.rb +13 -0
  131. data/lib/garcon/utility/uber/inheritable_attr.rb +37 -0
  132. data/lib/garcon/utility/uber/options.rb +101 -0
  133. data/lib/garcon/utility/uber/uber_version.rb +3 -0
  134. data/lib/garcon/utility/uber/version.rb +33 -0
  135. data/lib/garcon/utility/url_helper.rb +100 -0
  136. data/lib/garcon/utils.rb +29 -0
  137. data/lib/garcon/version.rb +62 -0
  138. data/lib/garcun.rb +24 -0
  139. metadata +680 -0
@@ -0,0 +1,151 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Author: Stefano Harding <riddopic@gmail.com>
4
+ # License: Apache License, Version 2.0
5
+ # Copyright: (C) 2014-2015 Stefano Harding
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ module Garcon
21
+ # Define update methods that use direct paths
22
+ module AtomicDirectUpdate
23
+
24
+ # Pass the current value to the given block, replacing it with the block's
25
+ # result. May retry if the value changes during the block's execution.
26
+ #
27
+ # @yield [Object]
28
+ # Calculate a new value for the atomic reference using given (old) value.
29
+ # @yieldparam [Object] old_value
30
+ # The starting value of the atomic reference
31
+ #
32
+ # @return [Object]
33
+ # The new value
34
+ def update
35
+ true until compare_and_set(old_value = get, new_value = yield(old_value))
36
+ new_value
37
+ end
38
+
39
+ # Pass the current value to the given block, replacing it with the block's
40
+ # result. Raise an exception if the update fails.
41
+ #
42
+ # @yield [Object]
43
+ # Calculate a new value for the atomic reference using given (old) value.
44
+ # @yieldparam [Object] old_value
45
+ # The starting value of the atomic reference.
46
+ #
47
+ # @raise [Garcon::ConcurrentUpdateError]
48
+ # If the update fails
49
+ #
50
+ # @return [Object] the new value
51
+ def try_update
52
+ old_value = get
53
+ new_value = yield old_value
54
+ unless compare_and_set(old_value, new_value)
55
+ raise ConcurrentUpdateError, "Update failed"
56
+ end
57
+ new_value
58
+ end
59
+ end
60
+
61
+ # Special "compare and set" handling of numeric values.
62
+ module AtomicNumericCompareAndSetWrapper
63
+
64
+ def compare_and_set(old_value, new_value)
65
+ if old_value.kind_of? Numeric
66
+ while true
67
+ old = get
68
+
69
+ return false unless old.kind_of? Numeric
70
+
71
+ return false unless old == old_value
72
+
73
+ result = _compare_and_set(old, new_value)
74
+ return result if result
75
+ end
76
+ else
77
+ _compare_and_set(old_value, new_value)
78
+ end
79
+ end
80
+ alias_method :compare_and_swap, :compare_and_set
81
+ end
82
+
83
+ class AtomicMutex
84
+ include Garcon::AtomicDirectUpdate
85
+ include Garcon::AtomicNumericCompareAndSetWrapper
86
+
87
+ def initialize(value = nil)
88
+ @mutex = Mutex.new
89
+ @value = value
90
+ end
91
+
92
+ # Gets the current value.
93
+ #
94
+ # @return [Object]
95
+ # The current value.
96
+ def get
97
+ @mutex.synchronize { @value }
98
+ end
99
+ alias_method :value, :get
100
+
101
+ # Sets to the given value.
102
+ #
103
+ # @param [Object] value
104
+ # The new value to set.
105
+ #
106
+ # @return [Object]
107
+ # The new value.
108
+ def set(value)
109
+ @mutex.synchronize { @value = value }
110
+ end
111
+ alias_method :value=, :set
112
+
113
+ # Atomically sets to the given value and returns the old value.
114
+ #
115
+ # @param [Object] value
116
+ # The new value to set.
117
+ #
118
+ # @return [Object]
119
+ # The old value.
120
+ def get_and_set(new_value)
121
+ @mutex.synchronize do
122
+ old_value = @value
123
+ @value = new_value
124
+ old_value
125
+ end
126
+ end
127
+ alias_method :swap, :get_and_set
128
+
129
+ # Atomically sets the value to the given updated value if the current value
130
+ # is equal the expected value.
131
+ #
132
+ # @param [Object] old_value
133
+ # The expected value.
134
+ # @param [Object] new_value
135
+ # The new value.
136
+ #
137
+ # @return [Boolean]
138
+ # `true` if successful, `false` indicates that the actual value was not
139
+ # equal to the expected value.
140
+ def _compare_and_set(old_value, new_value)
141
+ return false unless @mutex.try_lock
142
+ begin
143
+ return false unless @value.equal? old_value
144
+ @value = new_value
145
+ ensure
146
+ @mutex.unlock
147
+ end
148
+ true
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,127 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Author: Stefano Harding <riddopic@gmail.com>
4
+ # License: Apache License, Version 2.0
5
+ # Copyright: (C) 2014-2015 Stefano Harding
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ module Garcon
21
+
22
+ # A boolean value that can be updated atomically. Reads and writes to an
23
+ # atomic boolean and thread-safe and guaranteed to succeed. Reads and writes
24
+ # may block briefly but no explicit locking is required.
25
+ #
26
+ class MutexAtomicBoolean
27
+
28
+ # Creates a new `AtomicBoolean` with the given initial value.
29
+ #
30
+ # @param [Boolean] initial
31
+ # the initial value
32
+ #
33
+ # @api public
34
+ def initialize(initial = false)
35
+ @value = !!initial
36
+ @mutex = Mutex.new
37
+ end
38
+
39
+ # Retrieves the current `Boolean` value.
40
+ #
41
+ # @return [Boolean]
42
+ # the current value
43
+ #
44
+ # @api public
45
+ def value
46
+ @mutex.lock
47
+ @value
48
+ ensure
49
+ @mutex.unlock
50
+ end
51
+
52
+ # Explicitly sets the value.
53
+ #
54
+ # @param [Boolean] value
55
+ # the new value to be set
56
+ #
57
+ # @return [Boolean]
58
+ # the current value
59
+ #
60
+ # @api public
61
+ def value=(value)
62
+ @mutex.lock
63
+ @value = !!value
64
+ @value
65
+ ensure
66
+ @mutex.unlock
67
+ end
68
+
69
+ # Is the current value `true`
70
+ #
71
+ # @return [Boolean]
72
+ # True if the current value is `true`, else false
73
+ #
74
+ # @api public
75
+ def true?
76
+ @mutex.lock
77
+ @value
78
+ ensure
79
+ @mutex.unlock
80
+ end
81
+
82
+ # Is the current value `false`
83
+ #
84
+ # @return [Boolean]
85
+ # True if the current value is `false`, else false
86
+ #
87
+ # @api public
88
+ def false?
89
+ @mutex.lock
90
+ !@value
91
+ ensure
92
+ @mutex.unlock
93
+ end
94
+
95
+ # Explicitly sets the value to true.
96
+ #
97
+ # @return [Boolean]
98
+ # True is value has changed, otherwise false
99
+ #
100
+ # @api public
101
+ def make_true
102
+ @mutex.lock
103
+ old = @value
104
+ @value = true
105
+ !old
106
+ ensure
107
+ @mutex.unlock
108
+ end
109
+
110
+ # Explicitly sets the value to false.
111
+ #
112
+ # @return [Boolean]
113
+ # True is value has changed, otherwise false
114
+ #
115
+ # @api public
116
+ def make_false
117
+ @mutex.lock
118
+ old = @value
119
+ @value = false
120
+ old
121
+ ensure
122
+ @mutex.unlock
123
+ end
124
+ end
125
+
126
+ class AtomicBoolean < MutexAtomicBoolean; end
127
+ end
@@ -0,0 +1,99 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Author: Stefano Harding <riddopic@gmail.com>
4
+ # License: Apache License, Version 2.0
5
+ # Copyright: (C) 2014-2015 Stefano Harding
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ require_relative 'monotonic_time'
21
+
22
+ module Garcon
23
+
24
+ # Condition is a better implementation of standard Ruby ConditionVariable. The
25
+ # biggest difference is the wait return value: Condition#wait returns
26
+ # Condition::Result which make possible to know if waiting thread has been
27
+ # woken up by an another thread (using #signal or #broadcast) or due to
28
+ # timeout.
29
+ #
30
+ # Every #wait must be guarded by a locked Mutex or a ThreadError will be
31
+ # risen. Although it's not mandatory, it's recommended to call also #signal
32
+ # and #broadcast within the same mutex
33
+ class Condition
34
+
35
+ class Result
36
+ def initialize(remaining_time)
37
+ @remaining_time = remaining_time
38
+ end
39
+
40
+ attr_reader :remaining_time
41
+
42
+ # @return [Boolean]
43
+ # Returns true if current thread has been waken up by a #signal or a
44
+ # #broadcast call, otherwise false.
45
+ def woken_up?
46
+ @remaining_time.nil? || @remaining_time > 0
47
+ end
48
+
49
+ # @return [Boolean]
50
+ # Returns true if current thread has been waken up due to a timeout,
51
+ # otherwise false.
52
+ def timed_out?
53
+ @remaining_time != nil && @remaining_time <= 0
54
+ end
55
+
56
+ alias_method :can_wait?, :woken_up?
57
+ end
58
+
59
+ def initialize
60
+ @condition = ConditionVariable.new
61
+ end
62
+
63
+ # @param [Mutex] mutex
64
+ # The locked mutex guarding the wait.
65
+ #
66
+ # @param [Object] timeout
67
+ # Nil means no timeout.
68
+ #
69
+ # @return [Result]
70
+ #
71
+ # @!macro monotonic_clock_warning
72
+ def wait(mutex, timeout = nil)
73
+ start_time = Garcon.monotonic_time
74
+ @condition.wait(mutex, timeout)
75
+
76
+ if timeout.nil?
77
+ Result.new(nil)
78
+ else
79
+ Result.new(start_time + timeout - Garcon.monotonic_time)
80
+ end
81
+ end
82
+
83
+ # Wakes up a waiting thread
84
+ #
85
+ # @return [true]
86
+ def signal
87
+ @condition.signal
88
+ true
89
+ end
90
+
91
+ # Wakes up all waiting threads
92
+ #
93
+ # @return [true]
94
+ def broadcast
95
+ @condition.broadcast
96
+ true
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,154 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Author: Stefano Harding <riddopic@gmail.com>
4
+ # License: Apache License, Version 2.0
5
+ # Copyright: (C) 2014-2015 Stefano Harding
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ module Garcon
21
+
22
+ # A thread safe observer set implemented using copy-on-read approach:
23
+ # observers are added and removed from a thread safe collection; every time
24
+ # a notification is required the internal data structure is copied to
25
+ # prevent concurrency issues
26
+ class CopyOnNotifyObserverSet
27
+
28
+ def initialize
29
+ @mutex = Mutex.new
30
+ @observers = {}
31
+ end
32
+
33
+ # Adds an observer to this set. If a block is passed, the observer will be
34
+ # created by this method and no other params should be passed
35
+ #
36
+ # @param [Object] observer
37
+ # The observer to add
38
+ #
39
+ # @param [Symbol] func
40
+ # The function to call on the observer during notification. The default
41
+ # is :update
42
+ #
43
+ # @return [Object]
44
+ # the added observer
45
+ def add_observer(observer = nil, func = :update, &block)
46
+ if observer.nil? && block.nil?
47
+ raise ArgumentError, 'should pass observer as a first argument or block'
48
+ elsif observer && block
49
+ raise ArgumentError.new('cannot provide both an observer and a block')
50
+ end
51
+
52
+ if block
53
+ observer = block
54
+ func = :call
55
+ end
56
+
57
+ begin
58
+ @mutex.lock
59
+ @observers[observer] = func
60
+ ensure
61
+ @mutex.unlock
62
+ end
63
+
64
+ observer
65
+ end
66
+
67
+ # @param [Object] observer
68
+ # the observer to remove
69
+ # @return [Object]
70
+ # the deleted observer
71
+ def delete_observer(observer)
72
+ @mutex.lock
73
+ @observers.delete(observer)
74
+ @mutex.unlock
75
+
76
+ observer
77
+ end
78
+
79
+ # Deletes all observers
80
+ # @return [CopyOnWriteObserverSet] self
81
+ def delete_observers
82
+ @mutex.lock
83
+ @observers.clear
84
+ @mutex.unlock
85
+
86
+ self
87
+ end
88
+
89
+ # @return [Integer]
90
+ # the observers count
91
+ def count_observers
92
+ @mutex.lock
93
+ result = @observers.count
94
+ @mutex.unlock
95
+
96
+ result
97
+ end
98
+
99
+ # Notifies all registered observers with optional args
100
+ #
101
+ # @param [Object] args
102
+ # arguments to be passed to each observer
103
+ #
104
+ # @return [CopyOnWriteObserverSet] self
105
+ def notify_observers(*args, &block)
106
+ observers = duplicate_observers
107
+ notify_to(observers, *args, &block)
108
+
109
+ self
110
+ end
111
+
112
+ # Notifies all registered observers with optional args and deletes them.
113
+ #
114
+ # @param [Object] args
115
+ # arguments to be passed to each observer
116
+ #
117
+ # @return [CopyOnWriteObserverSet] self
118
+ def notify_and_delete_observers(*args, &block)
119
+ observers = duplicate_and_clear_observers
120
+ notify_to(observers, *args, &block)
121
+
122
+ self
123
+ end
124
+
125
+ private # P R O P R I E T À P R I V A T A Vietato L'accesso
126
+
127
+ def duplicate_and_clear_observers
128
+ @mutex.lock
129
+ observers = @observers.dup
130
+ @observers.clear
131
+ @mutex.unlock
132
+
133
+ observers
134
+ end
135
+
136
+ def duplicate_observers
137
+ @mutex.lock
138
+ observers = @observers.dup
139
+ @mutex.unlock
140
+
141
+ observers
142
+ end
143
+
144
+ def notify_to(observers, *args)
145
+ if block_given? && !args.empty?
146
+ raise ArgumentError.new 'cannot give arguments and a block'
147
+ end
148
+ observers.each do |observer, function|
149
+ args = yield if block_given?
150
+ observer.send(function, *args)
151
+ end
152
+ end
153
+ end
154
+ end