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,107 @@
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 'thread'
21
+
22
+ require_relative 'ivar'
23
+ require_relative 'safe_task_executor'
24
+ require_relative 'executor_options'
25
+
26
+ module Garcon
27
+
28
+ class Future < IVar
29
+ include ExecutorOptions
30
+
31
+ # Create a new `Future` in the `:unscheduled` state.
32
+ #
33
+ # @yield the asynchronous operation to perform
34
+ #
35
+ # @!macro executor_and_deref_options
36
+ #
37
+ # @option opts [object, Array] :args
38
+ # Zero or more arguments to be passed the task block on execution.
39
+ #
40
+ # @raise [ArgumentError] if no block is given
41
+ #
42
+ def initialize(opts = {}, &block)
43
+ raise ArgumentError.new('no block given') unless block_given?
44
+ super(IVar::NO_VALUE, opts)
45
+ @state = :unscheduled
46
+ @task = block
47
+ @executor = get_executor_from(opts) || Garcon.global_io_executor
48
+ @args = get_arguments_from(opts)
49
+ end
50
+
51
+ # Execute an `:unscheduled` `Future`. Immediately sets the state to
52
+ # `:pending` and passes the block to a new thread/thread pool for eventual
53
+ # execution. Does nothing if the `Future` is in any state other than
54
+ # `:unscheduled`.
55
+ #
56
+ # @return [Future] a reference to `self`
57
+ #
58
+ # @example Instance and execute in separate steps
59
+ # future = Garcon::Future.new{ sleep(1); 42 }
60
+ # future.state #=> :unscheduled
61
+ # future.execute
62
+ # future.state #=> :pending
63
+ #
64
+ # @example Instance and execute in one line
65
+ # future = Garcon::Future.new{ sleep(1); 42 }.execute
66
+ # future.state #=> :pending
67
+ def execute
68
+ if compare_and_set_state(:pending, :unscheduled)
69
+ @executor.post(@args){ work }
70
+ self
71
+ end
72
+ end
73
+
74
+ # Create a new `Future` object with the given block, execute it, and return
75
+ # the `:pending` object.
76
+ #
77
+ # @example
78
+ # future = Garcon::Future.execute{ sleep(1); 42 }
79
+ # future.state #=> :pending
80
+ #
81
+ # @yield the asynchronous operation to perform.
82
+ #
83
+ # @!macro executor_and_deref_options.
84
+ #
85
+ # @option opts [object, Array] :args
86
+ # Zero or more arguments to be passed the task block on execution.
87
+ #
88
+ # @raise [ArgumentError] if no block is given.
89
+ #
90
+ # @return [Future]
91
+ # The newly created `Future` in the `:pending` state.
92
+ #
93
+ def self.execute(opts = {}, &block)
94
+ Future.new(opts, &block).execute
95
+ end
96
+
97
+ protected :set, :fail, :complete
98
+
99
+ private # P R O P R I E T À P R I V A T A Vietato L'accesso
100
+
101
+ # @!visibility private
102
+ def work
103
+ success, val, reason = SafeTaskExecutor.new(@task).execute(*@args)
104
+ complete(success, val, reason)
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,84 @@
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 'event'
21
+ require_relative 'executor'
22
+
23
+ module Garcon
24
+
25
+ # An executor service which runs all operations on the current thread,
26
+ # blocking as necessary. Operations are performed in the order they are
27
+ # received and no two operations can be performed simultaneously.
28
+ #
29
+ # This executor service exists mainly for testing an debugging. When used
30
+ # it immediately runs every `#post` operation on the current thread, blocking
31
+ # that thread until the operation is complete. This can be very beneficial
32
+ # during testing because it makes all operations deterministic.
33
+ #
34
+ # @note Intended for use primarily in testing and debugging.
35
+ class ImmediateExecutor
36
+ include SerialExecutor
37
+
38
+ # Creates a new executor
39
+ def initialize
40
+ @stopped = Garcon::Event.new
41
+ end
42
+
43
+ # @!macro executor_method_post
44
+ def post(*args, &task)
45
+ raise ArgumentError, 'no block given' unless block_given?
46
+ return false unless running?
47
+ task.call(*args)
48
+ true
49
+ end
50
+
51
+ # @!macro executor_method_left_shift
52
+ def <<(task)
53
+ post(&task)
54
+ self
55
+ end
56
+
57
+ # @!macro executor_method_running_question
58
+ def running?
59
+ ! shutdown?
60
+ end
61
+
62
+ # @!macro executor_method_shuttingdown_question
63
+ def shuttingdown?
64
+ false
65
+ end
66
+
67
+ # @!macro executor_method_shutdown_question
68
+ def shutdown?
69
+ @stopped.set?
70
+ end
71
+
72
+ # @!macro executor_method_shutdown
73
+ def shutdown
74
+ @stopped.set
75
+ true
76
+ end
77
+ alias_method :kill, :shutdown
78
+
79
+ # @!macro executor_method_wait_for_termination
80
+ def wait_for_termination(timeout = nil)
81
+ @stopped.wait(timeout)
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,171 @@
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 'thread'
21
+
22
+ require_relative '../exceptions'
23
+ require_relative 'obligation'
24
+ require_relative 'observable'
25
+
26
+ module Garcon
27
+
28
+ # An `IVar` is like a future that you can assign. As a future is a value that
29
+ # is being computed that you can wait on, an `IVar` is a value that is waiting
30
+ # to be assigned, that you can wait on. `IVars` are single assignment and
31
+ # deterministic.
32
+ #
33
+ # Then, express futures as an asynchronous computation that assigns an `IVar`.
34
+ # The `IVar` becomes the primitive on which [futures](Future) and
35
+ # [dataflow](Dataflow) are built.
36
+ #
37
+ # An `IVar` is a single-element container that is normally created empty, and
38
+ # can only be set once. The I in `IVar` stands for immutable. Reading an
39
+ # `IVar` normally blocks until it is set. It is safe to set and read an `IVar`
40
+ # from different threads.
41
+ #
42
+ # If you want to have some parallel task set the value in an `IVar`, you want
43
+ # a `Future`. If you want to create a graph of parallel tasks all executed
44
+ # when the values they depend on are ready you want `dataflow`. `IVar` is
45
+ # generally a low-level primitive.
46
+ #
47
+ # @example Create, set and get an `IVar`
48
+ # ivar = Garcon::IVar.new
49
+ # ivar.set 14
50
+ # ivar.get #=> 14
51
+ # ivar.set 2 # would now be an error
52
+ #
53
+ class IVar
54
+ include Obligation
55
+ include Observable
56
+
57
+ # @!visibility private
58
+ NO_VALUE = Object.new
59
+
60
+ # Create a new `IVar` in the `:pending` state with the (optional) initial
61
+ # value.
62
+ #
63
+ # @param [Object] value
64
+ # The initial value.
65
+ #
66
+ # @param [Hash] opts the options to create a message with.
67
+ #
68
+ # @option opts [String] :dup_on_deref (false)
69
+ # Call `#dup` before returning the data.
70
+ #
71
+ # @option opts [String] :freeze_on_deref (false)
72
+ # Call `#freeze` before returning the data.
73
+ #
74
+ # @option opts [String] :copy_on_deref (nil)
75
+ # Cll the given `Proc` passing the internal value and returning the value
76
+ # returned from the proc.
77
+ #
78
+ def initialize(value = NO_VALUE, opts = {})
79
+ init_obligation
80
+ self.observers = CopyOnWriteObserverSet.new
81
+ set_deref_options(opts)
82
+
83
+ if value == NO_VALUE
84
+ @state = :pending
85
+ else
86
+ set(value)
87
+ end
88
+ end
89
+
90
+ # Add an observer on this object that will receive notification on update.
91
+ #
92
+ # Upon completion the `IVar` will notify all observers in a thread-safe way.
93
+ # The `func` method of the observer will be called with three arguments: the
94
+ # `Time` at which the `Future` completed the asynchronous operation, the
95
+ # final `value` (or `nil` on rejection), and the final `reason` (or `nil` on
96
+ # fulfillment).
97
+ #
98
+ # @param [Object] observer
99
+ # The object that will be notified of changes.
100
+ #
101
+ # @param [Symbol] func
102
+ # Symbol naming the method to call when the `Observable` has changes`
103
+ #
104
+ def add_observer(bsrver = nil, func = :update, &block)
105
+ if observer && block
106
+ raise ArgumentError, 'cannot provide both an observer and a block'
107
+ end
108
+ direct_notification = false
109
+
110
+ if block
111
+ observer = block
112
+ func = :call
113
+ end
114
+
115
+ mutex.synchronize do
116
+ if event.set?
117
+ direct_notification = true
118
+ else
119
+ observers.add_observer(observer, func)
120
+ end
121
+ end
122
+
123
+ observer.send(func, Time.now, self.value, reason) if direct_notification
124
+ observer
125
+ end
126
+
127
+ # Set the `IVar` to a value and wake or notify all threads waiting on it.
128
+ #
129
+ # @param [Object] value
130
+ # The value to store in the `IVar`.
131
+ #
132
+ # @raise [Garcon::MultipleAssignmentError]
133
+ # If the `IVar` has already been set or otherwise completed.
134
+ #
135
+ # @return [IVar] self
136
+ #
137
+ def set(value)
138
+ complete(true, value, nil)
139
+ end
140
+
141
+ # Set the `IVar` to failed due to some error and wake or notify all threads
142
+ # waiting on it.
143
+ #
144
+ # @param [Object] reason
145
+ # For the failure.
146
+ #
147
+ # @raise [Garcon::MultipleAssignmentError]
148
+ # If the `IVar` has already been set or otherwise completed.
149
+ #
150
+ # @return [IVar] self
151
+ #
152
+ def fail(reason = StandardError.new)
153
+ complete(false, nil, reason)
154
+ end
155
+
156
+ # @!visibility private
157
+ def complete(success, value, reason)
158
+ mutex.synchronize do
159
+ if [:fulfilled, :rejected].include? @state
160
+ raise MultipleAssignmentError, 'multiple assignment'
161
+ end
162
+ set_state(success, value, reason)
163
+ event.set
164
+ end
165
+
166
+ time = Time.now
167
+ observers.notify_and_delete_observers{ [time, self.value, reason] }
168
+ self
169
+ end
170
+ end
171
+ end
@@ -0,0 +1,74 @@
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
+ # Lazy evaluation of a block yielding an immutable result. Useful for
23
+ # expensive operations that may never be needed. `LazyReference` is a simpler,
24
+ # blocking version of `Delay` and has an API similar to `AtomicReference`.
25
+ # The first time `#value` is called the caller will block until the
26
+ # block given at construction is executed. Once the result has been
27
+ # computed the value will be immutably set. Any exceptions thrown during
28
+ # computation will be suppressed.
29
+ #
30
+ class LazyReference
31
+
32
+ # Creates a new unfulfilled object.
33
+ #
34
+ # @yield the delayed operation to perform
35
+ #
36
+ # @param [Object] default
37
+ # The default value for the object when the block raises an exception.
38
+ #
39
+ # @raise [ArgumentError] if no block is given
40
+ #
41
+ def initialize(default = nil, &block)
42
+ raise ArgumentError, 'no block given' unless block_given?
43
+ @default = default
44
+ @task = block
45
+ @mutex = Mutex.new
46
+ @value = nil
47
+ @fulfilled = false
48
+ end
49
+
50
+ # The calculated value of the object or the default value if one was given
51
+ # at construction. This first time this method is called it will block
52
+ # indefinitely while the block is processed. Subsequent calls will not
53
+ # block.
54
+ #
55
+ # @return [Object] the calculated value
56
+ #
57
+ def value
58
+ return @value if @fulfilled
59
+
60
+ @mutex.synchronize do
61
+ unless @fulfilled
62
+ begin
63
+ @value = @task.call
64
+ rescue
65
+ @value = @default
66
+ ensure
67
+ @fulfilled = true
68
+ end
69
+ end
70
+ return @value
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,69 @@
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
+ # Clock that cannot be set and represents monotonic time since
23
+ # some unspecified starting point.
24
+ # @!visibility private
25
+ GLOBAL_MONOTONIC_CLOCK = Class.new {
26
+
27
+ if defined?(Process::CLOCK_MONOTONIC)
28
+ # @!visibility private
29
+ def get_time
30
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
31
+ end
32
+ else
33
+
34
+ require 'thread'
35
+
36
+ # @!visibility private
37
+ def initialize
38
+ @mutex = Mutex.new
39
+ @last_time = Time.now.to_f
40
+ end
41
+
42
+ # @!visibility private
43
+ def get_time
44
+ @mutex.synchronize do
45
+ now = Time.now.to_f
46
+ if @last_time < now
47
+ @last_time = now
48
+ else # clock has moved back in time
49
+ @last_time += 0.000_001
50
+ end
51
+ end
52
+ end
53
+ end
54
+ }.new
55
+ private_constant :GLOBAL_MONOTONIC_CLOCK
56
+
57
+ # @!macro [attach] monotonic_get_time
58
+ #
59
+ # Returns the current time a tracked by the application monotonic clock.
60
+ #
61
+ # @return [Float] The current monotonic time when `since` not given else
62
+ # the elapsed monotonic time between `since` and the current time
63
+ #
64
+ # @!macro monotonic_clock_warning
65
+ def monotonic_time
66
+ GLOBAL_MONOTONIC_CLOCK.get_time
67
+ end
68
+ module_function :monotonic_time
69
+ end