Skip to content

Commit

Permalink
improve usability of registry (#12)
Browse files Browse the repository at this point in the history
  • Loading branch information
BugenZhao authored Mar 28, 2024
1 parent d999470 commit c58eaf5
Show file tree
Hide file tree
Showing 9 changed files with 256 additions and 51 deletions.
14 changes: 8 additions & 6 deletions benches/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,15 @@ async fn test_baseline() {
}

async fn spawn_many(size: usize) {
let mut root = Registry::new(Config::default());
let registry = Registry::new(Config::default());
let mut handles = vec![];
for i in 0..size {
let task = async {
tokio::time::sleep(Duration::from_millis(10)).await;
};
handles.push(tokio::spawn(root.register(i, "new_task").instrument(task)));
handles.push(tokio::spawn(
registry.register(i, "new_task").instrument(task),
));
}
futures::future::try_join_all(handles)
.await
Expand All @@ -102,9 +104,9 @@ fn bench_basic(c: &mut Criterion) {
c.bench_function("basic", |b| {
b.to_async(runtime()).iter(|| async {
let config = ConfigBuilder::default().verbose(false).build().unwrap();
let mut mgr = Registry::new(config);
let registry = Registry::new(config);

let root = mgr.register(233, "root");
let root = registry.register(233, "root");
root.instrument(test()).await;
})
});
Expand All @@ -114,9 +116,9 @@ fn bench_basic_baseline(c: &mut Criterion) {
c.bench_function("basic_baseline", |b| {
b.to_async(runtime()).iter(|| async {
let config = ConfigBuilder::default().verbose(false).build().unwrap();
let mut mgr = Registry::new(config);
let registry = Registry::new(config);

let root = mgr.register(233, "root");
let root = registry.register(233, "root");
black_box(root);
test_baseline().await
})
Expand Down
4 changes: 2 additions & 2 deletions examples/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ async fn foo() {

#[tokio::main]
async fn main() {
let mut registry = Registry::new(Config::default());
let registry = Registry::new(Config::default());
let root = registry.register((), "foo");
tokio::spawn(root.instrument(foo()));

sleep(Duration::from_secs(1)).await;
let tree = registry.get(&()).unwrap().to_string();
let tree = registry.get(()).unwrap().to_string();

// foo [1.006s]
// bar [1.006s]
Expand Down
2 changes: 1 addition & 1 deletion examples/detach.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ async fn work(rx: Receiver<()>) {

#[tokio::main]
async fn main() {
let mut registry = Registry::new(Config::default());
let registry = Registry::new(Config::default());
let root = registry.register((), "work");
let (tx, rx) = oneshot::channel();
tokio::spawn(root.instrument(work(rx)));
Expand Down
10 changes: 7 additions & 3 deletions examples/multiple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ async fn foo() {

#[tokio::main]
async fn main() {
let mut registry = Registry::new(Config::default());
for i in 0..3 {
let registry = Registry::new(Config::default());
for i in 0_i32..3 {
let root = registry.register(i, format!("actor {i}"));
tokio::spawn(root.instrument(work(i)));
}
Expand All @@ -50,7 +50,11 @@ async fn main() {
// actor 2 [1.007s]
// actor work 2 [1.007s]
// pending [1.007s]
for (_, tree) in registry.iter().sorted_by_key(|(i, _)| *i) {
for (_, tree) in registry
.collect::<i32>()
.into_iter()
.sorted_by_key(|(i, _)| *i)
{
println!("{tree}");
}
}
2 changes: 1 addition & 1 deletion examples/verbose.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ async fn foo() {

async fn work(verbose: bool) -> String {
let config = ConfigBuilder::default().verbose(verbose).build().unwrap();
let mut registry = Registry::new(config);
let registry = Registry::new(config);
let root = registry.register((), "foo");
tokio::spawn(root.instrument(foo()));

Expand Down
7 changes: 6 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,21 @@
// See the License for the specific language governing permissions and
// limitations under the License.

//! Instrument await-tree for actor-based applications.
#![forbid(missing_docs)]

use std::future::Future;

mod context;
mod future;
mod obj_utils;
mod registry;

pub use context::{current_tree, TreeContext};
use flexstr::SharedStr;
pub use future::Instrumented;
pub use registry::{Config, ConfigBuilder, ConfigBuilderError, Registry, TreeRoot};
pub use registry::{AnyKey, Config, ConfigBuilder, ConfigBuilderError, Key, Registry, TreeRoot};

/// A cheaply cloneable span in the await-tree.
#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord)]
Expand Down
74 changes: 74 additions & 0 deletions src/obj_utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright 2023 RisingWave Labs
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Utilities for using `Any` as the key of a `HashMap`.
// Adopted from:
// https://github.com/bevyengine/bevy/blob/56bcbb097552b45e3ff48c48947ed8ee4e2c24b1/crates/bevy_utils/src/label.rs

use std::any::Any;
use std::hash::{Hash, Hasher};

/// An object safe version of [`Eq`]. This trait is automatically implemented
/// for any `'static` type that implements `Eq`.
pub(crate) trait DynEq: Any {
/// Casts the type to `dyn Any`.
fn as_any(&self) -> &dyn Any;

/// This method tests for `self` and `other` values to be equal.
///
/// Implementers should avoid returning `true` when the underlying types are
/// not the same.
fn dyn_eq(&self, other: &dyn DynEq) -> bool;
}

impl<T> DynEq for T
where
T: Any + Eq,
{
fn as_any(&self) -> &dyn Any {
self
}

fn dyn_eq(&self, other: &dyn DynEq) -> bool {
if let Some(other) = other.as_any().downcast_ref::<T>() {
return self == other;
}
false
}
}

/// An object safe version of [`Hash`]. This trait is automatically implemented
/// for any `'static` type that implements `Hash`.
pub(crate) trait DynHash: DynEq {
/// Casts the type to `dyn Any`.
fn as_dyn_eq(&self) -> &dyn DynEq;

/// Feeds this value into the given [`Hasher`].
fn dyn_hash(&self, state: &mut dyn Hasher);
}

impl<T> DynHash for T
where
T: DynEq + Hash,
{
fn as_dyn_eq(&self) -> &dyn DynEq {
self
}

fn dyn_hash(&self, mut state: &mut dyn Hasher) {
T::hash(self, &mut state);
self.type_id().hash(&mut state);
}
}
Loading

0 comments on commit c58eaf5

Please sign in to comment.