Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: make it possible to construct a GasDuration #1898

Merged
merged 1 commit into from
Sep 27, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 38 additions & 8 deletions fvm/src/gas/timer.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::fmt;
// Copyright 2021-2023 Protocol Labs
// SPDX-License-Identifier: Apache-2.0, MIT
use std::sync::Arc;
Expand All @@ -13,12 +14,38 @@ type DurationCell = Arc<OnceCell<Duration>>;
///
/// This is normally created with an empty inner, because at the point of creation
/// we don't know if tracing is on or not. It will be filled in later by `GasTimer`.
#[derive(Default, Debug, Clone)]
pub struct GasDuration(Option<DurationCell>);
#[derive(Default, Clone)]
pub struct GasDuration(GasDurationInner);

#[derive(Default, Clone)]
pub enum GasDurationInner {
#[default]
None,
Atomic(DurationCell),
Constant(Duration),
}

impl GasDuration {
pub fn get(&self) -> Option<&Duration> {
self.0.as_ref().and_then(|d| d.get())
match &self.0 {
GasDurationInner::None => None,
GasDurationInner::Atomic(d) => d.get(),
GasDurationInner::Constant(d) => Some(d),
}
}
}

impl From<Duration> for GasDuration {
fn from(d: Duration) -> Self {
GasDuration(GasDurationInner::Constant(d))
}
}

impl fmt::Debug for GasDuration {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("GasDuration")
.field(&self.get() as &dyn fmt::Debug)
.finish()
}
}

Expand Down Expand Up @@ -53,16 +80,19 @@ impl GasTimer {
/// Create a new timer that will update the elapsed time of a charge when it's finished.
///
/// As a side effect it will establish the cell in the `GasDuration`, if it has been empty so far.
///
/// When compiled in debug mode, passing a "filled" duration will panic.
pub fn new(duration: &mut GasDuration) -> Self {
assert!(duration.get().is_none(), "GasCharge::elapsed already set!");

debug_assert!(duration.get().is_none(), "GasCharge::elapsed already set!");
Stebalien marked this conversation as resolved.
Show resolved Hide resolved
let cell = match &duration.0 {
Some(cell) => cell.clone(),
None => {
GasDurationInner::None => {
let cell = DurationCell::default();
duration.0 = Some(cell.clone());
duration.0 = GasDurationInner::Atomic(cell.clone());
cell
}
GasDurationInner::Atomic(cell) if cell.get().is_none() => cell.clone(),
// If the duration has already been set, the timer is a no-op.
_ => return Self(None),
};

Self(Some(GasTimerInner {
Expand Down