Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
teh-cmc committed May 11, 2023
1 parent 6fffd19 commit 883964d
Show file tree
Hide file tree
Showing 33 changed files with 1,464 additions and 733 deletions.
7 changes: 1 addition & 6 deletions crates/re_sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ demo = []
## Add support for some math operations using [`glam`](https://crates.io/crates/glam/).
glam = ["re_log_types/glam"]

## Add the `global_session` method.
global_session = ["dep:once_cell"]

## Integration with the [`image`](https://crates.io/crates/image/) crate.
image = ["re_log_types/image"]

Expand All @@ -44,12 +41,10 @@ re_sdk_comms = { workspace = true, features = ["client"] }
ahash.workspace = true
crossbeam.workspace = true
document-features = "0.2"
once_cell = "1.12"
parking_lot.workspace = true
thiserror.workspace = true

# Optional dependencies:
once_cell = { version = "1.12", optional = true }


[dev-dependencies]
arrow2_convert.workspace = true
Expand Down
206 changes: 206 additions & 0 deletions crates/re_sdk/src/global.rs
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);
});
}
},
}
}
}
2 changes: 2 additions & 0 deletions crates/re_sdk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
// ----------------
// Private modules:

mod global; // TODO
mod log_sink;
mod msg_sender;
mod recording_stream;

// -------------
// Public items:

pub use self::global::RecordingType;
pub use self::msg_sender::{MsgSender, MsgSenderError};
pub use self::recording_stream::{RecordingStream, RecordingStreamBuilder};

Expand Down
4 changes: 0 additions & 4 deletions crates/rerun/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,6 @@ demo = ["re_sdk?/demo"]
## Only relevant if feature `sdk` is enabled.
glam = ["re_sdk?/glam"]

## Add the `global_session` method.
## Only makes sense together with the `sdk` feature.
global_session = ["re_sdk?/global_session"]

## Integration with the [`image`](https://crates.io/crates/image/) crate.
image = ["re_log_types/image"]

Expand Down
Loading

0 comments on commit 883964d

Please sign in to comment.