Represents an acknowledgement of processing that a consumer sends back upstream.
A high-performance, back-pressured, asynchronous queue implementation.
A high-performance, back-pressured, asynchronous queue implementation.
This is the impure, future-enabled version of monix.catnap.ConcurrentQueue.
import monix.execution.Scheduler.Implicits.global val queue = AsyncQueue(capacity = 32) def producer(n: Int): CancelableFuture[Unit] = queue.offer(n).flatMap { _ => if (n >= 0) producer(n - 1) else CancelableFuture.unit } def consumer(index: Int): CancelableFuture[Unit] = queue.poll().flatMap { a => println(s"Worker $$index: $$a") }
The initialized queue can be limited to a maximum buffer size, a size that could be rounded to a power of 2, so you can't rely on it to be precise. Such a bounded queue can be initialized via AsyncQueue.bounded. Also see BufferCapacity, the configuration parameter that can be passed in the AsyncQueue.withConfig builder.
On offer, when the queue is full, the implementation back-pressures until the queue has room again in its internal buffer, the future being completed when the value was pushed successfully. Similarly poll awaits the queue to have items in it. This works for both bounded and unbounded queues.
For both offer
and poll
, in case awaiting a result happens, the
implementation does so asynchronously, without any threads being blocked.
Currently the implementation is optimized for speed. In a producer-consumer pipeline the best performance is achieved if the producer(s) and the consumer(s) do not contend for the same resources. This is why when doing asynchronous waiting for the queue to be empty or full, the implementation does so by repeatedly retrying the operation, with asynchronous boundaries and delays, until it succeeds. Fairness is ensured by the implementation.
This queue support a ChannelType configuration, for fine tuning depending on the needed multi-threading scenario — and this can yield better performance:
The default is MPMC
, because that's the safest scenario.
import monix.execution.ChannelType.MPSC val queue = AsyncQueue( capacity = 64, channelType = MPSC )
WARNING: default is MPMC
, however any other scenario implies
a relaxation of the internal synchronization between threads.
This means that using the wrong scenario can lead to severe
concurrency bugs. If you're not sure what multi-threading scenario you
have, then just stick with the default MPMC
.
The AsyncSemaphore
is an asynchronous semaphore implementation that
limits the parallelism on Future
execution.
The AsyncSemaphore
is an asynchronous semaphore implementation that
limits the parallelism on Future
execution.
The following example instantiates a semaphore with a maximum parallelism of 10:
val semaphore = AsyncSemaphore(maxParallelism = 10) def makeRequest(r: HttpRequest): Future[HttpResponse] = ??? // For such a task no more than 10 requests // are allowed to be executed in parallel. val future = semaphore.greenLight(() => makeRequest(???))
Asynchronous mutable location, that is either empty or contains
a value of type A
.
Asynchronous mutable location, that is either empty or contains
a value of type A
.
It has these fundamental atomic operations:
true
if it succeeded, or returning immediately false
in case
the var was full and thus the operation failedSome(a)
, or otherwise returning
None
in case the var was empty and thus the operation failedSome(a)
, or None
if emptyThe AsyncVar
is appropriate for building synchronization
primitives and performing simple inter-thread communications.
If it helps, it's similar with a BlockingQueue(capacity = 1)
,
except that it doesn't block any threads, all waiting being
callback-based.
Given its asynchronous, non-blocking nature, it can be used on top of Javascript as well.
This is inspired by Control.Concurrent.MVar from Haskell, except that the implementation is made to work with plain Scala futures (and is thus impure).
Describes the capacity of internal buffers.
Describes the capacity of internal buffers.
For abstractions that use an internal buffer, like AsyncQueue, this type provides the info required to build the internal buffer.
Represents a callback that should be called asynchronously with the result of a computation.
Represents a callback that should be called asynchronously with the result of a computation.
This is an Either[E, A] => Unit
with an OOP interface that
avoids extra boxing, along with overloads of apply
.
The onSuccess
method should be called only once, with the successful
result, whereas onError
should be called if the result is an error.
Obviously Callback
describes unsafe side-effects, a fact that is
highlighted by the usage of Unit
as the return type. Obviously
callbacks are unsafe to use in pure code, but are necessary for
describing asynchronous processes.
THREAD-SAFETY: callback implementations are NOT thread-safe by contract, this depends on the implementation. Callbacks can be made easily thread-safe via wrapping with:
NOTE that callbacks injected in the Task async builders (e.g. Task.async) are thread-safe.
Represents a one-time idempotent action that can be used to cancel async computations, or to release resources that active data sources are holding.
Represents a one-time idempotent action that can be used to cancel async computations, or to release resources that active data sources are holding.
It is equivalent to java.io.Closeable
, but without the I/O focus, or
to IDisposable
in Microsoft .NET, or to akka.actor.Cancellable
.
Represents an asynchronous computation that can be canceled as long as it isn't complete.
CancelablePromise
is a scala.concurrent.Promise implementation that
allows listeners to unsubscribe from receiving future results.
CancelablePromise
is a scala.concurrent.Promise implementation that
allows listeners to unsubscribe from receiving future results.
It does so by:
Being able to unsubscribe listeners helps with avoiding memory leaks in case of listeners or futures that are being timed-out due to promises that take a long time to complete.
An enumeration of all types
Specification for run-loops, imposed by the Scheduler
.
Specification for run-loops, imposed by the Scheduler
.
When executing tasks, a run-loop can always execute tasks asynchronously (by forking logical threads), or it can always execute them synchronously (same thread and call-stack, by using an internal trampoline), or it can do a mixed mode that executes tasks in batches before forking.
The specification is considered a recommendation for how run loops should behave, but ultimately it's up to the client to choose the best execution model. This can be related to recursive loops or to events pushed into consumers.
Features
describes a set of features described via
bitwise operators applied to ints, but made type safe.
Features
describes a set of features described via
bitwise operators applied to ints, but made type safe.
This is like a special purpose BitSet
.
Currently used to describe the features of Scheduler.
A Scheduler is an scala.concurrent.ExecutionContext
that additionally can
schedule the execution of units of work to run with a delay or periodically.
A Scheduler is an scala.concurrent.ExecutionContext
that additionally can
schedule the execution of units of work to run with a delay or periodically.
An exception reporter is a function that logs an uncaught error.
An exception reporter is a function that logs an uncaught error.
Usually taken as an implicit when executing computations that could fail, but that must not blow up the call-stack, like asynchronous tasks.
A default implicit is provided that simply logs the error on STDERR.
Utilities for Scala's standard concurrent.Future
.
A small toolkit of classes that support compare-and-swap semantics for safe mutation of variables.
A small toolkit of classes that support compare-and-swap semantics for safe mutation of variables.
On top of the JVM, this means dealing with lock-free thread-safe programming. Also works on top of Javascript, with Scala.js, for API compatibility purposes and because it's a useful way to box a value.
The backbone of Atomic references is this method:
def compareAndSet(expect: T, update: T): Boolean
This method atomically sets a variable to the update
value if it currently holds
the expect
value, reporting true
on success or false
on failure. The classes in this package
also contain methods to get and unconditionally set values.
Building a reference is easy with the provided constructor, which will automatically
return the most specific type needed (in the following sample, that's an AtomicDouble
,
inheriting from AtomicNumber[A]
):
val atomicNumber = Atomic(12.2) atomicNumber.incrementAndGet() // => 13.2
These also provide useful helpers for atomically mutating of values
(i.e. transform
, transformAndGet
, getAndTransform
, etc...) or of numbers of any kind
(incrementAndGet
, getAndAdd
, etc...).
Cancelables represent asynchronous units of work or other things scheduled for execution and whose execution can be canceled.
Cancelables represent asynchronous units of work or other things scheduled for execution and whose execution can be canceled.
One use-case is the scheduling done by monix.execution.Scheduler, in which
the scheduling methods return a Cancelable
, allowing the canceling of the
scheduling.
Example:
val s = ConcurrentScheduler() val task = s.scheduleRepeated(10.seconds, 50.seconds, { doSomething() }) // later, cancels the scheduling ... task.cancel()
Package exposing utilities for working with the Reactive Streams specification.
Represents an acknowledgement of processing that a consumer sends back upstream. Useful to implement back-pressure.