Skip to main content

RunState

Struct RunState 

Source
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

Source

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

Source

pub fn get_function_states(&self, function_id: usize) -> Vec<State>

Return the states a function is in

Source

pub fn get_running(&self) -> &HashMap<usize, Job>

Get a Set (job_id) of the currently running jobs

Source

pub fn get_function(&self, id: usize) -> Option<&RuntimeFunction>

Get a reference to the function with id

Source

pub fn get_busy_count(&self) -> &HashMap<usize, usize>

Return the busy count map (process_id -> count of busy entries)

Source

pub fn get_number_of_jobs_created(&self) -> usize

get the number of jobs created to date in the flow’s execution

Source

pub fn number_jobs_running(&self) -> usize

Return how many jobs are currently running

Source

pub fn number_jobs_ready(&self) -> usize

Return how many jobs are ready to be run, but not running yet

Source

pub fn num_functions(&self) -> usize

Return how many functions exist in this flow being executed

Trait Implementations§

Source§

impl Clone for RunState

Source§

fn clone(&self) -> RunState

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<'de> Deserialize<'de> for RunState

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Display for RunState

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Serialize for RunState

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.