| // Copyright 2019 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| use { |
| crate::work_scheduler::dispatcher::Dispatcher, |
| fidl_fuchsia_component as fcomponent, fidl_fuchsia_sys2 as fsys, |
| std::{cmp::Ordering, fmt, sync::Arc}, |
| }; |
| |
| /// `WorkItem` is a single item in the ordered-by-deadline collection maintained by `WorkScheduler`. |
| #[derive(Clone, Eq)] |
| pub(super) struct WorkItem { |
| /// A reference-counted pointer to the `WorkItem`'s `Dispatcher`. This is retained by the |
| /// `WorkItem` so that `Dispatcher` implementations can perform cleanup work when they are no |
| /// longer referenced by outstanding `WorkItem`s. |
| pub(super) dispatcher: Arc<dyn Dispatcher>, |
| /// Unique identifier for this unit of work **relative to others with the same |
| /// `dispatcher`**. |
| pub(super) id: String, |
| /// Next deadline for this unit of work, in monotonic time. |
| pub(super) next_deadline_monotonic: i64, |
| /// Period between repeating this unit of work (if any), measure in nanoseconds. |
| pub(super) period: Option<i64>, |
| } |
| |
| impl fmt::Debug for WorkItem { |
| fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
| fmt.debug_struct("WorkItem") |
| .field("id", &self.id) |
| .field("next_deadline_monotonic", &self.next_deadline_monotonic) |
| .field("period", &self.period) |
| .finish() |
| } |
| } |
| |
| /// WorkItem default equality: identical `dispatcher` and `id`. |
| impl PartialEq for WorkItem { |
| fn eq(&self, other: &Self) -> bool { |
| self.id == other.id && self.dispatcher.abs_moniker() == other.dispatcher.abs_moniker() |
| } |
| } |
| |
| impl WorkItem { |
| pub(super) fn new( |
| dispatcher: Arc<dyn Dispatcher>, |
| id: &str, |
| next_deadline_monotonic: i64, |
| period: Option<i64>, |
| ) -> Self { |
| WorkItem { dispatcher, id: id.to_string(), next_deadline_monotonic, period } |
| } |
| |
| /// Produce a canonical `WorkItem` from its identifying information: `abs_moniker` + `id`. Note |
| /// that other fields are ignored in equality testing. |
| pub(super) fn new_by_identity(dispatcher: Arc<dyn Dispatcher>, id: &str) -> Self { |
| WorkItem { dispatcher, id: id.to_string(), next_deadline_monotonic: 0, period: None } |
| } |
| |
| /// Attempt to unpack identifying info (`abs_moniker`, `id`) + `WorkRequest` into a `WorkItem`. |
| /// Errors: |
| /// - INVALID_ARGUMENTS: Missing or invalid `work_request.start` value. |
| pub(super) fn try_new( |
| dispatcher: Arc<dyn Dispatcher>, |
| id: &str, |
| work_request: &fsys::WorkRequest, |
| ) -> Result<Self, fcomponent::Error> { |
| let next_deadline_monotonic = match &work_request.start { |
| None => Err(fcomponent::Error::InvalidArguments), |
| Some(start) => match start { |
| fsys::Start::MonotonicTime(monotonic_time) => Ok(monotonic_time), |
| _ => Err(fcomponent::Error::InvalidArguments), |
| }, |
| }?; |
| Ok(WorkItem::new(dispatcher, id, *next_deadline_monotonic, work_request.period)) |
| } |
| |
| pub(super) fn deadline_order(left: &Self, right: &Self) -> Ordering { |
| left.next_deadline_monotonic.cmp(&right.next_deadline_monotonic) |
| } |
| } |