pub struct RunState { /* private fields */ }Expand description
RunState is a structure that maintains the state of all the functions in the currently
executing flow.
§The Semantics of a Flow’s RunState
The semantics of the state of each function in a flow and the flow over are described here and the tests of the struct attempt to reproduce and confirm as many of them as is possible
§Terminology
- function - an entry in the manifest and the flow graph that may take inputs, will execute an implementation on a Job and may produce an Output
- input - a function may have 0 or more inputs that accept values required for it’s execution
- implementation - the code that is run, accepting 0 or more input values performing some calculations and possibly producing an output value. One implementation can be used by multiple functions in a flow
- destinations - a set of other functions and their specific inputs that a function is connected to and hence where the output value is sent when execution is completed
- job - a job is the bundle of information necessary to execute. It consists of the function’s id, the input values, the implementation to run, and the destinations to send the output value to
- execution - the act of running an implementation on the input values to produce an output
- output - a function when ran produces an output. The output contains the id of the function that was ran, the input values (for debugging), the result (optional value plus an indicator if the function wishes to be ran again when ready), the destinations to send any value to and an optional error string.
§Start-up
At start-up all functions are initialized. For each of the functions inputs their
init_inputs function will be called, meaning that some inputs may be initialized (filled).
If all inputs are full then the Function will be ready to run.
§One-time Execution or Stopping repetitive execution
A function may need to only run once, or to stop being executed repeatedly at some point. So each implementation when ran returns a “run again” flag to indicate this. An example of functions that may decide to stop running are:
- args: produces arguments from the command line execution of a flow once at start-up
- readline: read a line of input from standard input, until End-of-file (EOF) is detected. If this was not done, then the flow would never stop running as the readline function would always be re-run and waiting for more input, but none would ever be received after EOF.
§Unused Functions
If a pure function has an output but it is not used (not connected to any input) then the
function should have no affect on the execution of the flow and the optimizer may remove it and
all connections to its input. That in turn may affect other functions which can be removed,
until there are no more left to remove.
Thus at run-time, a pure function with it’s output unused is not expected and no special
handling of that case is taken. If a manifest is read where a pure function has no destinations,
then it will be run (when it received inputs) and it’s output discarded.
That is sub-optimal execution but no errors should result. Hence the role of the optimizer at
compile time.
Tests: pure_function_no_destinations
§Unconnected inputs
If a function’s output is used but one or more of it’s inputs is unconnected, then the compiler should throw an error. If for some reason an alternative compiler did not reject this and generated a manifest with no other function sending to that input, then at run-time that functions inputs will never be full and the function will never run. This could produce some form of deadlock or incomplete execution, but it should not produce any run-time error.
A run-time is within it’s rights to discard this function, and then potentially other functions connected to it’s output and other inputs until no more can be removed. This run-time does not do that, in order to keep things simple and start-up time to a minimum. It relies on the compiler having done that previously.
§Initializers
There are two types of initializers on inputs:
- “Once” - the input is filled with the specified value once at start-up.
- “Constant” - after the functions runs the input refilled with the same value.
§Runtime Rules
- A function won’t be run until all of its inputs are ready
- An input maybe initialized at start-up once by a “Once” input initializer
- An input maybe initialized after each run by a “Constant” input initializer that ensures that the same value always re-fills the input
§State Transitions
From To State Event causing transition and additional conditions Test
Init Ready No inputs to_ready_1_on_init
All inputs initialized to_ready_2_on_init
All inputs initialized and no destinations to_ready_3_on_init
Init Waiting At least one input is not full to_waiting_on_init
Ready Running NextJob: called to fetch the function_id for execution ready_to_running_on_next
Waiting Ready Output: last empty input on a function is filled waiting_to_ready_on_input
Running Ready Output: it’s inputs are all full, so it can run again running_to_ready_on_done
Running Waiting Output: it has one input or more empty, to it can’t run running_to_waiting_on_done
§Iteration and Recursion
A function may send values to itself using a loop-back connector, in order to perform something similar to iteration or recursion, in procedural programming.
§Parallel Execution of Jobs
Multiple functions (jobs) may execute in parallel, providing there is no data dependency preventing it. Example dependencies:
- a function lacks an input and needs to get it from another function that has not completed
Respecting this rule, a RunTime can dispatch as many Jobs in parallel as it desires. This one
takes the parameter max_jobs on RunState::new() to specify the maximum number of jobs that
are launched in parallel. The minimum value for this is 1
Implementations§
Source§impl RunState
impl RunState
Sourcepub fn new(submission: Submission) -> Self
pub fn new(submission: Submission) -> Self
Create a new RunState struct from the list of functions provided and the Submission
that was sent to be executed
Sourcepub fn get_function_states(&self, function_id: usize) -> Vec<State>
pub fn get_function_states(&self, function_id: usize) -> Vec<State>
Return the states a function is in
Sourcepub fn get_running(&self) -> &HashMap<usize, Job>
pub fn get_running(&self) -> &HashMap<usize, Job>
Get a Set (job_id) of the currently running jobs
Sourcepub fn get_function(&self, id: usize) -> Option<&RuntimeFunction>
pub fn get_function(&self, id: usize) -> Option<&RuntimeFunction>
Get a reference to the function with id
Sourcepub fn get_busy_count(&self) -> &HashMap<usize, usize>
pub fn get_busy_count(&self) -> &HashMap<usize, usize>
Return the busy count map (process_id -> count of busy entries)
Sourcepub fn get_number_of_jobs_created(&self) -> usize
pub fn get_number_of_jobs_created(&self) -> usize
get the number of jobs created to date in the flow’s execution
Sourcepub fn number_jobs_running(&self) -> usize
pub fn number_jobs_running(&self) -> usize
Return how many jobs are currently running
Sourcepub fn number_jobs_ready(&self) -> usize
pub fn number_jobs_ready(&self) -> usize
Return how many jobs are ready to be run, but not running yet
Sourcepub fn num_functions(&self) -> usize
pub fn num_functions(&self) -> usize
Return how many functions exist in this flow being executed
Trait Implementations§
Source§impl<'de> Deserialize<'de> for RunState
impl<'de> Deserialize<'de> for RunState
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Auto Trait Implementations§
impl !RefUnwindSafe for RunState
impl !Sync for RunState
impl !UnwindSafe for RunState
impl Freeze for RunState
impl Send for RunState
impl Unpin for RunState
impl UnsafeUnpin for RunState
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more