pub struct SchedulingStateMachine { /* private fields */ }
Expand description
A high-level struct
, managing the overall scheduling of tasks, to be used by
solana-unified-scheduler-pool
.
Implementations§
Source§impl SchedulingStateMachine
impl SchedulingStateMachine
pub fn has_no_running_task(&self) -> bool
pub fn has_no_active_task(&self) -> bool
pub fn has_unblocked_task(&self) -> bool
pub fn has_runnable_task(&self) -> bool
pub fn unblocked_task_queue_count(&self) -> usize
Sourcepub fn schedule_task(&mut self, task: Task) -> Option<Task>
pub fn schedule_task(&mut self, task: Task) -> Option<Task>
Schedules given task
, returning it if successful.
Returns Some(task)
if it’s immediately scheduled. Otherwise, returns None
,
indicating the scheduled task is blocked currently.
Note that this function takes ownership of the task to allow for future optimizations.
Sourcepub fn buffer_task(&mut self, task: Task)
pub fn buffer_task(&mut self, task: Task)
Adds given task
to internal buffer, even if it’s immediately schedulable otherwise.
Put differently, buffering means to force the task to be blocked unconditionally after normal scheduling processing.
Thus, the task is internally retained inside this SchedulingStateMachine
, whether the
task is blocked or not. Eventually, the buffered task will be returned by one of later
invocations schedule_next_unblocked_task()
.
Note that this function takes ownership of the task to allow for future optimizations.
Sourcepub fn schedule_or_buffer_task(
&mut self,
task: Task,
force_buffering: bool,
) -> Option<Task>
pub fn schedule_or_buffer_task( &mut self, task: Task, force_buffering: bool, ) -> Option<Task>
Schedules or buffers given task
, returning successful one unless buffering is forced.
Refer to schedule_task()
and
buffer_task()
for the difference between scheduling and
buffering respectively.
Note that this function takes ownership of the task to allow for future optimizations.
pub fn schedule_next_unblocked_task(&mut self) -> Option<Task>
Sourcepub fn deschedule_task(&mut self, task: &Task)
pub fn deschedule_task(&mut self, task: &Task)
Deschedules given scheduled task
.
This must be called exactly once for all scheduled tasks to uphold both
SchedulingStateMachine
and UsageQueue
internal state consistency at any given moment of
time. It’s serious logic error to call this twice with the same task or none at all after
scheduling. Similarly, calling this with not scheduled task is also forbidden.
Note that this function intentionally doesn’t take ownership of the task to avoid dropping
tasks inside SchedulingStateMachine
to provide an offloading-based optimization
opportunity for callers.
Sourcepub fn create_task(
transaction: RuntimeTransaction<SanitizedTransaction>,
index: usize,
usage_queue_loader: &mut impl FnMut(Pubkey) -> UsageQueue,
) -> Task
pub fn create_task( transaction: RuntimeTransaction<SanitizedTransaction>, index: usize, usage_queue_loader: &mut impl FnMut(Pubkey) -> UsageQueue, ) -> Task
Creates a new task with RuntimeTransaction<SanitizedTransaction>
with all of
its corresponding UsageQueue
s preloaded.
Closure (usage_queue_loader
) is used to delegate the (possibly multi-threaded)
implementation of UsageQueue
look-up by pubkey
to callers. It’s the
caller’s responsibility to ensure the same instance is returned from the closure, given a
particular pubkey.
Closure is used here to delegate the responsibility of primary ownership of UsageQueue
(and caching/pruning if any) to the caller. SchedulingStateMachine
guarantees that all of
shared owndership of UsageQueue
s are released and UsageQueue state is identical to just
after created, if has_no_active_task()
is true
. Also note that this is desired for
separation of concern.
pub fn create_block_production_task( transaction: RuntimeTransaction<SanitizedTransaction>, index: usize, consumed_block_size: BlockSize, usage_queue_loader: &mut impl FnMut(Pubkey) -> UsageQueue, ) -> Task
Sourcepub fn reinitialize(&mut self)
pub fn reinitialize(&mut self)
Rewind the inactive state machine to be initialized
This isn’t called reset to indicate this isn’t safe to call this at any given moment.
This panics if the state machine hasn’t properly been finished (i.e. there should be no
active task) to uphold invariants of UsageQueue
s.
This method is intended to reuse SchedulingStateMachine instance (to avoid its unsafe
constructor
as much as possible) and its (possibly cached) associated UsageQueue
s for processing
other slots.
There’s a related method called clear_and_reinitialize()
.
Sourcepub fn clear_and_reinitialize(&mut self) -> usize
pub fn clear_and_reinitialize(&mut self) -> usize
Clear all buffered tasks and immediately rewind the state machine to be initialized
This method may panic if there are tasks which has been scheduled but hasn’t been
descheduled yet (called active tasks). This is due to the invocation of
reinitialize()
at last. On the other hand, it’s guaranteed not to
panic otherwise. That’s because the first clearing step effectively relaxes the runtime
invariant of reinitialize()
by making the state machine inactive beforehand. After a
successful operation, this method returns the number of cleared tasks.
Somewhat surprisingly, the clearing logic is same as the normal (de-)scheduling operation
because it is still the fastest way to just clear all tasks, under the consideration of
potential later use of UsageQueue
s. That’s because state_machine
doesn’t maintain the
global list of tasks. Maintaining such one would incur a needless overhead on scheduling,
which isn’t strictly needed otherwise.
Moreover, the descheduling operation is rather heavily optimized to begin with. All collection ops are just O(1) over total N of addresses accessed by all active tasks with no amortized mem ops.
Whatever the algorithm is chosen, the ultimate goal of this operation is to clear all usage
queues. Toward to that end, one may create a temporary hash set over UsageQueue
s on the
fly alternatively. However, that would be costlier than the above usual descheduling
approach due to extra mem ops and many lookups/insertions.
Sourcepub unsafe fn exclusively_initialize_current_thread_for_scheduling(
max_running_task_count: Option<usize>,
) -> Self
pub unsafe fn exclusively_initialize_current_thread_for_scheduling( max_running_task_count: Option<usize>, ) -> Self
Creates a new instance of SchedulingStateMachine
with its unsafe
fields created as
well, thus carrying over unsafe
.
§Safety
Call this exactly once for each thread. See [TokenCell
] for details.
Auto Trait Implementations§
impl Freeze for SchedulingStateMachine
impl !RefUnwindSafe for SchedulingStateMachine
impl !Send for SchedulingStateMachine
impl !Sync for SchedulingStateMachine
impl Unpin for SchedulingStateMachine
impl !UnwindSafe for SchedulingStateMachine
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> 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