-
Notifications
You must be signed in to change notification settings - Fork 373
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
34 changed files
with
1,490 additions
and
733 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,206 @@ | ||
use std::cell::RefCell; | ||
|
||
use once_cell::sync::OnceCell; | ||
use parking_lot::Mutex; | ||
|
||
use crate::RecordingStream; | ||
|
||
// --- | ||
|
||
// TODO: use Jeremy's | ||
#[derive(Clone, Copy, Debug, PartialEq, Eq)] | ||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] | ||
pub enum RecordingType { | ||
Unknown, | ||
Data, | ||
Blueprint, | ||
} | ||
|
||
impl std::fmt::Display for RecordingType { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
f.write_str(match self { | ||
RecordingType::Unknown => "unknown", | ||
RecordingType::Data => "data", | ||
RecordingType::Blueprint => "blueprint", | ||
}) | ||
} | ||
} | ||
|
||
#[derive(Clone, Copy, Debug, PartialEq, Eq)] | ||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] | ||
enum RecordingScope { | ||
Global, | ||
ThreadLocal, | ||
} | ||
|
||
impl std::fmt::Display for RecordingScope { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
f.write_str(match self { | ||
RecordingScope::Global => "global", | ||
RecordingScope::ThreadLocal => "thread-local", | ||
}) | ||
} | ||
} | ||
|
||
// --- | ||
|
||
// TODO: RwLock...? | ||
|
||
static GLOBAL_DATA_RECORDING: OnceCell<Mutex<Option<RecordingStream>>> = OnceCell::new(); | ||
thread_local! { | ||
static LOCAL_DATA_RECORDING: RefCell<Option<RecordingStream>> = RefCell::new(None); | ||
} | ||
|
||
static GLOBAL_BLUEPRINT_RECORDING: OnceCell<Mutex<Option<RecordingStream>>> = OnceCell::new(); | ||
thread_local! { | ||
static LOCAL_BLUEPRINT_RECORDING: RefCell<Option<RecordingStream>> = RefCell::new(None); | ||
} | ||
|
||
impl RecordingStream { | ||
// --- Global --- | ||
|
||
/// Returns the currently active recording of the specified type in the global scope, if any. | ||
#[inline] | ||
pub fn global(which: RecordingType) -> Option<RecordingStream> { | ||
Self::get(RecordingScope::Global, which, None) | ||
} | ||
|
||
/// Returns the currently active recording of the specified type in the global scope, if any; | ||
/// fallbacks to the specified recording otherwise. | ||
#[inline] | ||
pub fn global_or(which: RecordingType, fallback: RecordingStream) -> RecordingStream { | ||
// NOTE: unwrap cannot fail, fallback is mandatory. | ||
Self::get(RecordingScope::Global, which, fallback.into()).unwrap() | ||
} | ||
|
||
/// Returns the currently active recording of the specified type in the global scope, if any; | ||
/// fallbacks to the specified recording otherwise, if any. | ||
#[inline] | ||
pub fn global_or_opt( | ||
which: RecordingType, | ||
fallback: Option<RecordingStream>, | ||
) -> Option<RecordingStream> { | ||
Self::get(RecordingScope::Global, which, fallback) | ||
} | ||
|
||
/// Replaces the currently active recording in the global scope with the specified one. | ||
#[inline] | ||
pub fn set_global(which: RecordingType, rec: RecordingStream) { | ||
Self::set(RecordingScope::Global, which, rec); | ||
} | ||
|
||
// --- Thread local --- | ||
|
||
/// Returns the currently active recording of the specified type in the thread-local scope, | ||
/// if any. | ||
#[inline] | ||
pub fn thread_local(which: RecordingType) -> Option<RecordingStream> { | ||
Self::get(RecordingScope::ThreadLocal, which, None) | ||
} | ||
|
||
/// Returns the currently active recording of the specified type in the thread-local scope, | ||
/// if any; fallbacks to the specified recording otherwise. | ||
#[inline] | ||
pub fn thread_local_or(which: RecordingType, fallback: RecordingStream) -> RecordingStream { | ||
// NOTE: unwrap cannot fail, fallback is mandatory. | ||
Self::get(RecordingScope::ThreadLocal, which, fallback.into()).unwrap() | ||
} | ||
|
||
/// Returns the currently active recording of the specified type in the thread-local scope, | ||
/// if any; fallbacks to the specified recording otherwise, if any. | ||
#[inline] | ||
pub fn thread_local_or_opt( | ||
which: RecordingType, | ||
fallback: Option<RecordingStream>, | ||
) -> Option<RecordingStream> { | ||
Self::get(RecordingScope::ThreadLocal, which, fallback) | ||
} | ||
|
||
/// Replaces the currently active recording in the thread-local scope with the specified one. | ||
#[inline] | ||
pub fn set_thread_local(which: RecordingType, rec: RecordingStream) { | ||
Self::set(RecordingScope::ThreadLocal, which, rec); | ||
} | ||
|
||
// --- Internal helpers --- | ||
|
||
fn get( | ||
scope: RecordingScope, | ||
which: RecordingType, | ||
fallback: Option<RecordingStream>, | ||
) -> Option<RecordingStream> { | ||
let rec = match which { | ||
RecordingType::Unknown => None, | ||
RecordingType::Data => match scope { | ||
RecordingScope::Global => GLOBAL_DATA_RECORDING | ||
.get_or_init(Default::default) | ||
.lock() | ||
.clone(), | ||
RecordingScope::ThreadLocal => { | ||
LOCAL_DATA_RECORDING.with(|rec| rec.borrow().clone()) | ||
} | ||
}, | ||
RecordingType::Blueprint => match scope { | ||
RecordingScope::Global => GLOBAL_BLUEPRINT_RECORDING | ||
.get_or_init(Default::default) | ||
.lock() | ||
.clone(), | ||
RecordingScope::ThreadLocal => { | ||
LOCAL_BLUEPRINT_RECORDING.with(|rec| rec.borrow().clone()) | ||
} | ||
}, | ||
}; | ||
|
||
let rec = rec.or(fallback); | ||
|
||
if rec.is_none() { | ||
match scope { | ||
RecordingScope::Global => { | ||
re_log::warn_once!( | ||
"There is no currently active {scope} {which} recording available: \ | ||
have you called `set_global()` first?" | ||
); | ||
} | ||
RecordingScope::ThreadLocal => { | ||
re_log::warn_once!( | ||
"There is no currently active {scope} {which} recording available \ | ||
for the current thread ({:?}): have you called `set_global()` first?", | ||
std::thread::current().id(), | ||
); | ||
} | ||
} | ||
} | ||
|
||
rec | ||
} | ||
|
||
fn set(scope: RecordingScope, which: RecordingType, rec: RecordingStream) { | ||
match which { | ||
RecordingType::Unknown => {} | ||
RecordingType::Data => match scope { | ||
RecordingScope::Global => { | ||
*GLOBAL_DATA_RECORDING.get_or_init(Default::default).lock() = Some(rec); | ||
} | ||
RecordingScope::ThreadLocal => { | ||
LOCAL_DATA_RECORDING.with(|cell| { | ||
let mut cell = cell.borrow_mut(); | ||
*cell = Some(rec); | ||
}); | ||
} | ||
}, | ||
RecordingType::Blueprint => match scope { | ||
RecordingScope::Global => { | ||
*GLOBAL_BLUEPRINT_RECORDING | ||
.get_or_init(Default::default) | ||
.lock() = Some(rec); | ||
} | ||
RecordingScope::ThreadLocal => { | ||
LOCAL_BLUEPRINT_RECORDING.with(|cell| { | ||
let mut cell = cell.borrow_mut(); | ||
*cell = Some(rec); | ||
}); | ||
} | ||
}, | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.