snarkos-utilities 4.6.2

Utilities for a decentralized operating system
Documentation
// Copyright (c) 2019-2026 Provable Inc.
// This file is part of the snarkOS library.

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:

// http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use anyhow::{Result, bail};
#[cfg(feature = "locktick")]
use locktick::{LockGuard, parking_lot::RwLock};
#[cfg(not(feature = "locktick"))]
use parking_lot::RwLock;
use parking_lot::RwLockReadGuard;

/// Helper struct to hold a reference to a callback struct.
pub struct CallbackHandle<C: Clone + Send + Sync> {
    callback: RwLock<Option<C>>,
}

impl<C: Send + Sync + Clone> Default for CallbackHandle<C> {
    /// By default, the handle holds no callback.
    fn default() -> Self {
        Self { callback: RwLock::new(None) }
    }
}

impl<C: Send + Sync + Clone> CallbackHandle<C> {
    /// Set a callback. Returns an error if a callback was already set.
    pub fn set(&self, callback: C) -> Result<()> {
        let prev = self.callback.write().replace(callback);

        if prev.is_some() {
            bail!("Callback was already set");
        }

        Ok(())
    }

    /// Get a cloned copy of the callback.
    /// Useful when the callback will be used across await-boundaries.
    #[inline]
    pub fn get(&self) -> Option<C> {
        self.callback.read().clone()
    }

    /// Get reference to the callback.
    /// Cannot be shared across await-boundaries.
    #[cfg(feature = "locktick")]
    #[inline]
    pub fn get_ref(&self) -> LockGuard<RwLockReadGuard<'_, Option<C>>> {
        self.callback.read()
    }

    /// Get reference to the callback.
    /// Cannot be shared across await-boundaries.
    #[cfg(not(feature = "locktick"))]
    #[inline]
    pub fn get_ref(&self) -> RwLockReadGuard<'_, Option<C>> {
        self.callback.read()
    }

    /// Remove the callback.
    /// Used during shutdown to resolve circular dependencies between types.
    pub fn clear(&self) {
        let _ = self.callback.write().take();
    }
}