nautilus_common::ffi::clock

Struct TestClock_API

Source
#[repr(C)]
pub struct TestClock_API(/* private fields */);
Expand description

C compatible Foreign Function Interface (FFI) for an underlying TestClock.

This struct wraps TestClock in a way that makes it compatible with C function calls, enabling interaction with TestClock in a C environment.

It implements the Deref trait, allowing instances of TestClock_API to be dereferenced to TestClock, providing access to TestClock’s methods without having to manually access the underlying TestClock instance.

Methods from Deref<Target = TestClock>§

Source

pub fn get_timers(&self) -> &BTreeMap<Ustr, TestTimer>

Returns a reference to the internal timers for the clock.

Source

pub fn advance_time( &mut self, to_time_ns: UnixNanos, set_time: bool, ) -> Vec<TimeEvent>

Advances the internal clock to the specified to_time_ns and optionally sets the clock to that time.

This function ensures that the clock behaves in a non-decreasing manner. If set_time is true, the internal clock will be updated to the value of to_time_ns. Otherwise, the clock will advance without explicitly setting the time.

The method processes active timers, advancing them to to_time_ns, and collects any TimeEvent objects that are triggered as a result. Only timers that are not expired are processed.

Source

pub fn advance_to_time_on_heap(&mut self, to_time_ns: UnixNanos)

Advances the internal clock to the specified to_time_ns and optionally sets the clock to that time.

Pushes the TimeEvents on the heap to ensure ordering

Note: set_time is not used but present to keep backward compatible api call

Source

pub fn match_handlers(&self, events: Vec<TimeEvent>) -> Vec<TimeEventHandlerV2>

Matches TimeEvent objects with their corresponding event handlers.

This function takes an events vector of TimeEvent objects, assumes they are already sorted by their ts_event, and matches them with the appropriate callback handler from the internal registry of callbacks. If no specific callback is found for an event, the default callback is used.

Methods from Deref<Target = AtomicTime>§

pub fn get_time_ns(&self) -> UnixNanos

Get time in nanoseconds.

  • Real-time mode returns current wall clock time since UNIX epoch (unique and monotonic).
  • Static mode returns currently stored time.

pub fn get_time_us(&self) -> u64

Get time as microseconds.

pub fn get_time_ms(&self) -> u64

Get time as milliseconds.

pub fn get_time(&self) -> f64

Get time as seconds.

pub fn set_time(&self, time: UnixNanos)

Sets new time for the clock.

pub fn increment_time(&self, delta: u64) -> UnixNanos

Increments current time with a delta and returns the updated time.

pub fn time_since_epoch(&self) -> UnixNanos

Stores and returns current time.

pub fn make_realtime(&self)

Switches the clock to real-time mode.

pub fn make_static(&self)

Switches the clock to static mode.

Methods from Deref<Target = AtomicU64>§

1.34.0 · Source

pub fn load(&self, order: Ordering) -> u64

Loads a value from the atomic integer.

load takes an Ordering argument which describes the memory ordering of this operation. Possible values are SeqCst, Acquire and Relaxed.

§Panics

Panics if order is Release or AcqRel.

§Examples
use std::sync::atomic::{AtomicU64, Ordering};

let some_var = AtomicU64::new(5);

assert_eq!(some_var.load(Ordering::Relaxed), 5);
1.34.0 · Source

pub fn store(&self, val: u64, order: Ordering)

Stores a value into the atomic integer.

store takes an Ordering argument which describes the memory ordering of this operation. Possible values are SeqCst, Release and Relaxed.

§Panics

Panics if order is Acquire or AcqRel.

§Examples
use std::sync::atomic::{AtomicU64, Ordering};

let some_var = AtomicU64::new(5);

some_var.store(10, Ordering::Relaxed);
assert_eq!(some_var.load(Ordering::Relaxed), 10);
1.34.0 · Source

pub fn swap(&self, val: u64, order: Ordering) -> u64

Stores a value into the atomic integer, returning the previous value.

swap takes an Ordering argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using Acquire makes the store part of this operation Relaxed, and using Release makes the load part Relaxed.

Note: This method is only available on platforms that support atomic operations on u64.

§Examples
use std::sync::atomic::{AtomicU64, Ordering};

let some_var = AtomicU64::new(5);

assert_eq!(some_var.swap(10, Ordering::Relaxed), 5);
1.34.0 · Source

pub fn compare_and_swap(&self, current: u64, new: u64, order: Ordering) -> u64

👎Deprecated since 1.50.0: Use compare_exchange or compare_exchange_weak instead

Stores a value into the atomic integer if the current value is the same as the current value.

The return value is always the previous value. If it is equal to current, then the value was updated.

compare_and_swap also takes an Ordering argument which describes the memory ordering of this operation. Notice that even when using AcqRel, the operation might fail and hence just perform an Acquire load, but not have Release semantics. Using Acquire makes the store part of this operation Relaxed if it happens, and using Release makes the load part Relaxed.

Note: This method is only available on platforms that support atomic operations on u64.

§Migrating to compare_exchange and compare_exchange_weak

compare_and_swap is equivalent to compare_exchange with the following mapping for memory orderings:

OriginalSuccessFailure
RelaxedRelaxedRelaxed
AcquireAcquireAcquire
ReleaseReleaseRelaxed
AcqRelAcqRelAcquire
SeqCstSeqCstSeqCst

compare_exchange_weak is allowed to fail spuriously even when the comparison succeeds, which allows the compiler to generate better assembly code when the compare and swap is used in a loop.

§Examples
use std::sync::atomic::{AtomicU64, Ordering};

let some_var = AtomicU64::new(5);

assert_eq!(some_var.compare_and_swap(5, 10, Ordering::Relaxed), 5);
assert_eq!(some_var.load(Ordering::Relaxed), 10);

assert_eq!(some_var.compare_and_swap(6, 12, Ordering::Relaxed), 10);
assert_eq!(some_var.load(Ordering::Relaxed), 10);
1.34.0 · Source

pub fn compare_exchange( &self, current: u64, new: u64, success: Ordering, failure: Ordering, ) -> Result<u64, u64>

Stores a value into the atomic integer if the current value is the same as the current value.

The return value is a result indicating whether the new value was written and containing the previous value. On success this value is guaranteed to be equal to current.

compare_exchange takes two Ordering arguments to describe the memory ordering of this operation. success describes the required ordering for the read-modify-write operation that takes place if the comparison with current succeeds. failure describes the required ordering for the load operation that takes place when the comparison fails. Using Acquire as success ordering makes the store part of this operation Relaxed, and using Release makes the successful load Relaxed. The failure ordering can only be SeqCst, Acquire or Relaxed.

Note: This method is only available on platforms that support atomic operations on u64.

§Examples
use std::sync::atomic::{AtomicU64, Ordering};

let some_var = AtomicU64::new(5);

assert_eq!(some_var.compare_exchange(5, 10,
                                     Ordering::Acquire,
                                     Ordering::Relaxed),
           Ok(5));
assert_eq!(some_var.load(Ordering::Relaxed), 10);

assert_eq!(some_var.compare_exchange(6, 12,
                                     Ordering::SeqCst,
                                     Ordering::Acquire),
           Err(10));
assert_eq!(some_var.load(Ordering::Relaxed), 10);
1.34.0 · Source

pub fn compare_exchange_weak( &self, current: u64, new: u64, success: Ordering, failure: Ordering, ) -> Result<u64, u64>

Stores a value into the atomic integer if the current value is the same as the current value.

Unlike AtomicU64::compare_exchange, this function is allowed to spuriously fail even when the comparison succeeds, which can result in more efficient code on some platforms. The return value is a result indicating whether the new value was written and containing the previous value.

compare_exchange_weak takes two Ordering arguments to describe the memory ordering of this operation. success describes the required ordering for the read-modify-write operation that takes place if the comparison with current succeeds. failure describes the required ordering for the load operation that takes place when the comparison fails. Using Acquire as success ordering makes the store part of this operation Relaxed, and using Release makes the successful load Relaxed. The failure ordering can only be SeqCst, Acquire or Relaxed.

Note: This method is only available on platforms that support atomic operations on u64.

§Examples
use std::sync::atomic::{AtomicU64, Ordering};

let val = AtomicU64::new(4);

let mut old = val.load(Ordering::Relaxed);
loop {
    let new = old * 2;
    match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
        Ok(_) => break,
        Err(x) => old = x,
    }
}
1.34.0 · Source

pub fn fetch_add(&self, val: u64, order: Ordering) -> u64

Adds to the current value, returning the previous value.

This operation wraps around on overflow.

fetch_add takes an Ordering argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using Acquire makes the store part of this operation Relaxed, and using Release makes the load part Relaxed.

Note: This method is only available on platforms that support atomic operations on u64.

§Examples
use std::sync::atomic::{AtomicU64, Ordering};

let foo = AtomicU64::new(0);
assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0);
assert_eq!(foo.load(Ordering::SeqCst), 10);
1.34.0 · Source

pub fn fetch_sub(&self, val: u64, order: Ordering) -> u64

Subtracts from the current value, returning the previous value.

This operation wraps around on overflow.

fetch_sub takes an Ordering argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using Acquire makes the store part of this operation Relaxed, and using Release makes the load part Relaxed.

Note: This method is only available on platforms that support atomic operations on u64.

§Examples
use std::sync::atomic::{AtomicU64, Ordering};

let foo = AtomicU64::new(20);
assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 20);
assert_eq!(foo.load(Ordering::SeqCst), 10);
1.34.0 · Source

pub fn fetch_and(&self, val: u64, order: Ordering) -> u64

Bitwise “and” with the current value.

Performs a bitwise “and” operation on the current value and the argument val, and sets the new value to the result.

Returns the previous value.

fetch_and takes an Ordering argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using Acquire makes the store part of this operation Relaxed, and using Release makes the load part Relaxed.

Note: This method is only available on platforms that support atomic operations on u64.

§Examples
use std::sync::atomic::{AtomicU64, Ordering};

let foo = AtomicU64::new(0b101101);
assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101);
assert_eq!(foo.load(Ordering::SeqCst), 0b100001);
1.34.0 · Source

pub fn fetch_nand(&self, val: u64, order: Ordering) -> u64

Bitwise “nand” with the current value.

Performs a bitwise “nand” operation on the current value and the argument val, and sets the new value to the result.

Returns the previous value.

fetch_nand takes an Ordering argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using Acquire makes the store part of this operation Relaxed, and using Release makes the load part Relaxed.

Note: This method is only available on platforms that support atomic operations on u64.

§Examples
use std::sync::atomic::{AtomicU64, Ordering};

let foo = AtomicU64::new(0x13);
assert_eq!(foo.fetch_nand(0x31, Ordering::SeqCst), 0x13);
assert_eq!(foo.load(Ordering::SeqCst), !(0x13 & 0x31));
1.34.0 · Source

pub fn fetch_or(&self, val: u64, order: Ordering) -> u64

Bitwise “or” with the current value.

Performs a bitwise “or” operation on the current value and the argument val, and sets the new value to the result.

Returns the previous value.

fetch_or takes an Ordering argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using Acquire makes the store part of this operation Relaxed, and using Release makes the load part Relaxed.

Note: This method is only available on platforms that support atomic operations on u64.

§Examples
use std::sync::atomic::{AtomicU64, Ordering};

let foo = AtomicU64::new(0b101101);
assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101);
assert_eq!(foo.load(Ordering::SeqCst), 0b111111);
1.34.0 · Source

pub fn fetch_xor(&self, val: u64, order: Ordering) -> u64

Bitwise “xor” with the current value.

Performs a bitwise “xor” operation on the current value and the argument val, and sets the new value to the result.

Returns the previous value.

fetch_xor takes an Ordering argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using Acquire makes the store part of this operation Relaxed, and using Release makes the load part Relaxed.

Note: This method is only available on platforms that support atomic operations on u64.

§Examples
use std::sync::atomic::{AtomicU64, Ordering};

let foo = AtomicU64::new(0b101101);
assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101);
assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
1.45.0 · Source

pub fn fetch_update<F>( &self, set_order: Ordering, fetch_order: Ordering, f: F, ) -> Result<u64, u64>
where F: FnMut(u64) -> Option<u64>,

Fetches the value, and applies a function to it that returns an optional new value. Returns a Result of Ok(previous_value) if the function returned Some(_), else Err(previous_value).

Note: This may call the function multiple times if the value has been changed from other threads in the meantime, as long as the function returns Some(_), but the function will have been applied only once to the stored value.

fetch_update takes two Ordering arguments to describe the memory ordering of this operation. The first describes the required ordering for when the operation finally succeeds while the second describes the required ordering for loads. These correspond to the success and failure orderings of AtomicU64::compare_exchange respectively.

Using Acquire as success ordering makes the store part of this operation Relaxed, and using Release makes the final successful load Relaxed. The (failed) load ordering can only be SeqCst, Acquire or Relaxed.

Note: This method is only available on platforms that support atomic operations on u64.

§Considerations

This method is not magic; it is not provided by the hardware. It is implemented in terms of AtomicU64::compare_exchange_weak, and suffers from the same drawbacks. In particular, this method will not circumvent the ABA Problem.

§Examples
use std::sync::atomic::{AtomicU64, Ordering};

let x = AtomicU64::new(7);
assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(7));
assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(7));
assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(8));
assert_eq!(x.load(Ordering::SeqCst), 9);
1.45.0 · Source

pub fn fetch_max(&self, val: u64, order: Ordering) -> u64

Maximum with the current value.

Finds the maximum of the current value and the argument val, and sets the new value to the result.

Returns the previous value.

fetch_max takes an Ordering argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using Acquire makes the store part of this operation Relaxed, and using Release makes the load part Relaxed.

Note: This method is only available on platforms that support atomic operations on u64.

§Examples
use std::sync::atomic::{AtomicU64, Ordering};

let foo = AtomicU64::new(23);
assert_eq!(foo.fetch_max(42, Ordering::SeqCst), 23);
assert_eq!(foo.load(Ordering::SeqCst), 42);

If you want to obtain the maximum value in one step, you can use the following:

use std::sync::atomic::{AtomicU64, Ordering};

let foo = AtomicU64::new(23);
let bar = 42;
let max_foo = foo.fetch_max(bar, Ordering::SeqCst).max(bar);
assert!(max_foo == 42);
1.45.0 · Source

pub fn fetch_min(&self, val: u64, order: Ordering) -> u64

Minimum with the current value.

Finds the minimum of the current value and the argument val, and sets the new value to the result.

Returns the previous value.

fetch_min takes an Ordering argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using Acquire makes the store part of this operation Relaxed, and using Release makes the load part Relaxed.

Note: This method is only available on platforms that support atomic operations on u64.

§Examples
use std::sync::atomic::{AtomicU64, Ordering};

let foo = AtomicU64::new(23);
assert_eq!(foo.fetch_min(42, Ordering::Relaxed), 23);
assert_eq!(foo.load(Ordering::Relaxed), 23);
assert_eq!(foo.fetch_min(22, Ordering::Relaxed), 23);
assert_eq!(foo.load(Ordering::Relaxed), 22);

If you want to obtain the minimum value in one step, you can use the following:

use std::sync::atomic::{AtomicU64, Ordering};

let foo = AtomicU64::new(23);
let bar = 12;
let min_foo = foo.fetch_min(bar, Ordering::SeqCst).min(bar);
assert_eq!(min_foo, 12);
1.70.0 · Source

pub fn as_ptr(&self) -> *mut u64

Returns a mutable pointer to the underlying integer.

Doing non-atomic reads and writes on the resulting integer can be a data race. This method is mostly useful for FFI, where the function signature may use *mut u64 instead of &AtomicU64.

Returning an *mut pointer from a shared reference to this atomic is safe because the atomic types work with interior mutability. All modifications of an atomic change the value through a shared reference, and can do so safely as long as they use atomic operations. Any use of the returned raw pointer requires an unsafe block and still has to uphold the same restriction: operations on it must be atomic.

§Examples
use std::sync::atomic::AtomicU64;

extern "C" {
    fn my_atomic_op(arg: *mut u64);
}

let atomic = AtomicU64::new(1);

// SAFETY: Safe as long as `my_atomic_op` is atomic.
unsafe {
    my_atomic_op(atomic.as_ptr());
}

Trait Implementations§

Source§

impl Deref for TestClock_API

Source§

type Target = TestClock

The resulting type after dereferencing.
Source§

fn deref(&self) -> &Self::Target

Dereferences the value.
Source§

impl DerefMut for TestClock_API

Source§

fn deref_mut(&mut self) -> &mut Self::Target

Mutably dereferences the value.

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> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
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
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
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.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

impl<T> Ungil for T
where T: Send,