| // Copyright (C) 2022 The Android Open Source Project |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| // To render: dot -Tpng stream-out-async-sm.gv -o stream-out-async-sm.png |
| digraph stream_out_async_state_machine { |
| node [shape=doublecircle style=filled fillcolor=black width=0.5] I; |
| node [shape=point width=0.5] F; |
| node [shape=oval width=1]; |
| node [fillcolor=lightgreen] STANDBY; // buffer is empty |
| node [fillcolor=lightgreen] IDLE; // buffer is empty |
| node [fillcolor=tomato] CLOSED; |
| node [fillcolor=tomato] ERROR; |
| node [style=dashed] ANY_STATE; |
| node [fillcolor=lightblue style=filled]; |
| // Note that when the consumer (h/w) is passive, "burst" operations |
| // complete synchronously, bypassing the TRANSFERRING state. |
| I -> STANDBY; |
| STANDBY -> IDLE [label="start"]; // consumer -> active |
| STANDBY -> PAUSED [label="burst"]; // producer -> active |
| IDLE -> STANDBY [label="standby"]; // consumer -> passive |
| IDLE -> TRANSFERRING [label="burst"]; // producer -> active |
| IDLE -> ACTIVE [label="burst"]; // full write |
| ACTIVE -> PAUSED [label="pause"]; // consumer -> passive (not consuming) |
| ACTIVE -> DRAINING [label="drain"]; // producer -> passive |
| ACTIVE -> TRANSFERRING [label="burst"]; // early unblocking |
| ACTIVE -> ACTIVE [label="burst"]; // full write |
| TRANSFERRING -> ACTIVE [label="←IStreamCallback.onTransferReady"]; |
| TRANSFERRING -> TRANSFER_PAUSED [label="pause"]; // consumer -> passive (not consuming) |
| TRANSFERRING -> DRAINING [label="drain"]; // producer -> passive |
| TRANSFER_PAUSED -> TRANSFERRING [label="start"]; // consumer -> active |
| TRANSFER_PAUSED -> DRAIN_PAUSED [label="drain"]; // producer -> passive |
| TRANSFER_PAUSED -> IDLE [label="flush"]; // buffer is cleared |
| PAUSED -> PAUSED [label="burst"]; |
| PAUSED -> ACTIVE [label="start"]; // consumer -> active |
| PAUSED -> IDLE [label="flush"]; // producer -> passive, buffer is cleared |
| DRAINING -> IDLE [label="←IStreamCallback.onDrainReady"]; |
| DRAINING -> TRANSFERRING [label="burst"]; // producer -> active |
| DRAINING -> ACTIVE [label="burst"]; // full write |
| DRAINING -> DRAIN_PAUSED [label="pause"]; // consumer -> passive (not consuming) |
| DRAIN_PAUSED -> DRAINING [label="start"]; // consumer -> active |
| DRAIN_PAUSED -> TRANSFER_PAUSED [label="burst"]; // producer -> active |
| DRAIN_PAUSED -> IDLE [label="flush"]; // buffer is cleared |
| IDLE -> ERROR [label="←IStreamCallback.onError"]; |
| DRAINING -> ERROR [label="←IStreamCallback.onError"]; |
| TRANSFERRING -> ERROR [label="←IStreamCallback.onError"]; |
| ANY_STATE -> CLOSED [label="→IStream*.close"]; |
| CLOSED -> F; |
| } |