farce 0.1.0-java → 0.2.0-java
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +80 -1
- data/README.md +72 -16
- data/docs/gems/dry-types.md +8 -8
- data/docs/modes.md +67 -10
- data/lib/farce/_yard/macros.rb +18 -3
- data/lib/farce/abstract/flag.rb +73 -0
- data/lib/farce/abstract/queue.rb +4 -3
- data/lib/farce/abstract/scheduler.rb +3 -3
- data/lib/farce/abstract/set.rb +17 -5
- data/lib/farce/abstract/sorted_set.rb +2 -2
- data/lib/farce/abstract/timer_queue.rb +49 -10
- data/lib/farce/abstract/vector.rb +510 -28
- data/lib/farce/atom.rb +1 -1
- data/lib/farce/class_mirror.rb +20 -7
- data/lib/farce/config.rb +7 -1
- data/lib/farce/engine/jvm/flag.rb +15 -3
- data/lib/farce/engine/ruby/shared/require_hook.rb +18 -0
- data/lib/farce/engine/ruby.rb +7 -0
- data/lib/farce/engine/shared/unshared_vector.rb +31 -4
- data/lib/farce/engine/shared/vector.rb +8 -0
- data/lib/farce/engine/shared/weak_map/index.rb +14 -1
- data/lib/farce/engine/truffleruby/native/flag.rb +15 -3
- data/lib/farce/envelope.rb +54 -7
- data/lib/farce/exchanger.rb +1 -1
- data/lib/farce/flag.rb +2 -0
- data/lib/farce/integrations/active_support.rb +1 -1
- data/lib/farce/integrations/bson.rb +1 -1
- data/lib/farce/integrations/cbor.rb +1 -1
- data/lib/farce/integrations/concurrent.rb +3 -3
- data/lib/farce/integrations/date.rb +8 -0
- data/lib/farce/integrations/dry_types.rb +7 -4
- data/lib/farce/integrations/json.rb +2 -2
- data/lib/farce/integrations/msgpack.rb +1 -1
- data/lib/farce/integrations/oj.rb +3 -4
- data/lib/farce/integrations/psych.rb +1 -1
- data/lib/farce/integrations/ractor_sharing.rb +1 -1
- data/lib/farce/integrations/sorted_set.rb +1 -1
- data/lib/farce/integrations/weakref.rb +9 -1
- data/lib/farce/integrations/yajl.rb +3 -3
- data/lib/farce/integrations.rb +33 -23
- data/lib/farce/internal/flag_waiting.rb +30 -0
- data/lib/farce/internal/freeze.rb +8 -3
- data/lib/farce/internal/map_value_modes.rb +1 -1
- data/lib/farce/internal/scheduler_lifecycle.rb +1 -1
- data/lib/farce/lazy.rb +4 -4
- data/lib/farce/lazy_ref.rb +3 -3
- data/lib/farce/lfu_map.rb +1 -1
- data/lib/farce/local/flag.rb +4 -0
- data/lib/farce/local/scoped.rb +1 -1
- data/lib/farce/lru_map.rb +1 -1
- data/lib/farce/map.rb +2 -2
- data/lib/farce/mode_manager/smart_rule.rb +138 -0
- data/lib/farce/mode_manager.rb +12 -3
- data/lib/farce/molecule.rb +2 -2
- data/lib/farce/pool.rb +1 -1
- data/lib/farce/port.rb +4 -4
- data/lib/farce/priority_queue.rb +1 -1
- data/lib/farce/proxy/register.rb +6 -0
- data/lib/farce/proxy/supervisor.rb +1 -1
- data/lib/farce/proxy.rb +7 -2
- data/lib/farce/queue.rb +1 -1
- data/lib/farce/scheduler.rb +2 -2
- data/lib/farce/set.rb +1 -1
- data/lib/farce/sorted_set.rb +1 -1
- data/lib/farce/timer_queue.rb +20 -6
- data/lib/farce/transaction/vector.rb +43 -9
- data/lib/farce/transaction/wrapper.rb +14 -0
- data/lib/farce/tree_map.rb +1 -1
- data/lib/farce/unsafe/lfu_map.rb +2 -0
- data/lib/farce/unsafe/lru_map.rb +2 -0
- data/lib/farce/unsafe/tree_map.rb +2 -0
- data/lib/farce/unshareable.rb +8 -19
- data/lib/farce/unshared/atom.rb +3 -0
- data/lib/farce/unshared/lfu_map.rb +2 -0
- data/lib/farce/unshared/lru_map.rb +2 -0
- data/lib/farce/unshared/map.rb +3 -0
- data/lib/farce/unshared/set.rb +1 -0
- data/lib/farce/unshared/sorted_set.rb +1 -0
- data/lib/farce/unshared/tree_map.rb +5 -1
- data/lib/farce/unshared/vector.rb +3 -0
- data/lib/farce/unshared/weak_atom.rb +5 -1
- data/lib/farce/unshared/weak_key_map.rb +3 -0
- data/lib/farce/unshared/weak_map.rb +3 -0
- data/lib/farce/unshared/weak_set.rb +1 -0
- data/lib/farce/unshared/weak_value_map.rb +3 -0
- data/lib/farce/vector.rb +44 -19
- data/lib/farce/version.rb +1 -1
- data/lib/farce.rb +11 -8
- metadata +6 -2
|
@@ -6,7 +6,7 @@ module Farce
|
|
|
6
6
|
module Abstract
|
|
7
7
|
# @abstract A shared super class for all scheduler implementations.
|
|
8
8
|
#
|
|
9
|
-
# @!method schedule(*args, mode: :
|
|
9
|
+
# @!method schedule(*args, mode: :smart, auto_local: true)
|
|
10
10
|
# @abstract This method must be implemented by concrete scheduler subclasses.
|
|
11
11
|
#
|
|
12
12
|
# Schedules a block for execution.
|
|
@@ -23,7 +23,7 @@ module Farce
|
|
|
23
23
|
# May be handled according to `mode`.
|
|
24
24
|
#
|
|
25
25
|
# @param mode [Symbol]
|
|
26
|
-
# The mode in which to schedule the task. Defaults to `:
|
|
26
|
+
# The mode in which to schedule the task. Defaults to `:smart`.
|
|
27
27
|
# May be ignored by some schedulers.
|
|
28
28
|
#
|
|
29
29
|
# @param auto_local [Boolean]
|
|
@@ -82,7 +82,7 @@ module Farce
|
|
|
82
82
|
#
|
|
83
83
|
# @param (see #schedule)
|
|
84
84
|
# @return [self]
|
|
85
|
-
def execute(*, mode: :
|
|
85
|
+
def execute(*, mode: :smart, auto_local: true, &callback)
|
|
86
86
|
raise LocalJumpError, "Cannot yield without a block" unless block_given?
|
|
87
87
|
raise SchedulerClosedError, "cannot execute task on a closed scheduler" if closed?
|
|
88
88
|
|
data/lib/farce/abstract/set.rb
CHANGED
|
@@ -61,7 +61,7 @@ module Farce
|
|
|
61
61
|
# @param normalize [Symbol, Proc, Hash, Farce::Abstract::Map, nil] The element normalizer.
|
|
62
62
|
# @param compare_by_identity [Boolean] Whether membership uses object identity.
|
|
63
63
|
# @param mode [Symbol] The default transfer mode for Farce::Set, Farce::SortedSet,
|
|
64
|
-
# and Farce::WeakSet. Defaults to :
|
|
64
|
+
# and Farce::WeakSet. Defaults to :smart for strong sets and :raise for WeakSet.
|
|
65
65
|
# @param options [Hash] Additional options for the selected variant.
|
|
66
66
|
# @option options [Symbol] scope (:ractor) The scope used by Farce::Local variants.
|
|
67
67
|
# @yield [element] Optionally transform each initial element before storage.
|
|
@@ -753,11 +753,22 @@ module Farce
|
|
|
753
753
|
def prepare_mode_entry(element, requested_mode)
|
|
754
754
|
if identity_membership?(element) && !Ractor.shareable?(element)
|
|
755
755
|
case requested_mode
|
|
756
|
-
when :copy
|
|
756
|
+
when :copy, :marshal
|
|
757
757
|
raise ArgumentError, "identity comparison cannot copy a non-shareable element"
|
|
758
758
|
when :shareable_copy, :make_shareable
|
|
759
759
|
payload = @manager.wrap(element, mode: requested_mode)
|
|
760
760
|
return [insertion_key(payload), payload]
|
|
761
|
+
when :smart, :smart_raise, :smart_copy, :smart_move
|
|
762
|
+
token = IDENTITY_TOKENS[element]
|
|
763
|
+
payload = @manager.wrap(element, mode: requested_mode)
|
|
764
|
+
case payload
|
|
765
|
+
when Envelope::Copy, Envelope::Marshal
|
|
766
|
+
raise ArgumentError, "identity comparison cannot copy a non-shareable element"
|
|
767
|
+
when Envelope::Move
|
|
768
|
+
return [MembershipKey.new(token || Object.new.freeze, identity: true), payload]
|
|
769
|
+
end
|
|
770
|
+
key = @manager.managed_envelope?(payload) ? insertion_key(element) : insertion_key(payload)
|
|
771
|
+
return [key, payload]
|
|
761
772
|
end
|
|
762
773
|
end
|
|
763
774
|
|
|
@@ -812,9 +823,10 @@ module Farce
|
|
|
812
823
|
|
|
813
824
|
def stored_mode(entry)
|
|
814
825
|
case entry.payload
|
|
815
|
-
when Envelope::Copy
|
|
816
|
-
when Envelope::
|
|
817
|
-
when Envelope::
|
|
826
|
+
when Envelope::Copy then :copy
|
|
827
|
+
when Envelope::Marshal then :marshal
|
|
828
|
+
when Envelope::Local then :local
|
|
829
|
+
when Envelope::Move then :move
|
|
818
830
|
else @manager.mode
|
|
819
831
|
end
|
|
820
832
|
end
|
|
@@ -11,12 +11,12 @@ module Farce
|
|
|
11
11
|
# elements raise during insertion or lookup.
|
|
12
12
|
class SortedSet < Set
|
|
13
13
|
# Construct a set in ascending comparator order.
|
|
14
|
-
# @overload initialize(enumerable = nil, normalize: nil, compare_by_identity: false, mode: :
|
|
14
|
+
# @overload initialize(enumerable = nil, normalize: nil, compare_by_identity: false, mode: :smart, **options)
|
|
15
15
|
# @param enumerable [#each, nil] The initial elements, or nil for an empty set.
|
|
16
16
|
# @param normalize [Symbol, Proc, Hash, Farce::Abstract::Map, nil] The element normalizer.
|
|
17
17
|
# @param compare_by_identity [Boolean] Must be false. Membership uses <=>.
|
|
18
18
|
# @param mode [Symbol] The default transfer mode. Only Farce::SortedSet accepts
|
|
19
|
-
# this option, which defaults to :
|
|
19
|
+
# this option, which defaults to :smart.
|
|
20
20
|
# @param options [Hash] Additional options for the selected variant.
|
|
21
21
|
# @option options [Symbol] scope (:ractor) The scope used by Farce::Local::SortedSet.
|
|
22
22
|
# @yield [element] Optionally transform each initial element before normalization.
|
|
@@ -8,6 +8,37 @@ module Farce
|
|
|
8
8
|
class TimerQueue < Queue
|
|
9
9
|
include Internal::BlockingPriorityQueue
|
|
10
10
|
|
|
11
|
+
# A handle for canceling a scheduled value.
|
|
12
|
+
# Entries keep the stored value private, so canceling a moved value does not claim it.
|
|
13
|
+
# With local queues, cancellation uses the current scope.
|
|
14
|
+
#
|
|
15
|
+
# @example Cancel a delayed value
|
|
16
|
+
# queue = Farce::TimerQueue.new
|
|
17
|
+
# entry = queue.push(:work, delay: 60)
|
|
18
|
+
# entry.delete # => true
|
|
19
|
+
class Entry
|
|
20
|
+
# @return [Float] the scheduled monotonic clock time
|
|
21
|
+
attr_reader :clock
|
|
22
|
+
|
|
23
|
+
# @return [Farce::Abstract::TimerQueue] the queue that created this entry
|
|
24
|
+
attr_reader :queue
|
|
25
|
+
|
|
26
|
+
# @api private
|
|
27
|
+
def initialize(value, clock, queue)
|
|
28
|
+
@value = value
|
|
29
|
+
@clock = clock
|
|
30
|
+
@queue = queue
|
|
31
|
+
freeze
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Cancel the scheduled value by identity at its exact timestamp.
|
|
35
|
+
# If the same value was queued more than once at that timestamp, delete the oldest match.
|
|
36
|
+
# @return [Boolean] whether a value was deleted
|
|
37
|
+
# @raise [Farce::ClosedQueueError] when the queue is closed
|
|
38
|
+
def delete = queue.delete(@value, at: clock, compare_by_identity: true)
|
|
39
|
+
alias cancel delete
|
|
40
|
+
end
|
|
41
|
+
|
|
11
42
|
# @param capacity [Integer, nil] the maximum number of values, or nil for an unbounded queue
|
|
12
43
|
def initialize(capacity: nil, track_age: false)
|
|
13
44
|
super
|
|
@@ -22,10 +53,11 @@ module Farce
|
|
|
22
53
|
# With no scheduling option, the value is available immediately. Since `timeout:` controls the capacity wait,
|
|
23
54
|
# use `delay:` or `wait:` to schedule a relative offset.
|
|
24
55
|
# @raise [ThreadError] when the queue is at capacity and non_block is true
|
|
25
|
-
# @return [
|
|
56
|
+
# @return [Entry, false] the cancellation handle, or false if the capacity wait expires
|
|
26
57
|
def push(value, non_block = false, timeout: nil, **time_options) # rubocop:disable Style/OptionalBooleanParameter
|
|
27
58
|
at = Clock.parse(time_options)
|
|
28
|
-
|
|
59
|
+
entry = Entry.new(value, at, self)
|
|
60
|
+
push_to_storage(at, non_block, value, timeout:) && entry
|
|
29
61
|
end
|
|
30
62
|
|
|
31
63
|
# Remove the earliest value, waiting until its timestamp is reached.
|
|
@@ -50,10 +82,11 @@ module Farce
|
|
|
50
82
|
# `at:`, `time:`, `timeout_at:`, `delay:`, `in:`, `offset:`, `timeout:`, `wait:`, or `clock:`.
|
|
51
83
|
# With no scheduling option, the value is available immediately.
|
|
52
84
|
# @yield called when the queue is at capacity
|
|
53
|
-
# @return [
|
|
85
|
+
# @return [Entry, BasicObject] the cancellation handle, or the fallback result when full
|
|
54
86
|
def try_push(value, **time_options)
|
|
55
87
|
at = Clock.parse(time_options)
|
|
56
|
-
|
|
88
|
+
entry = Entry.new(value, at, self)
|
|
89
|
+
return entry if internal_queue.push(at, value)
|
|
57
90
|
block_given? ? yield : false
|
|
58
91
|
end
|
|
59
92
|
|
|
@@ -100,12 +133,18 @@ module Farce
|
|
|
100
133
|
!UNDEFINED.equal?(wait_for_timestamp(timeout_at(timeout)))
|
|
101
134
|
end
|
|
102
135
|
|
|
103
|
-
#
|
|
104
|
-
#
|
|
105
|
-
# @param
|
|
106
|
-
# @param
|
|
107
|
-
# @
|
|
108
|
-
|
|
136
|
+
# Cancel an entry, or delete the oldest matching value at the exact time.
|
|
137
|
+
# Pass `at:` to delete an Entry that was itself queued as a value.
|
|
138
|
+
# @param value [Entry, BasicObject] the cancellation handle or value to delete
|
|
139
|
+
# @param at [Numeric, Time] the exact time to search, required when deleting a value
|
|
140
|
+
# @param compare_by_identity [Boolean] compare values by identity instead of equality when `at:` is given
|
|
141
|
+
# @return [Boolean] whether a value was deleted, or false if the entry belongs to another queue
|
|
142
|
+
# @raise [ArgumentError] when deleting a value without `at:`
|
|
143
|
+
def delete(value, at: UNDEFINED, compare_by_identity: false)
|
|
144
|
+
if UNDEFINED.equal?(at)
|
|
145
|
+
raise ArgumentError, "at: is required when deleting a value" unless Entry === value
|
|
146
|
+
return value.queue.equal?(self) && value.delete
|
|
147
|
+
end
|
|
109
148
|
delete_from_storage(Clock.at(at), value, compare_by_identity:)
|
|
110
149
|
end
|
|
111
150
|
|