use super::{Abstracter, DefaultOnUninit};
use crate::handlers::common::handler::CommonHandler;
use crate::handlers::common::thread_local::{
scope_guard::ScopeGuard as GenericScopeGuard, ThreadLocal as GenericThreadLocal,
ThreadLocalDefinition,
};
use crate::handlers::common::Primary;
use crate::handlers::common::ThreadLocal as ThreadLocalScope;
use crate::handlers::on_uninit::{ErrorOnUninit, FlagOnUninit, PanicOnUninit};
use crate::handlers::uninit_error::UninitializedError;
use crate::FallibleTryDropStrategy;
use std::boxed::Box;
use std::cell::{Cell, RefCell};
use std::thread::LocalKey;
use std::{convert, thread_local};
#[cfg(feature = "ds-write")]
use crate::handlers::common::thread_local::DefaultThreadLocalDefinition;
#[cfg(feature = "ds-write")]
use crate::handlers::on_uninit::UseDefaultOnUninit;
pub type ThreadLocalPrimaryHandler<OU = DefaultOnUninit> =
CommonHandler<OU, ThreadLocalScope, Primary>;
pub static DEFAULT_THREAD_LOCAL_PRIMARY_HANDLER: ThreadLocalPrimaryHandler =
ThreadLocalPrimaryHandler::DEFAULT;
impl_fallible_try_drop_strategy_for!(ThreadLocalPrimaryHandler
where
Scope: ThreadLocalScope,
Definition: ThreadLocalDefinition
);
thread_local! {
static PRIMARY_HANDLER: RefCell<Option<Box<dyn ThreadLocalFallibleTryDropStrategy>>> = RefCell::new(None);
static LOCKED: Cell<bool> = Cell::new(false);
}
impl ThreadLocalDefinition for Primary {
const UNINITIALIZED_ERROR: &'static str =
"the thread local primary handler is not initialized yet";
const DYN: &'static str = "ThreadLocalFallibleTryDropStrategy";
type ThreadLocal = Box<dyn ThreadLocalFallibleTryDropStrategy>;
fn thread_local() -> &'static LocalKey<RefCell<Option<Self::ThreadLocal>>> {
&PRIMARY_HANDLER
}
fn locked() -> &'static LocalKey<Cell<bool>> {
&LOCKED
}
}
#[cfg(feature = "ds-write")]
impl DefaultThreadLocalDefinition for Primary {
fn default() -> Self::ThreadLocal {
let mut strategy = crate::drop_strategies::WriteDropStrategy::stderr();
strategy.prelude("error: ");
Box::new(strategy)
}
}
impl<T: ThreadLocalFallibleTryDropStrategy> From<T>
for Box<dyn ThreadLocalFallibleTryDropStrategy>
{
fn from(strategy: T) -> Self {
Box::new(strategy)
}
}
type ThreadLocal = GenericThreadLocal<Primary>;
pub type ScopeGuard = GenericScopeGuard<Primary>;
pub type BoxDynFallibleTryDropStrategy = Box<dyn ThreadLocalFallibleTryDropStrategy>;
thread_local_methods! {
ThreadLocal = ThreadLocal;
ScopeGuard = ScopeGuard;
GenericStrategy = ThreadLocalFallibleTryDropStrategy;
DynStrategy = BoxDynFallibleTryDropStrategy;
feature = "ds-write";
install;
install_dyn;
read;
try_read;
read_or_default;
write;
try_write;
write_or_default;
uninstall;
take;
replace;
replace_dyn;
scope;
scope_dyn;
}