|
Open Model Railroad Network (OpenMRN)
|
Base class for state machines. More...
#include <StateFlow.hxx>
Classes | |
| class | Action |
| Return type for a state flow callback. More... | |
| struct | StateFlowSelectHelper |
| Use this class to read from an fd using select() in a state flow. More... | |
| struct | StateFlowTimedSelectHelper |
| Use this class to read from an fd with select and timeout. More... | |
| class | StateFlowTimer |
| Use this timer class to deliver the timeout notification to a stateflow. More... | |
Public Member Functions | |
| void | run () override |
| Callback from the executor. | |
| void | notify () override |
| Wakeup call arrived. | |
| Service * | service () |
| Return a pointer to the service I am bound to. | |
Public Member Functions inherited from Executable | |
| void | test_deletion () |
Public Member Functions inherited from QMember | |
| void | init () |
| Initiailize a QMember, in place of a public placement construction. | |
Static Public Member Functions | |
| template<class T , typename... Args> | |
| static void | invoke_subflow_and_ignore_result (FlowInterface< Buffer< T > > *target_flow, Args &&... args) |
| Calls a helper flow to perform some actions. | |
Protected Types | |
| typedef Action(StateFlowBase::* | Callback) () |
| State Flow callback prototype. | |
Protected Member Functions | |
| StateFlowBase (Service *service) | |
| Constructor. | |
| ~StateFlowBase () | |
| Destructor. | |
| void | reset_flow (Callback c) |
| Resets the flow to the specified state. | |
| bool | is_state (Callback c) |
| bool | is_terminated () |
| void | start_flow (Callback c) |
| Resets the flow to the specified state and starts it. | |
| Action | again () |
| Call the current state again via call_immediately. | |
| Action | exit () |
| Terminate current StateFlow activity. | |
| Action | delete_this () |
| Terminates the flow and deletes *this. | |
| Action | set_terminated () |
| Sets the flow to terminated state. | |
| Action | call_immediately (Callback c) |
| Imediately call the next state upon return. | |
| Action | wait () |
| Wait for an asynchronous call. | |
| Action | wait_and_call (Callback c) |
| Wait for resource to become available before proceeding to next state. | |
| template<class T > | |
| Action | allocate_and_call (FlowInterface< Buffer< T > > *target_flow, Callback c, Pool *pool=nullptr) |
| Allocates a buffer from a pool and proceed to the next state when allocation is successful. | |
| Action | allocate_and_call (Callback c, QAsync *queue) |
| Allocates an entry from an asynchronous queue, and transitions to a state once the allocation is complete. | |
| template<class T > | |
| Buffer< T > * | full_allocation_result (FlowInterface< Buffer< T > > *target_flow) |
| Takes the result of the asynchronous allocation without resetting the object. | |
| template<class T > | |
| T * | full_allocation_result (TypedQAsync< T > *queue) |
| Takes the result of the asynchronous allocation without resetting the object. | |
| template<class T > | |
| void | cast_allocation_result (T **member) |
| Takes the result of the asynchronous allocation without resetting the object. | |
| template<class T > | |
| Buffer< T > * | get_allocation_result (FlowInterface< Buffer< T > > *target_flow) |
| Takes the result of the asynchronous allocation. | |
| Action | yield_and_call (Callback c) |
| Place the current flow to the back of the executor, and transition to a new state after we get the CPU again. | |
| Action | yield () |
| Place the current flow to the back of the executor, and re-try the current state after we get the CPU again. | |
| Action | sleep_and_call (::Timer *timer, long long timeout_nsec, Callback c) |
| Suspends execution of this control flow for a specified time. | |
| template<class T , typename... Args> | |
| Action | invoke_subflow_and_wait (FlowInterface< Buffer< T > > *target_flow, Callback c, Args &&... args) |
| Calls a helper flow to perform some actions. | |
| Action | read_repeated (StateFlowSelectHelper *helper, int fd, void *buf, size_t size, Callback c, unsigned priority=Selectable::MAX_PRIO) |
| Blocks until size bytes are read and then invokes the next state. | |
| Action | read_single (StateFlowSelectHelper *helper, int fd, void *buf, size_t size, Callback c, unsigned priority=Selectable::MAX_PRIO) |
| Attempts to read at most size_t bytes, and blocks the caller until at least one byte is read. | |
| Action | read_nonblocking (StateFlowSelectHelper *helper, int fd, void *buf, size_t size, Callback c, unsigned priority=Selectable::MAX_PRIO) |
| Attempts to read at most size bytes, and then invokes the next state, even if only zero bytes are available right now. | |
| Action | read_repeated_with_timeout (StateFlowTimedSelectHelper *helper, long long timeout_nsec, int fd, void *buf, size_t size, Callback c, unsigned priority=Selectable::MAX_PRIO) |
| Blocks until size bytes are read, or a timeout expires. | |
| Action | internal_try_read () |
| Implementation state that gets repeatedly called upon every wakeup and tries to make progress on reading. | |
| Action | write_repeated (StateFlowSelectHelper *helper, int fd, const void *buf, size_t size, Callback c, unsigned priority=Selectable::MAX_PRIO) |
| Writes some data into a file descriptor, repeating the operation as necessary until all bytes are written. | |
| Action | internal_try_write () |
| Implementation state that gets repeatedly called upon every wakeup and tries to make progress on writing. | |
Protected Member Functions inherited from QMember | |
| QMember () | |
| Constructor. | |
| ~QMember () | |
| Destructor. | |
Private Member Functions | |
| Action | terminated () |
| Terminates the current StateFlow activity. | |
| void | alloc_result (QMember *b) override |
| Callback from a Pool in case of an asynchronous allocation. | |
| StateFlowBase () | |
| Default constructor. | |
| DISALLOW_COPY_AND_ASSIGN (StateFlowBase) | |
Private Attributes | |
| Service * | service_ |
| Service this StateFlow belongs to. | |
| Callback | state_ |
| current active state in the flow | |
| QMember * | allocationResult_ |
| The result of the next allocation that comes in. | |
Additional Inherited Members | |
Protected Attributes inherited from QMember | |
| QMember * | next |
| pointer to the next member in the queue | |
Base class for state machines.
A state machine is a form of collaborative multi-tasking. StateFlows can be scheduled on an executor, and alternately perform synchronous code (executing a state handler function) and an asynchronous operation (waiting for some event to happen). The asynchronous operations may include waiting for a message to arrive in a queue, or waiting for the allocation of an empty buffer, or a notification from a called lower-level library that a specific request has completed processing.
The current state of the StateFlow is represented by a function pointer the points to a member function of the current object. When the state flow is scheduled on an executor, it will execute the current state function. Upon the return of that state function some Action will be performed. The Actions to perform are represented by functions on the StateFlowBase class that return an Action structure, such as allocate_and_call(), wait_and_call(), or call_immediately(). Most factory functions that create these Actions will receive the new state handler as an argument; when the asynchronous action is complete, the state flow will resume execution in the presented state handler function.
Definition at line 170 of file StateFlow.hxx.
|
protected |
State Flow callback prototype.
Definition at line 218 of file StateFlow.hxx.
|
inlineprotected |
Constructor.
| service | Service that this state flow is part of |
Definition at line 200 of file StateFlow.hxx.
|
inlineprotected |
Destructor.
Definition at line 209 of file StateFlow.hxx.
|
inlineprotected |
Call the current state again via call_immediately.
Definition at line 280 of file StateFlow.hxx.
|
inlineoverrideprivatevirtual |
Callback from a Pool in case of an asynchronous allocation.
| b | the newly allocated payload object. |
Reimplemented from Executable.
Definition at line 945 of file StateFlow.hxx.
Allocates an entry from an asynchronous queue, and transitions to a state once the allocation is complete.
| c | is the state to transition to after allocation |
| queue | is the queue to allocate from. |
Definition at line 372 of file StateFlow.hxx.
|
inlineprotected |
Allocates a buffer from a pool and proceed to the next state when allocation is successful.
| target_flow | defines the type of buffer to allocate. |
| c | Callback "state" to move to after allocation |
| pool | pool to allocate from; defaults to the pool of the target flow. |
Definition at line 351 of file StateFlow.hxx.
Imediately call the next state upon return.
| c | Callback "state" to move to |
Definition at line 318 of file StateFlow.hxx.
|
inlineprotected |
Takes the result of the asynchronous allocation without resetting the object.
This should be the first statement in the state where the allocation transitioned. T must be descendant of QMember.
| member | will be filled with the current / latest allocation result correctly casted to the given type. |
Definition at line 411 of file StateFlow.hxx.
|
inlineprotected |
Terminates the flow and deletes *this.
Do not access any member function after this call has been made.
Definition at line 298 of file StateFlow.hxx.
|
inlineprotected |
Terminate current StateFlow activity.
The message instance is not released before termination. This is usefull if the message will be reused for the purpose of sending to another StateFlow.
Definition at line 290 of file StateFlow.hxx.
|
inlineprotected |
Takes the result of the asynchronous allocation without resetting the object.
This should be the first statement in the state where the allocation transitioned. If you expect an empty object, use get_allocation_result() instead.
| target_flow | is the StateFlow for which we allocated. |
Definition at line 386 of file StateFlow.hxx.
|
inlineprotected |
Takes the result of the asynchronous allocation without resetting the object.
This should be the first statement in the state where the allocation transitioned. If you expect an empty object, use get_allocation_result() instead.
| queue | is the typed queue which we allocated from. |
Definition at line 399 of file StateFlow.hxx.
|
inlineprotected |
Takes the result of the asynchronous allocation.
This should be the first statement in the state where the allocation transitioned.
| target_flow | is the StateFlow for which we allocated. |
Definition at line 1221 of file StateFlow.hxx.
|
inlineprotected |
Implementation state that gets repeatedly called upon every wakeup and tries to make progress on reading.
Definition at line 667 of file StateFlow.hxx.
|
inlineprotected |
Implementation state that gets repeatedly called upon every wakeup and tries to make progress on writing.
Definition at line 808 of file StateFlow.hxx.
|
inlinestatic |
Calls a helper flow to perform some actions.
Performs inline synchronous allocation form the main buffer pool. Ignores the target flow's buffer pool settings, because that makes it impossible to guarantee successful allocation.
Fills in the payload's arguments using the passed-in args by calling T::reset(args...). Then sends the buffer to the target flow, and ignores any response value.
| target_flow | is a pointer to the helper flow to be used |
| args | are forwarded to the reset() method on the target flow's buffer type. |
Definition at line 548 of file StateFlow.hxx.
|
inlineprotected |
Calls a helper flow to perform some actions.
Performs inline synchronous allocation form the main buffer pool. Ignores the target flow's buffer pool settings, because that makes it impossible to guarantee successful allocation.
Fills in the payload's arguments using the passed-in args by calling T::reset(args...). Then sends the buffer to the target flow, and waits for the target flow to call return_buffer().
There are requirements on the arguments structure T:
struct Foo { void reset(...); BarrierNotifiable done; }
| target_flow | is a pointer to the helper flow to be used |
| c | is the next state after the target flow is completed |
| args | are forwarded to the reset() method on the target flow's buffer type. |
Definition at line 521 of file StateFlow.hxx.
Definition at line 253 of file StateFlow.hxx.
|
inlineprotected |
Definition at line 259 of file StateFlow.hxx.
|
overridevirtual |
Wakeup call arrived.
Schedules *this on the executor. Does not know the priority.
Reimplemented from Executable.
Reimplemented in StateFlowWithQueue.
Definition at line 97 of file StateFlow.cxx.
|
inlineprotected |
Attempts to read at most size bytes, and then invokes the next state, even if only zero bytes are available right now.
| helper | stores intermediate state. |
| fd | isthe file to read from |
| buf | where to write data we've read |
| size | how many bytes to read |
| c | next state to call after write is complete |
| piority | what execution priority we should be scheduling the intermediate and next states after the read is complete. |
Definition at line 619 of file StateFlow.hxx.
|
inlineprotected |
Blocks until size bytes are read and then invokes the next state.
| helper | stores intermediate state. |
| fd | isthe file to read from |
| buf | where to write data we've read |
| size | how many bytes to read |
| c | next state to call after write is complete |
| piority | what execution priority we should be scheduling the intermediate and next states after the read is complete. |
Definition at line 570 of file StateFlow.hxx.
|
inlineprotected |
Blocks until size bytes are read, or a timeout expires.
If the timeout expires, jumps to next state with whatever data has been read. To figure out whether the timer expired or the read completed, the caller can check helper->remaining_ != 0.
| helper | stores intermediate state. |
| timeout_nsec | stop waiting for more data after this many nanoseconds elapsed |
| fd | isthe file to read from |
| buf | where to write data we've read |
| size | how many bytes to read maximum |
| c | next state to call after write is complete |
| piority | what execution priority we should be scheduling the intermediate and next states after the read is complete. |
Definition at line 646 of file StateFlow.hxx.
|
inlineprotected |
Attempts to read at most size_t bytes, and blocks the caller until at least one byte is read.
Then the next state is invoked with whatever the first read returned.
| helper | stores intermediate state. |
| fd | isthe file to read from |
| buf | where to write data we've read |
| size | how many bytes to read maximum |
| c | next state to call after write is complete |
| piority | what execution priority we should be scheduling the intermediate and next states after the read is complete. |
Definition at line 594 of file StateFlow.hxx.
|
inlineprotected |
Resets the flow to the specified state.
| c | is the state to continue the flow from after the next notification. |
Definition at line 247 of file StateFlow.hxx.
|
overridevirtual |
Callback from the executor.
Executes the current state (until we get a wait or yield return).
This function will be invoked when the current stateflow gets the CPU. It will execute the current states until the flow yields or is blocked in a waiting state.
Implements Executable.
Definition at line 58 of file StateFlow.cxx.
|
inline |
Return a pointer to the service I am bound to.
Definition at line 191 of file StateFlow.hxx.
|
inlineprotected |
Sets the flow to terminated state.
Definition at line 309 of file StateFlow.hxx.
|
inlineprotected |
Suspends execution of this control flow for a specified time.
After the timeout expires the flow will continue in state c.
| timer | is the timer to start. This timer should be set up to eventually call notify() on *this. We recommend using a StateFlowTimer. |
| timeout_nsec | is the timeout with which to start the timer. |
| c | is the next state to transition to when the timeout expires or the timer gets triggered. |
Definition at line 493 of file StateFlow.hxx.
|
inlineprotected |
Resets the flow to the specified state and starts it.
| c | is the state to start the flow from. |
Definition at line 267 of file StateFlow.hxx.
|
private |
Terminates the current StateFlow activity.
This is a sink state, and there has to be an external call to do anything useful after this state has been reached.
Definition at line 126 of file StateFlow.cxx.
|
inlineprotected |
Wait for an asynchronous call.
Definition at line 327 of file StateFlow.hxx.
Wait for resource to become available before proceeding to next state.
| c | State to move to |
Definition at line 336 of file StateFlow.hxx.
|
inlineprotected |
Writes some data into a file descriptor, repeating the operation as necessary until all bytes are written.
| helper | temporary storage (usually local to the calling flow) |
| fd | filedes to write into |
| buf | Pointer to data to write. The data must stay alive until the next state is called. |
| size | Number of bytes of data to write. |
| c | next state function to call. Use the syntax STATE(my_state_fn) |
| priority | Which priority to schedule the flow's next state when the write is complete. |
Definition at line 790 of file StateFlow.hxx.
|
inlineprotected |
Place the current flow to the back of the executor, and re-try the current state after we get the CPU again.
Similar to again, except we place this flow on the back of the Executor queue.
Definition at line 442 of file StateFlow.hxx.
Place the current flow to the back of the executor, and transition to a new state after we get the CPU again.
Similar to call_immediately, except we place this flow on the back of the Executor queue.
| c | Callback "state" to move to |
Definition at line 430 of file StateFlow.hxx.
|
private |
The result of the next allocation that comes in.
Definition at line 955 of file StateFlow.hxx.
|
private |
Service this StateFlow belongs to.
Definition at line 934 of file StateFlow.hxx.
|
private |
current active state in the flow
Definition at line 952 of file StateFlow.hxx.