From aa2596f08893e41f98fe938585898faab322ad7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Endre=20S=C3=A1ndor=20Varga?= Date: Thu, 9 Jul 2015 10:40:20 +0200 Subject: [PATCH] +doc #16765: Clarify asyncrhonous backpressure and thread-safety --- akka-docs-dev/rst/java/stream-customize.rst | 16 ++++++++++++++++ .../rst/java/stream-flows-and-basics.rst | 10 ++++++++++ akka-docs-dev/rst/scala/stream-customize.rst | 16 ++++++++++++++++ .../rst/scala/stream-flows-and-basics.rst | 9 +++++++++ 4 files changed, 51 insertions(+) diff --git a/akka-docs-dev/rst/java/stream-customize.rst b/akka-docs-dev/rst/java/stream-customize.rst index b36f8718a6..536f7b1246 100644 --- a/akka-docs-dev/rst/java/stream-customize.rst +++ b/akka-docs-dev/rst/java/stream-customize.rst @@ -322,3 +322,19 @@ and continue with shutting down the entire stream. It is not possible to emit elements from the completion handling, since completion handlers may be invoked at any time (without regard to downstream demand being available). +Thread safety of custom processing stages +========================================= + +All of the above custom stages (linear or graph) provide a few simple guarantees that implementors can rely on. + - The callbacks exposed by all of these classes are never called concurrently. + - The state encapsulated by these classes can be safely modified from the provided callbacks, without any further + synchronization. + +In essence, the above guarantees are similar to what :class:`Actor`s provide, if one thinks of the state of a custom +stage as state of an actor, and the callbacks as the ``receive`` block of the actor. + +.. warning:: +It is **not safe** to access the state of any custom stage outside of the callbacks that it provides, just like it + is unsafe to access the state of an actor from the outside. This means that Future callbacks should **not close over** + internal state of custom stages because such access can be concurrent with the provided callbacks, leading to undefined + behavior. \ No newline at end of file diff --git a/akka-docs-dev/rst/java/stream-flows-and-basics.rst b/akka-docs-dev/rst/java/stream-flows-and-basics.rst index 969f0daacc..c41bf266e1 100644 --- a/akka-docs-dev/rst/java/stream-flows-and-basics.rst +++ b/akka-docs-dev/rst/java/stream-flows-and-basics.rst @@ -26,12 +26,22 @@ Back-pressure A means of flow-control, a way for consumers of data to notify a producer about their current availability, effectively slowing down the upstream producer to match their consumption speeds. In the context of Akka Streams back-pressure is always understood as *non-blocking* and *asynchronous*. +Non-Blocking + Means that a certain operation does not hinder the progress of the calling thread, even if it takes long time to + finish the requested operation. Processing Stage The common name for all building blocks that build up a Flow or FlowGraph. Examples of a processing stage would be operations like ``map()``, ``filter()``, stages added by ``transform()`` like :class:`PushStage`, :class:`PushPullStage`, :class:`StatefulStage` and graph junctions like ``Merge`` or ``Broadcast``. For the full list of built-in processing stages see :ref:`stages-overview` +When we talk about *asynchronous, non-blocking backpressure* we mean that the processing stages available in Akka +Streams will not use blocking calls but asynchronous message passing to exchange messages between each other, and they +will use asynchronous means to slow down a fast producer, without blocking its thread. This is a thread-pool friendly +design, since entities that need to wait (a fast producer waiting on a slow consumer) will not block the thread but +can hand it back for further use to an underlying thread-pool. + + Defining and running streams ---------------------------- Linear processing pipelines can be expressed in Akka Streams using the following core abstractions: diff --git a/akka-docs-dev/rst/scala/stream-customize.rst b/akka-docs-dev/rst/scala/stream-customize.rst index a014734a38..bfab4e952a 100644 --- a/akka-docs-dev/rst/scala/stream-customize.rst +++ b/akka-docs-dev/rst/scala/stream-customize.rst @@ -324,3 +324,19 @@ and continue with shutting down the entire stream. It is not possible to emit elements from the completion handling, since completion handlers may be invoked at any time (without regard to downstream demand being available). +Thread safety of custom processing stages +========================================= + +All of the above custom stages (linear or graph) provide a few simple guarantees that implementors can rely on. + - The callbacks exposed by all of these classes are never called concurrently. + - The state encapsulated by these classes can be safely modified from the provided callbacks, without any further + synchronization. + +In essence, the above guarantees are similar to what :class:`Actor`s provide, if one thinks of the state of a custom +stage as state of an actor, and the callbacks as the ``receive`` block of the actor. + +.. warning:: + It is **not safe** to access the state of any custom stage outside of the callbacks that it provides, just like it + is unsafe to access the state of an actor from the outside. This means that Future callbacks should **not close over** + internal state of custom stages because such access can be concurrent with the provided callbacks, leading to undefined + behavior. \ No newline at end of file diff --git a/akka-docs-dev/rst/scala/stream-flows-and-basics.rst b/akka-docs-dev/rst/scala/stream-flows-and-basics.rst index 12febcff4a..9ab8de8daa 100644 --- a/akka-docs-dev/rst/scala/stream-flows-and-basics.rst +++ b/akka-docs-dev/rst/scala/stream-flows-and-basics.rst @@ -26,12 +26,21 @@ Back-pressure A means of flow-control, a way for consumers of data to notify a producer about their current availability, effectively slowing down the upstream producer to match their consumption speeds. In the context of Akka Streams back-pressure is always understood as *non-blocking* and *asynchronous*. +Non-Blocking + Means that a certain operation does not hinder the progress of the calling thread, even if it takes long time to + finish the requested operation. Processing Stage The common name for all building blocks that build up a Flow or FlowGraph. Examples of a processing stage would be operations like ``map()``, ``filter()``, stages added by ``transform()`` like :class:`PushStage`, :class:`PushPullStage`, :class:`StatefulStage` and graph junctions like ``Merge`` or ``Broadcast``. For the full list of built-in processing stages see :ref:`stages-overview` +When we talk about *asynchronous, non-blocking backpressure* we mean that the processing stages available in Akka +Streams will not use blocking calls but asynchronous message passing to exchange messages between each other, and they +will use asynchronous means to slow down a fast producer, without blocking its thread. This is a thread-pool friendly +design, since entities that need to wait (a fast producer waiting on a slow consumer) will not block the thread but +can hand it back for further use to an underlying thread-pool. + Defining and running streams ---------------------------- Linear processing pipelines can be expressed in Akka Streams using the following core abstractions: