concurrent-ruby-edge 0.1.0.pre3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b3b0a6f42dd53529fb35370f6d9d6b1957aa576c
4
- data.tar.gz: b960e25b2834254aaa00685cf38e41fc3a481e9f
3
+ metadata.gz: 3d078f232b2a8d30df70a0d008daeaee93884f58
4
+ data.tar.gz: 767e96651e435eb373a2751fb11bd45fc336ab51
5
5
  SHA512:
6
- metadata.gz: aec6112c612dbfa9f709181cef273ba892ae5db92915875e7750d18e159c821e613f5c02520530eb27805e60531e55e68021ac003279a94b8d78b63ef184948e
7
- data.tar.gz: bb59836fc4e5da39fc2c3f7885d1a123f0a9100850c9c486871830d9421c5b2e0756f45e9f7c7dee7f538adfd030f765b3a54fa33fd94726c13e05b8d08b4977
6
+ metadata.gz: 231af4d7c79ca4bba8ec44d262b893a62a1a935bf6345a55dae736e55dc524e1939c8ee869b6c6c1f727e8f42a8134f71392f6dcac2056e717975db991b9a58a
7
+ data.tar.gz: 5f1df67b0ba95a112067cbf69dfd3301c26e44430d97c6f7120ee30efad6a2261d7c52decdfa70c572ac567e7710f355c194b148b6f7944ea3d07a313ecbd5f1
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # Concurrent Ruby
2
- [![Gem Version](https://badge.fury.io/rb/concurrent-ruby.svg)](http://badge.fury.io/rb/concurrent-ruby) [![Build Status](https://travis-ci.org/ruby-concurrency/concurrent-ruby.svg?branch=master)](https://travis-ci.org/ruby-concurrency/concurrent-ruby) [![Code Climate](https://codeclimate.com/github/ruby-concurrency/concurrent-ruby.svg)](https://codeclimate.com/github/ruby-concurrency/concurrent-ruby) [![Inline docs](http://inch-ci.org/github/ruby-concurrency/concurrent-ruby.svg)](http://inch-ci.org/github/ruby-concurrency/concurrent-ruby) [![Dependency Status](https://gemnasium.com/ruby-concurrency/concurrent-ruby.svg)](https://gemnasium.com/ruby-concurrency/concurrent-ruby) [![License](https://img.shields.io/badge/license-MIT-green.svg)](http://opensource.org/licenses/MIT) [![Gitter chat](http://img.shields.io/badge/gitter-join%20chat%20%E2%86%92-brightgreen.svg)](https://gitter.im/ruby-concurrency/concurrent-ruby)
2
+ [![Gem Version](https://badge.fury.io/rb/concurrent-ruby.svg)](http://badge.fury.io/rb/concurrent-ruby) [![Build Status](https://travis-ci.org/ruby-concurrency/concurrent-ruby.svg?branch=master)](https://travis-ci.org/ruby-concurrency/concurrent-ruby) [![Build status](https://ci.appveyor.com/api/projects/status/iq8aboyuu3etad4w?svg=true)](https://ci.appveyor.com/project/rubyconcurrency/concurrent-ruby) [![Code Climate](https://codeclimate.com/github/ruby-concurrency/concurrent-ruby.svg)](https://codeclimate.com/github/ruby-concurrency/concurrent-ruby) [![Inline docs](http://inch-ci.org/github/ruby-concurrency/concurrent-ruby.svg)](http://inch-ci.org/github/ruby-concurrency/concurrent-ruby) [![Dependency Status](https://gemnasium.com/ruby-concurrency/concurrent-ruby.svg)](https://gemnasium.com/ruby-concurrency/concurrent-ruby) [![License](https://img.shields.io/badge/license-MIT-green.svg)](http://opensource.org/licenses/MIT) [![Gitter chat](http://img.shields.io/badge/gitter-join%20chat%20%E2%86%92-brightgreen.svg)](https://gitter.im/ruby-concurrency/concurrent-ruby)
3
3
 
4
4
  <table>
5
5
  <tr>
@@ -39,6 +39,7 @@
39
39
 
40
40
  MRI 1.9.3, 2.0, 2.1, 2.2, JRuby (1.9 mode), and Rubinius 2.x are supported.
41
41
  This gem should be fully compatible with any interpreter that is compliant with Ruby 1.9.3 or newer.
42
+ Java 8 is required for JRuby (Java 7 support is deprecated in version 0.9 and will be removed in 1.0).
42
43
 
43
44
  ## Features & Documentation
44
45
 
@@ -127,14 +128,14 @@ be obeyed though. Features developed in `concurrent-ruby-edge` are expected to m
127
128
 
128
129
  #### Statuses:
129
130
 
130
- *Why is not in core?*
131
+ *Why are these not in core?*
131
132
 
132
- - **Actor** - partial documentation and tests, stability good.
133
- - **Future/Promise Framework** - partial documentation and tests, stability good.
134
- - **Agent** - incomplete behaviour compared to Clojure's model, stability good.
135
- - **Channel** - missing documentation, stability good.
136
- - **Exchanger** - known race issue.
137
- - **LazyRegister** - missing documentation and tests.
133
+ - **Actor** - Partial documentation and tests; stability is good.
134
+ - **Future/Promise Framework** - API changes; partial documentation and tests; stability good.
135
+ - **Agent** - Incomplete behaviour compared to Clojure's models; stability good.
136
+ - **Channel** - Missing documentation; limted features; stability good.
137
+ - **Exchanger** - Known race condition requiring a new implementation.
138
+ - **LazyRegister** - Missing documentation and tests.
138
139
 
139
140
  ## Usage
140
141
 
@@ -248,10 +249,16 @@ bundle exec rake build # Build JRuby-specific core gem (alias for `
248
249
  bundle exec rake build:core # Build concurrent-ruby-<version>-java.gem into the pkg directory
249
250
 
250
251
  *All except JRuby*
251
- bundle exec rake build # Build core and extension gems
252
252
  bundle exec rake build:core # Build concurrent-ruby-<version>.gem into the pkg directory
253
253
  bundle exec rake build:ext # Build concurrent-ruby-ext-<version>.gem into the pkg directory
254
254
 
255
+ *When Docker IS installed*
256
+ bundle exec rake build:windows # Build the windows binary <version> gems per rake-compiler-dock
257
+ bundle exec rake build # Build core, extension, and edge gems, including Windows binaries
258
+
259
+ *When Docker is NOT installed*
260
+ bundle exec rake build # Build core, extension, and edge gems (excluding Windows binaries)
261
+
255
262
  *All*
256
263
  bundle exec rake clean # Remove any temporary products
257
264
  bundle exec rake clobber # Remove any generated file
@@ -260,7 +267,7 @@ bundle exec rake compile # Compile all the extensions
260
267
 
261
268
  ## Maintainers
262
269
 
263
- * [Jerry D'Antonio](https://github.com/jdantonio)
270
+ * [Jerry D'Antonio](https://github.com/jdantonio) (creator)
264
271
  * [Michele Della Torre](https://github.com/mighe)
265
272
  * [Chris Seaton](https://github.com/chrisseaton)
266
273
  * [Lucas Allan](https://github.com/lucasallan)
@@ -9,3 +9,4 @@ require 'concurrent/lazy_register'
9
9
  require 'concurrent/edge/future'
10
10
  require 'concurrent/edge/lock_free_stack'
11
11
  require 'concurrent/edge/atomic_markable_reference'
12
+ require 'concurrent/edge/lock_free_linked_set'
@@ -37,10 +37,6 @@ module Concurrent
37
37
  #
38
38
  # > {include:Actor::Behaviour::Termination}
39
39
  #
40
- # - {Behaviour::TerminatesChildren}:
41
- #
42
- # > {include:Actor::Behaviour::TerminatesChildren}
43
- #
44
40
  # - {Behaviour::RemovesChild}:
45
41
  #
46
42
  # > {include:Actor::Behaviour::RemovesChild}
@@ -66,14 +62,12 @@ module Concurrent
66
62
  require 'concurrent/actor/behaviour/sets_results'
67
63
  require 'concurrent/actor/behaviour/supervising'
68
64
  require 'concurrent/actor/behaviour/termination'
69
- require 'concurrent/actor/behaviour/terminates_children'
70
65
 
71
66
  # Array of behaviours and their construction parameters.
72
67
  #
73
68
  # [[Behaviour::SetResults, :terminate!],
74
69
  # [Behaviour::RemovesChild],
75
70
  # [Behaviour::Termination],
76
- # [Behaviour::TerminatesChildren],
77
71
  # [Behaviour::Linking],
78
72
  # [Behaviour::Awaits],
79
73
  # [Behaviour::ExecutesContext],
@@ -91,7 +85,6 @@ module Concurrent
91
85
  # [[Behaviour::SetResults, :pause!],
92
86
  # [Behaviour::RemovesChild],
93
87
  # [Behaviour::Termination],
94
- # [Behaviour::TerminatesChildren],
95
88
  # [Behaviour::Linking],
96
89
  # [Behaviour::Pausing],
97
90
  # [Behaviour::Supervising, :reset!, :one_for_one],
@@ -113,8 +106,7 @@ module Concurrent
113
106
  [[SetResults, on_error],
114
107
  # has to be before Termination to be able to remove children from terminated actor
115
108
  RemovesChild,
116
- Termination,
117
- TerminatesChildren]
109
+ Termination]
118
110
  end
119
111
 
120
112
  # @see '' its source code
@@ -2,22 +2,22 @@ module Concurrent
2
2
  module Actor
3
3
  module Behaviour
4
4
 
5
- # Handles actor termination.
5
+ # Handles actor termination. Waits until all its children are terminated,
6
+ # can be configured on behaviour initialization.
6
7
  # @note Actor rejects envelopes when terminated.
7
8
  # @note TODO missing example
8
9
  class Termination < Abstract
9
10
 
10
11
  # @!attribute [r] terminated
11
12
  # @return [Edge::Event] event which will become set when actor is terminated.
12
- # @!attribute [r] reason
13
- attr_reader :terminated, :reason
13
+ attr_reader :terminated
14
14
 
15
- def initialize(core, subsequent, core_options, trapping = false)
15
+ def initialize(core, subsequent, core_options, trapping = false, terminate_children = true)
16
16
  super core, subsequent, core_options
17
- @terminated = Concurrent.event
18
- @public_terminated = @terminated.hide_completable
19
- @reason = nil
20
- @trapping = trapping
17
+ @terminated = Concurrent.future
18
+ @public_terminated = @terminated.hide_completable
19
+ @trapping = trapping
20
+ @terminate_children = terminate_children
21
21
  end
22
22
 
23
23
  # @note Actor rejects envelopes when terminated.
@@ -43,7 +43,7 @@ module Concurrent
43
43
  if trapping? && reason != :kill
44
44
  pass envelope
45
45
  else
46
- terminate! reason
46
+ terminate! reason, envelope
47
47
  end
48
48
  when :termination_event
49
49
  @public_terminated
@@ -59,14 +59,23 @@ module Concurrent
59
59
 
60
60
  # Terminates the actor. Any Envelope received after termination is rejected.
61
61
  # Terminates all its children, does not wait until they are terminated.
62
- def terminate!(reason = :normal)
63
- # TODO return after all children are terminated
62
+ def terminate!(reason = nil, envelope = nil)
64
63
  return true if terminated?
65
- @reason = reason
66
- terminated.complete
64
+
65
+ self_termination = Concurrent.completed_future(reason.nil?, reason.nil? || nil, reason)
66
+ all_terminations = if @terminate_children
67
+ Concurrent.zip(*children.map { |ch| ch.ask(:terminate!) }, self_termination)
68
+ else
69
+ self_termination
70
+ end
71
+
72
+ all_terminations.chain_completable(@terminated)
73
+ all_terminations.chain_completable(envelope.future) if envelope && envelope.future
74
+
67
75
  broadcast(true, [:terminated, reason]) # TODO do not end up in Dead Letter Router
68
76
  parent << :remove_child if parent
69
- true
77
+
78
+ MESSAGE_PROCESSED
70
79
  end
71
80
  end
72
81
  end
@@ -18,10 +18,10 @@ module Concurrent
18
18
  behaviour!(Behaviour::Termination).terminated?
19
19
  end
20
20
 
21
- # @see Termination#reason
22
- def reason
23
- behaviour!(Behaviour::Termination).reason
24
- end
21
+ # # @see Termination#reason
22
+ # def reason
23
+ # behaviour!(Behaviour::Termination).reason
24
+ # end
25
25
 
26
26
  # delegates to core.log
27
27
  # @see Logging#log
@@ -18,7 +18,6 @@ module Concurrent
18
18
  # # this block has to return proc defining #on_message behaviour
19
19
  # -> message { where.tell message }
20
20
  # end
21
- # @note TODO remove in favor of the module
22
21
  class AdHoc < Context
23
22
  include AsAdHoc
24
23
  end
@@ -39,9 +39,19 @@ module Concurrent
39
39
  end
40
40
  end
41
41
 
42
- # @return [Future] which is already completed with value
43
- def completed_future(value, default_executor = :io)
44
- ImmediateFuturePromise.new(default_executor, value).future
42
+ # @return [Future] which is already completed
43
+ def completed_future(success, value, reason, default_executor = :io)
44
+ ImmediateFuturePromise.new(default_executor, success, value, reason).future
45
+ end
46
+
47
+ # @return [Future] which is already completed in success state with value
48
+ def succeeded_future(value, default_executor = :io)
49
+ completed_future true, value, nil, default_executor
50
+ end
51
+
52
+ # @return [Future] which is already completed in failed state with reason
53
+ def failed_future(reason, default_executor = :io)
54
+ completed_future false, nil, reason, default_executor
45
55
  end
46
56
 
47
57
  # @return [Event] which is already completed
@@ -678,10 +688,10 @@ module Concurrent
678
688
 
679
689
  alias_method :|, :any
680
690
 
681
- # only proof of concept
682
691
  # @note may block
692
+ # @note only proof of concept
683
693
  def then_push(channel)
684
- on_success { |value| channel.push value }
694
+ on_success(:io) { |value| channel.push value }
685
695
  end
686
696
 
687
697
  # @yield [value] executed async on `executor` when success
@@ -1057,7 +1067,7 @@ module Concurrent
1057
1067
  evaluate_to lambda { done_future.apply task }
1058
1068
  end
1059
1069
  else
1060
- complete_with Future::Failed.new(done_future.reason)
1070
+ complete_with done_future.internal_state
1061
1071
  end
1062
1072
  end
1063
1073
  end
@@ -1104,8 +1114,9 @@ module Concurrent
1104
1114
 
1105
1115
  # @!visibility private
1106
1116
  class ImmediateFuturePromise < InnerPromise
1107
- def initialize(default_executor, value)
1108
- super Future.new(self, default_executor).complete_with(Future::Success.new(value))
1117
+ def initialize(default_executor, success, value, reason)
1118
+ super Future.new(self, default_executor).
1119
+ complete_with(success ? Future::Success.new(value) : Future::Failed.new(reason))
1109
1120
  end
1110
1121
  end
1111
1122
 
@@ -1360,7 +1371,7 @@ module Concurrent
1360
1371
  end
1361
1372
  end
1362
1373
 
1363
- # proof of concept
1374
+ # @note proof of concept
1364
1375
  class Channel < Synchronization::Object
1365
1376
  # TODO make lock free
1366
1377
  def initialize
@@ -0,0 +1,146 @@
1
+ require 'concurrent/edge/lock_free_linked_set/node'
2
+ require 'concurrent/edge/lock_free_linked_set/window'
3
+
4
+ module Concurrent
5
+ module Edge
6
+ # This class implements a lock-free linked set. The general idea of this
7
+ # implementation is this: each node has a successor which is an Atomic
8
+ # Markable Reference. This is used to ensure that all modifications to the
9
+ # list are atomic, preserving the structure of the linked list under _any_
10
+ # circumstance in a multithreaded application.
11
+ #
12
+ # One interesting aspect of this algorithm occurs with removing a node.
13
+ # Instead of physically removing a node when remove is called, a node is
14
+ # logically removed, by 'marking it.' By doing this, we prevent calls to
15
+ # `remove` from traversing the list twice to perform a physical removal.
16
+ # Instead, we have have calls to `add` and `remove` clean up all marked
17
+ # nodes they encounter while traversing the list.
18
+ #
19
+ # This algorithm is a variation of the Nonblocking Linked Set found in
20
+ # 'The Art of Multiprocessor Programming' by Herlihy and Shavit.
21
+ class LockFreeLinkedSet
22
+ include Enumerable
23
+
24
+ # @!macro [attach] lock_free_linked_list_method_initialize
25
+ #
26
+ # @param [Fixnum] initial_size the size of the linked_list to initialize
27
+ def initialize(initial_size = 0, val = nil)
28
+ @head = Head.new
29
+
30
+ initial_size.times do
31
+ val = block_given? ? yield : val
32
+ add val
33
+ end
34
+ end
35
+
36
+ # @!macro [attach] lock_free_linked_list_method_add
37
+ #
38
+ # Atomically adds the item to the set if it does not yet exist. Note:
39
+ # internally the set uses `Object#hash` to compare equality of items,
40
+ # meaning that Strings and other objects will be considered equal
41
+ # despite being different objects.
42
+ #
43
+ # @param [Object] item the item you wish to insert
44
+ #
45
+ # @return [Boolean] `true` if successful. A `false` return indicates
46
+ # that the item was already in the set.
47
+ def add(item)
48
+ loop do
49
+ window = Window.find @head, item
50
+
51
+ pred, curr = window.pred, window.curr
52
+
53
+ # Item already in set
54
+ return false if curr == item
55
+
56
+ node = Node.new item, curr
57
+
58
+ if pred.Successor_reference.compare_and_set curr, node, false, false
59
+ return true
60
+ end
61
+ end
62
+ end
63
+
64
+ # @!macro [attach] lock_free_linked_list_method_<<
65
+ #
66
+ # Atomically adds the item to the set if it does not yet exist.
67
+ #
68
+ # @param [Object] item the item you wish to insert
69
+ #
70
+ # @return [Oject] the set on which the :<< method was invoked
71
+ def <<(item)
72
+ add item
73
+ self
74
+ end
75
+
76
+ # @!macro [attach] lock_free_linked_list_method_contains
77
+ #
78
+ # Atomically checks to see if the set contains an item. This method
79
+ # compares equality based on the `Object#hash` method, meaning that the
80
+ # hashed contents of an object is what determines equality instead of
81
+ # `Object#object_id`
82
+ #
83
+ # @param [Object] item the item you to check for presence in the set
84
+ #
85
+ # @return [Boolean] whether or not the item is in the set
86
+ def contains?(item)
87
+ curr = @head
88
+
89
+ while curr < item
90
+ curr = curr.next_node
91
+ marked = curr.Successor_reference.marked?
92
+ end
93
+
94
+ curr == item && !marked
95
+ end
96
+
97
+ # @!macro [attach] lock_free_linked_list_method_remove
98
+ #
99
+ # Atomically attempts to remove an item, comparing using `Object#hash`.
100
+ #
101
+ # @param [Object] item the item you to remove from the set
102
+ #
103
+ # @return [Boolean] whether or not the item was removed from the set
104
+ def remove(item)
105
+ loop do
106
+ window = Window.find @head, item
107
+ pred, curr = window.pred, window.curr
108
+
109
+ return false if curr != item
110
+
111
+ succ = curr.next_node
112
+ removed = curr.Successor_reference.compare_and_set succ, succ, false, true
113
+
114
+ next_node unless removed
115
+
116
+ pred.Successor_reference.compare_and_set curr, succ, false, false
117
+
118
+ return true
119
+ end
120
+ end
121
+
122
+ # @!macro [attach] lock_free_linked_list_method_each
123
+ #
124
+ # An iterator to loop through the set.
125
+ #
126
+ # @param [Object] item the item you to remove from the set
127
+ # @yeild [Object] each item in the set
128
+ #
129
+ # @return [Object] self: the linked set on which each was called
130
+ def each
131
+ return to_enum unless block_given?
132
+
133
+ curr = @head
134
+
135
+ until curr.last?
136
+ curr = curr.next_node
137
+ marked = curr.Successor_reference.marked?
138
+
139
+ yield curr.Data unless marked
140
+ end
141
+
142
+ self
143
+ end
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,72 @@
1
+ require 'concurrent/edge/atomic_markable_reference'
2
+
3
+ module Concurrent
4
+ module Edge
5
+ class LockFreeLinkedSet
6
+ class Node < Synchronization::Object
7
+ include Comparable
8
+
9
+ attr_reader :Data, :Successor_reference, :Key
10
+
11
+ def initialize(data = nil, successor = nil)
12
+ super()
13
+
14
+ @Successor_reference = AtomicMarkableReference.new(successor || Tail.new)
15
+ @Data = data
16
+ @Key = key_for data
17
+
18
+ ensure_ivar_visibility!
19
+ end
20
+
21
+ # Check to see if the node is the last in the list.
22
+ def last?
23
+ @Successor_reference.value.is_a? Tail
24
+ end
25
+
26
+ # Next node in the list. Note: this is not the AtomicMarkableReference
27
+ # of the next node, this is the actual Node itself.
28
+ def next_node
29
+ @Successor_reference.value
30
+ end
31
+
32
+ # This method provides a unqiue key for the data which will be used for
33
+ # ordering. This is configurable, and changes depending on how you wish
34
+ # the nodes to be ordered.
35
+ def key_for(data)
36
+ data.hash
37
+ end
38
+
39
+ # We use `Object#hash` as a way to enforce ordering on the nodes. This
40
+ # can be configurable in the future; for example, you could enforce a
41
+ # split-ordering on the nodes in the set.
42
+ def <=>(other)
43
+ @Key <=> other.hash
44
+ end
45
+ end
46
+
47
+ # Internal sentinel node for the Tail. It is always greater than all
48
+ # other nodes, and it is self-referential; meaning its successor is
49
+ # a self-loop.
50
+ class Tail < Node
51
+ def initialize(_data = nil, _succ = nil)
52
+ @Successor_reference = AtomicMarkableReference.new self
53
+ end
54
+
55
+ # Always greater than other nodes. This means that traversal will end
56
+ # at the tail node since we are comparing node size in the traversal.
57
+ def <=>(_other)
58
+ 1
59
+ end
60
+ end
61
+
62
+
63
+ # Internal sentinel node for the Head of the set. Head is always smaller
64
+ # than any other node.
65
+ class Head < Node
66
+ def <=>(_other)
67
+ -1
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,49 @@
1
+ module Concurrent
2
+ module Edge
3
+ class LockFreeLinkedSet
4
+ class Window
5
+ attr_accessor :pred, :curr
6
+
7
+ def initialize(pred, curr)
8
+ @pred, @curr = pred, curr
9
+ end
10
+
11
+ # This method is used to find a 'window' for which `add` and `remove`
12
+ # methods can use to know where to add and remove from the list. However,
13
+ # it has another responsibilility, which is to physically unlink any
14
+ # nodes marked for removal in the set. This prevents adds/removes from
15
+ # having to retraverse the list to physically unlink nodes.
16
+ def self.find(head, item)
17
+ loop do
18
+ break_inner_loops = false
19
+ pred = head
20
+ curr = pred.next_node
21
+
22
+ loop do
23
+ succ, marked = curr.Successor_reference.get
24
+
25
+ # Remove sequence of marked nodes
26
+ while marked
27
+ removed = pred.Successor_reference.compare_and_set curr, succ, false, false
28
+
29
+ # If could not remove node, try again
30
+ break_inner_loops = true && break unless removed
31
+
32
+ curr = succ
33
+ succ, marked = curr.Successor_reference.get
34
+ end
35
+
36
+ break if break_inner_loops
37
+
38
+ # We have found a window
39
+ return new pred, curr if curr >= item
40
+
41
+ pred = curr
42
+ curr = succ
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: concurrent-ruby-edge
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.pre3
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jerry D'Antonio
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2015-06-22 00:00:00.000000000 Z
13
+ date: 2015-07-10 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: concurrent-ruby
@@ -18,14 +18,14 @@ dependencies:
18
18
  requirements:
19
19
  - - "~>"
20
20
  - !ruby/object:Gem::Version
21
- version: 0.9.0.pre3
21
+ version: 0.9.0
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
26
  - - "~>"
27
27
  - !ruby/object:Gem::Version
28
- version: 0.9.0.pre3
28
+ version: 0.9.0
29
29
  description: |
30
30
  These features are under active development and may change frequently. They are expected not to
31
31
  keep backward compatibility (there may also lack tests and documentation). Semantic versions will
@@ -55,7 +55,6 @@ files:
55
55
  - lib/concurrent/actor/behaviour/removes_child.rb
56
56
  - lib/concurrent/actor/behaviour/sets_results.rb
57
57
  - lib/concurrent/actor/behaviour/supervising.rb
58
- - lib/concurrent/actor/behaviour/terminates_children.rb
59
58
  - lib/concurrent/actor/behaviour/termination.rb
60
59
  - lib/concurrent/actor/context.rb
61
60
  - lib/concurrent/actor/core.rb
@@ -82,6 +81,9 @@ files:
82
81
  - lib/concurrent/channel/waitable_list.rb
83
82
  - lib/concurrent/edge/atomic_markable_reference.rb
84
83
  - lib/concurrent/edge/future.rb
84
+ - lib/concurrent/edge/lock_free_linked_set.rb
85
+ - lib/concurrent/edge/lock_free_linked_set/node.rb
86
+ - lib/concurrent/edge/lock_free_linked_set/window.rb
85
87
  - lib/concurrent/edge/lock_free_stack.rb
86
88
  homepage: http://www.concurrent-ruby.com
87
89
  licenses:
@@ -98,9 +100,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
98
100
  version: 1.9.3
99
101
  required_rubygems_version: !ruby/object:Gem::Requirement
100
102
  requirements:
101
- - - ">"
103
+ - - ">="
102
104
  - !ruby/object:Gem::Version
103
- version: 1.3.1
105
+ version: '0'
104
106
  requirements: []
105
107
  rubyforge_project:
106
108
  rubygems_version: 2.4.8
@@ -1,14 +0,0 @@
1
- module Concurrent
2
- module Actor
3
- module Behaviour
4
- # Terminates all children when the actor terminates.
5
- class TerminatesChildren < Abstract
6
- def on_event(public, event)
7
- event_name, _ = event
8
- children.map { |ch| ch << :terminate! } if event_name == :terminated
9
- super public, event
10
- end
11
- end
12
- end
13
- end
14
- end