#![allow(
clippy::unwrap_used,
clippy::expect_used,
clippy::print_stdout,
clippy::panic
)]
#[cfg(all(feature = "shm", target_os = "linux"))]
fn main() {
use std::io::Write;
use tf_tree::{AttachMode, Capacity, EdgeCfg, InterpPolicy, Stamp, TreeBuilder};
use tf_tree_ipc::CreatePolicy;
fn say(line: &str) {
println!("{line}");
let _ = std::io::stdout().flush();
}
fn layout() -> TreeBuilder {
TreeBuilder::new()
.default_interp(InterpPolicy::LerpSlerp)
.dynamic_edge("map", "base", EdgeCfg::new(Capacity::slots(64)))
.dynamic_edge("base", "cam", EdgeCfg::new(Capacity::slots(64)))
}
fn render(tree: &tf_tree::Tree, stamp: i64) -> String {
let g = tree.guard();
let target = tree.frame("map").unwrap();
let source = tree.frame("base").unwrap();
let plan = tree.plan(target, source).unwrap();
let iso = plan
.at(&g, Stamp::<tf_tree::SystemDomain>::from_nanos(stamp))
.unwrap();
let b = iso.to_bits();
b.iter()
.map(|w| format!("{w:016x}"))
.collect::<Vec<_>>()
.join(":")
}
let mode = std::env::args().nth(1).unwrap_or_default();
match mode.as_str() {
"own" => {
let tree = tf_tree::Open::new()
.mode(AttachMode::ReadWrite)
.create(CreatePolicy::IfAbsent)
.layout_if_creating(layout())
.open()
.expect("create the arena");
let child = tree.frame("base").unwrap();
let parent = tree.frame("map").unwrap();
let pubr = tree.claim(child, parent).expect("claim");
let iso = tf_tree::exp_se3([1.0, 2.0, 3.0, 0.1, 0.2, 0.3]);
pubr.push(1_000, &iso).expect("push");
pubr.push(2_000, &iso).expect("push");
say(&format!("owning {}", render(&tree, 1_500)));
loop {
std::thread::park();
}
}
"join" | "join-rw" => {
let mode = if mode == "join-rw" {
AttachMode::ReadWrite
} else {
AttachMode::ReadOnly
};
match tf_tree::Open::new()
.mode(mode)
.create(CreatePolicy::Never)
.timeout(std::time::Duration::from_millis(500))
.open()
{
Ok(tree) => {
say(&format!("joined {}", render(&tree, 1_500)));
loop {
std::thread::park();
}
}
Err(e) => say(&format!("error {e}")),
}
}
"open-free" => {
match tf_tree::open() {
Ok(tree) => {
say(&format!("joined {}", render(&tree, 1_500)));
loop {
std::thread::park();
}
}
Err(e) => say(&format!("error {e}")),
};
}
"own-headroom" => {
let tree = tf_tree::Open::new()
.mode(AttachMode::ReadWrite)
.create(CreatePolicy::IfAbsent)
.layout_if_creating(layout().frame_headroom(4))
.open()
.expect("create the arena");
say("owning");
let mut line = String::new();
let _ = std::io::BufRead::read_line(&mut std::io::stdin().lock(), &mut line);
let id = tree.frame("late_frame").expect("intern the late frame");
say(&format!("interned {}", id.get()));
loop {
std::thread::park();
}
}
"own-claiming" => {
let tree = tf_tree::Open::new()
.mode(AttachMode::ReadWrite)
.create(CreatePolicy::IfAbsent)
.layout_if_creating(layout())
.open()
.expect("create the arena");
let child = tree.frame("base").unwrap();
let parent = tree.frame("map").unwrap();
let w = tree.claim(child, parent).expect("claim");
say(&format!("claimed {}", w.edge().get()));
loop {
std::thread::park();
}
}
"join-claiming" => {
let tree = tf_tree::Open::new()
.mode(AttachMode::ReadWrite)
.create(CreatePolicy::Never)
.timeout(std::time::Duration::from_millis(500))
.open()
.expect("join");
let child = tree.frame("cam").unwrap();
let parent = tree.frame("base").unwrap();
let _held = match tree.claim(child, parent) {
Ok(w) => {
say(&format!("claimed {}", w.edge().get()));
Some(w)
}
Err(e) => {
say(&format!("refused {e:?}"));
None
}
};
loop {
std::thread::park();
}
}
"own-reap" => {
let tree = tf_tree::Open::new()
.mode(AttachMode::ReadWrite)
.create(CreatePolicy::IfAbsent)
.layout_if_creating(layout())
.open()
.expect("create");
let child = tree.frame("base").unwrap();
let parent = tree.frame("map").unwrap();
let w = tree.claim(child, parent).expect("claim");
say("claimed");
let mut line = String::new();
let _ = std::io::BufRead::read_line(&mut std::io::stdin().lock(), &mut line);
let n = tree.reap_dead();
let iso = tf_tree::exp_se3([0.0, 0.0, 0.0, 1.0, 0.0, 0.0]);
let still_ours = w.push(9_000, &iso).is_ok();
say(&format!("reaped {n} still_ours {still_ours}"));
loop {
std::thread::park();
}
}
"join-reparent" => {
let tree = tf_tree::Open::new()
.mode(AttachMode::ReadWrite)
.create(CreatePolicy::Never)
.timeout(std::time::Duration::from_millis(500))
.open()
.expect("join");
say("joined");
let mut line = String::new();
std::io::BufRead::read_line(&mut std::io::stdin().lock(), &mut line).expect("read");
let cam = tree.frame("cam").unwrap();
let map = tree.frame("map").unwrap();
match tree.reparent(cam, map) {
Ok(()) => say("reparented"),
Err(e) => say(&format!("refused {e:?}")),
}
loop {
std::thread::park();
}
}
"join-sweep" => {
let tree = tf_tree::Open::new()
.mode(AttachMode::ReadWrite)
.create(CreatePolicy::Never)
.timeout(std::time::Duration::from_secs(5))
.open()
.expect("join");
say(&format!("joined {}", tree.participant_slot()));
let mut line = String::new();
let _ = std::io::BufRead::read_line(&mut std::io::stdin().lock(), &mut line);
let n = tree.reap_participants();
say(&format!("swept {n}"));
}
"hold-topo" => {
let path = std::env::args().nth(2).expect("lock file path");
let lock = tf_tree_ipc::LockFile::open(std::path::Path::new(&path))
.expect("open the lock file");
match lock.try_take_topology().expect("fcntl the topology byte") {
tf_tree_ipc::LockAttempt::Acquired => say("holding-topo"),
tf_tree_ipc::LockAttempt::Contended => say("topo-contended"),
}
loop {
std::thread::park();
}
}
"peer-alive" => {
let slot: u32 = std::env::args()
.nth(2)
.and_then(|s| s.parse().ok())
.expect("slot");
let tree = tf_tree::Open::new()
.create(CreatePolicy::Never)
.timeout(std::time::Duration::from_millis(500))
.open()
.expect("join");
say(&format!("alive {}", tree.participant_alive(slot)));
loop {
std::thread::park();
}
}
"join-heir" => {
let tree = tf_tree::Open::new()
.mode(AttachMode::ReadWrite)
.create(CreatePolicy::Never)
.open()
.expect("join");
say(&format!("joined {}", tree.participant_slot()));
let stdin = std::io::stdin();
let mut line = String::new();
while std::io::BufRead::read_line(&mut stdin.lock(), &mut line).unwrap_or(0) > 0 {
line.clear();
let lost = tree.owner_lost();
let outcome = match tree.inherit_ownership() {
Ok(o) => format!("{o:?}"),
Err(e) => format!("error {e}"),
};
say(&format!("{lost} {outcome} {}", tree.participant_slot()));
}
loop {
std::thread::park();
}
}
#[cfg(feature = "unstable")]
"join-rw-report" => {
let tree = tf_tree::Open::new()
.mode(AttachMode::ReadWrite)
.create(CreatePolicy::Never)
.timeout(std::time::Duration::from_millis(500))
.open()
.expect("join");
say("joined");
let stdin = std::io::stdin();
let mut line = String::new();
while std::io::BufRead::read_line(&mut stdin.lock(), &mut line).unwrap_or(0) > 0 {
let slot: u32 = line.trim().parse().expect("a slot number per line");
line.clear();
let view = tree.arena_view();
let rec = view.participants().get(slot).expect("slot in range");
let word = rec.state.load(std::sync::atomic::Ordering::Acquire);
let state = match tf_tree_core::participant::state_of(word) {
tf_tree_core::participant::LIVE => "live",
tf_tree_core::participant::RESERVED => "reserved",
_ => "free",
};
say(&format!(
"slot {slot} state {state} word {word:#x} pid {} alive {}",
rec.pid.load(std::sync::atomic::Ordering::Relaxed),
tree.participant_alive(slot),
));
}
loop {
std::thread::park();
}
}
other => panic!("tf_tree_rendezvous_child: unknown mode {other}"),
}
}
#[cfg(not(all(feature = "shm", target_os = "linux")))]
fn main() {}