pub struct StorageBuilder<LockingPolicyFactory>where
LockingPolicyFactory: LockingPolicyFactory,{ /* private fields */ }Expand description
Builder for Storage instances configured with a specific
LockingPolicyFactory.
§Purpose
Trading policies built on openpit typically maintain in-memory state
(reserved margin, position tracking, rate-limit counters, …) that must
be thread-safe in multi-threaded embeddings yet have zero overhead in
single-threaded ones. Rather than implementing ad hoc synchronization
in every policy, the recommended pattern is:
- Accept a
&StorageBuilder<Factory>obtained from an engine builder at policy construction time. - Call
create_for_bound_keyfor each internal data table. - Operate on the resulting
Storageinstances exclusively throughStorage::withandStorage::with_mut.
The synchronization mode is then entirely determined by the engine’s synchronization mode, not by the policy. Switching from no-sync to fully-synchronized execution only requires changing the engine builder’s sync mode - the policy logic is untouched.
§Lifetime discipline
StorageBuilder is intentionally not Clone. The intended usage
is for the engine builder to own it during the application’s
initialization phase. Application code passes
SyncedEngineBuilder::storage_builder
by shared reference to every policy that needs to create storages.
Storing a StorageBuilder inside a policy — even by value through
unsafe code — is a misuse: the builder is only meaningful during
initialization, after which the storages it produced are already live
and the builder itself carries no additional information.
§Examples
use openpit::Engine;
let engine_builder = Engine::builder::<(), (), ()>().full_sync();
let users = engine_builder.storage_builder().create_for_bound_key::<u64, String>();
let orders = engine_builder.storage_builder().create_for_bound_key::<u64, Vec<u8>>();
// `users` and `orders` are unrelated storages; locking one does
// not affect the other.
users.with_mut(1, || "alice".to_string(), |_, _| {});
orders.with_mut(42, Vec::new, |_, _| {});Implementations§
Source§impl<LockingPolicyFactory> StorageBuilder<LockingPolicyFactory>where
LockingPolicyFactory: LockingPolicyFactory,
impl<LockingPolicyFactory> StorageBuilder<LockingPolicyFactory>where
LockingPolicyFactory: LockingPolicyFactory,
Sourcepub fn create_for_bound_key<Key, Value>(
&self,
) -> Storage<Key, Value, LockingPolicyFactory::Policy>where
LockingPolicyFactory: CreateStorageFor<Key>,
pub fn create_for_bound_key<Key, Value>(
&self,
) -> Storage<Key, Value, LockingPolicyFactory::Policy>where
LockingPolicyFactory: CreateStorageFor<Key>,
Creates an empty storage configured by this builder’s policy factory.
Each call obtains a fresh LockingPolicy
instance from the factory; the resulting storage’s locks are
independent of any other storage created by this builder.
The factory must declare it supports Key by implementing
CreateStorageFor<Key>. All built-in
factories ship with the appropriate impls.
Creates an empty storage wrapped in a LockingPolicyFactory::Shared
handle.
Equivalent to Factory::new_shared(self.create_for_bound_key::<Key, Value>()).
Use this when the storage needs to be shared across clones of the
same policy.
Sourcepub fn create_with_capacity<Key, Value>(
&self,
capacity: usize,
) -> Storage<Key, Value, LockingPolicyFactory::Policy>where
LockingPolicyFactory: CreateStorageFor<Key>,
pub fn create_with_capacity<Key, Value>(
&self,
capacity: usize,
) -> Storage<Key, Value, LockingPolicyFactory::Policy>where
LockingPolicyFactory: CreateStorageFor<Key>,
Creates an empty storage with an initial capacity hint for the underlying map.
Otherwise identical to Self::create_for_bound_key; useful when the
rough number of entries is known up front and the caller wants to
avoid rehashing during the warm-up phase.