Variants
Most Farce classes implement a set of variants as separate subclasses within module namespaces.
These namespaces and variants are:
- Farce: Data containers that support both shareable and unshareable content. Unshareable content is usually handled by implementing mode support. Keep in mind that this is also the top level namespace for Farce in general, so it contains other classes and modules not implementing variants (including the variant namespaces themselves).
- Farce::Strict: Variants that enforce strict sharing rules. Unshareable content will be rejected.
- Farce::Local: Variants that hold concrete, independent data for each scope (i.e., one copy per ractor, thread, etc). As no scope stretches across multiple ractors, these may contain unshareable content without issue.
- Farce::Unshared: Variants that explicitly allow unshareable content. These cannot be shared across multiple ractors.
- Farce::Unsafe: Variants that aren't shareable but moreover aren't guaranteed to be thread-safe either. They only exist if they give a significant performance or usability benefit despite these limitations.
- Farce::Transaction: Variants generated by transactions.
You can choose the variant based on your needs:
global_map = Farce::Map.new
local_map = Farce::Local::Map.new(scope: :thread)
None of the namespaces define any instance methods, so they are safe to include:
class MyClass
include Farce::Strict
@register = Map.new
@cache = LRUMap.new
end
Classes implementing Variants
| Farce | Strict | Local | Unshared | Unsafe | Transaction | |
|---|---|---|---|---|---|---|
| Atom | ✅ | ✅ | ✅ | ✅ | 🔗 | ✅ |
| Counter | ✅ | 🔗 | ✅ | 🔗 | 🔗 | ➖ |
| Exchanger | ✅ | ✅ | ➖ | ➖ | ➖ | ➖ |
| Flag | ✅ | 🔗 | ✅ | 🔗 | 🔗 | ➖ |
| Lazy | ✅ | ✅ | ✅ | ✅ | 🔗 | ➖ |
| LazyRef | ✅ | ✅ | ✅ | ✅ | 🔗 | ➖ |
| Lease | ✅ | ✅ | ✅ | ✅ | 🔗 | ➖ |
| LeaseMap | ✅ | ✅ | ✅ | ✅ | 🔗 | ➖ |
| LeasePool | ✅ | ✅ | ✅ | ✅ | 🔗 | ➖ |
| LFUMap | ✅ | ✅ | ✅ | ✅ | ✅ | ➖ |
| LRUMap | ✅ | ✅ | ✅ | ✅ | ✅ | ➖ |
| Molecule | ✅ | ✅ | ✅ | ✅ | 🔗 | ✅ |
| Map | ✅ | ✅ | ✅ | ✅ | 🔗 | ✅ |
| Mutable | ✅ | ➖ | ➖ | ➖ | ➖ | ✅ |
| Port | ✅ | ✅ | ➖ | ➖ | ➖ | ➖ |
| PriorityQueue | ✅ | ✅ | ✅ | ✅ | 🔗 | ➖ |
| Queue | ✅ | ✅ | ✅ | ✅ | 🔗 | ➖ |
| Set | ✅ | ✅ | ✅ | ✅ | 🔗 | ✅ |
| SortedSet | ✅ | ✅ | ✅ | ✅ | 🔗 | ✅ |
| TimerQueue | ✅ | ✅ | ✅ | ✅ | 🔗 | ➖ |
| TreeMap | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Vector | ✅ | ✅ | ✅ | ✅ | 🔗 | ✅ |
| WeakAtom | ✅ | ✅ | ✅ | ✅ | 🔗 | ➖ |
| WeakKeyMap | ✅ | ✅ | ✅ | ✅ | 🔗 | ➖ |
| WeakMap | ✅ | ✅ | ✅ | ✅ | 🔗 | ➖ |
| WeakSet | ✅ | ✅ | ✅ | ✅ | 🔗 | ➖ |
| WeakValueMap | ✅ | ✅ | ✅ | ✅ | 🔗 | ➖ |
Legend:
- ✅ Defined
- ➖ Not defined
- 🔗 Alias for another variant
Classes without Variants
When using the variant namespaces interchangeably, keep in mind that some classes do not come with variants.
This is obvious for classes that aren't data containers, like Signal or Lock, but also include classes like Envelope and Scheduler, which support modes, and WeakValue and WeakRef, which will choose (and switch) between the correct WeakAtom variants automatically.
Abstract Classes and Modules
Classes with variants will typically have at least one abstract class or module that they implement. This is helpful for type checking and as a possible extension point, while doing a better job at substitution.
For example, Farce::Map subclasses should all implement mode support, but the same cannot be said for all Farce::Abstract::Map subclasses.
This makes type checking easy:
def self.increment_counter(counter)
case counter
when Farce::Abstract::Counter then counter.increment
when Ratomic::Counter then counter.increment(1) # required argument
else raise "Unsupported counter type"
end
end
counter = Farce::Counter.new
increment_counter(counter)
counter = Farce::Local::Counter.new(scope: :fiber)
increment_counter(counter)
Abstract classes may in turn have abstract subclasses to group functionality. For instance, all PriorityQueue variants inherit from Farce::Abstract::PriorityQueue, which in turn is a subclass of Farce::Abstract::Queue.
A noticeably more complex abstract hierarchy exists for maps:
Farce::Abstract::Map: Superclass for all map variants. Contains the almost complete set of Hash-compatible methods, as well as some additional methods likestore_if_absent.Farce::Abstract::ConcurrentMap: Superclass for maps with an extended concurrency API, includingFarce::Mapand its variants.Farce::Abstract::WeakMap: Superclass for allWeakMapvariants.Farce::Abstract::WeakKeyMap: Superclass for allWeakKeyMapvariants.Farce::Abstract::WeakValueMap: Superclass for allWeakValueMapvariants.
Farce::Abstract::BoundedMap: Superclass for all map variants with an enforced size limit. All current variants enforce this limit via eviction, but a subclass rejecting writes could be a valid implementation.Farce::Abstract::LFUMap: Superclass for all Least Frequently Used (LFU) map variants.Farce::Abstract::LRUMap: Superclass for all Least Recently Used (LRU) map variants.
Farce::Abstract::LeaseMap: Superclass for allLeaseMapvariants.Farce::Abstract::TreeMap: Superclass for allTreeMapvariants.