Skip to content

Commit 38771a4

Browse files
authored
Publish version 0.2 (#12)
- Version 0.2 - Update cargo.toml - Update documentation - Added SplitTickedAsyncExecutor APIs
1 parent a792d18 commit 38771a4

File tree

5 files changed

+105
-39
lines changed

5 files changed

+105
-39
lines changed

Cargo.toml

+8-6
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
[package]
22
name = "ticked_async_executor"
3-
version = "0.1.0"
3+
version = "0.2.0"
4+
authors = ["coder137"]
45
edition = "2021"
6+
description = "Local executor that runs woken async tasks when it is ticked"
7+
license = "Apache-2.0"
8+
repository = "https://github.com/coder137/ticked-async-executor"
9+
categories = ["asynchronous", "concurrency", "game-development", "simulation"]
10+
readme = "README.md"
511

612
[dependencies]
713
async-task = "4.7"
814
pin-project = "1"
9-
10-
# For timer only
11-
# TODO, Add this under a feature gate
12-
# TODO, Only tokio::sync::watch channel is used (find individual dependency)
13-
tokio = { version = "1.0", default-features = false, features = ["sync"] }
15+
tokio = { version = "1", default-features = false, features = ["sync"] }
1416

1517
[dev-dependencies]
1618
tokio = { version = "1", features = ["full"] }

README.md

+59-6
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,71 @@
11
# Ticked Async Executor
22

3-
Rust based Async Executor which executes woken tasks only when it is ticked
3+
Async Local Executor which executes woken tasks only when it is ticked
44

5-
# Example
5+
# Usage
6+
7+
## Default Local Executor
68

79
```rust
10+
use ticked_async_executor::*;
11+
12+
const DELTA: f64 = 1000.0 / 60.0;
13+
814
let executor = TickedAsyncExecutor::default();
915

1016
executor.spawn_local("MyIdentifier", async move {}).detach();
1117

12-
// Make sure to tick your executor to run the tasks
13-
executor.tick(DELTA, LIMIT);
18+
// Tick your executor to run the tasks
19+
assert_eq!(executor.num_tasks(), 1);
20+
executor.tick(DELTA, None);
21+
assert_eq!(executor.num_tasks(), 0);
22+
```
23+
24+
## Split Local Executor
25+
26+
```rust
27+
use ticked_async_executor::*;
28+
29+
const DELTA: f64 = 1000.0 / 60.0;
30+
31+
let (spawner, ticker) = SplitTickedAsyncExecutor::default();
32+
33+
spawner.spawn_local("MyIdentifier", async move {}).detach();
34+
35+
// Tick your ticker to run the tasks
36+
assert_eq!(spawner.num_tasks(), 1);
37+
ticker.tick(DELTA, None);
38+
assert_eq!(spawner.num_tasks(), 0);
1439
```
1540

16-
# Limitation
41+
## Limit the number of woken tasks run per tick
42+
43+
```rust
44+
use ticked_async_executor::*;
45+
46+
const DELTA: f64 = 1000.0 / 60.0;
47+
48+
let executor = TickedAsyncExecutor::default();
49+
50+
executor.spawn_local("MyIdentifier1", async move {}).detach();
51+
executor.spawn_local("MyIdentifier2", async move {}).detach();
52+
53+
// Runs upto 1 woken tasks per tick
54+
assert_eq!(executor.num_tasks(), 2);
55+
executor.tick(DELTA, Some(1));
56+
assert_eq!(executor.num_tasks(), 1);
57+
executor.tick(DELTA, Some(1));
58+
assert_eq!(executor.num_tasks(), 0);
59+
```
60+
61+
# Caveats
62+
63+
- Uses the `smol` ecosystem
64+
- Ensure that tasks are spawned on the same thread as the one that initializes the executor
65+
66+
# Roadmap
1767

18-
- Does not work with the tokio runtime and async constructs that use the tokio runtime internally
68+
- [x] TickedAsyncExecutor
69+
- [x] SplitTickedAsyncExecutor
70+
- Similar to the channel API, but spawner and ticker cannot be moved to different threads
71+
- [ ] Tracing

src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#![doc = include_str!("../README.md")]
2+
13
mod droppable_future;
24
use droppable_future::*;
35

src/split_ticked_async_executor.rs

+34-25
Original file line numberDiff line numberDiff line change
@@ -19,31 +19,40 @@ pub enum TaskState {
1919
pub type Task<T> = async_task::Task<T>;
2020
type Payload = (TaskIdentifier, async_task::Runnable);
2121

22-
pub fn new_split_ticked_async_executor<O>(
23-
observer: O,
24-
) -> (TickedAsyncExecutorSpawner<O>, TickedAsyncExecutorTicker<O>)
25-
where
26-
O: Fn(TaskState) + Clone + Send + Sync + 'static,
27-
{
28-
let (tx_channel, rx_channel) = mpsc::channel();
29-
let num_woken_tasks = Arc::new(AtomicUsize::new(0));
30-
let num_spawned_tasks = Arc::new(AtomicUsize::new(0));
31-
let (tx_tick_event, rx_tick_event) = tokio::sync::watch::channel(1.0);
32-
let spawner = TickedAsyncExecutorSpawner {
33-
tx_channel,
34-
num_woken_tasks: num_woken_tasks.clone(),
35-
num_spawned_tasks: num_spawned_tasks.clone(),
36-
observer: observer.clone(),
37-
rx_tick_event,
38-
};
39-
let ticker = TickedAsyncExecutorTicker {
40-
rx_channel,
41-
num_woken_tasks,
42-
num_spawned_tasks,
43-
observer,
44-
tx_tick_event,
45-
};
46-
(spawner, ticker)
22+
pub struct SplitTickedAsyncExecutor;
23+
24+
impl SplitTickedAsyncExecutor {
25+
pub fn default() -> (
26+
TickedAsyncExecutorSpawner<fn(TaskState)>,
27+
TickedAsyncExecutorTicker<fn(TaskState)>,
28+
) {
29+
Self::new(|_state| {})
30+
}
31+
32+
pub fn new<O>(observer: O) -> (TickedAsyncExecutorSpawner<O>, TickedAsyncExecutorTicker<O>)
33+
where
34+
O: Fn(TaskState) + Clone + Send + Sync + 'static,
35+
{
36+
let (tx_channel, rx_channel) = mpsc::channel();
37+
let num_woken_tasks = Arc::new(AtomicUsize::new(0));
38+
let num_spawned_tasks = Arc::new(AtomicUsize::new(0));
39+
let (tx_tick_event, rx_tick_event) = tokio::sync::watch::channel(1.0);
40+
let spawner = TickedAsyncExecutorSpawner {
41+
tx_channel,
42+
num_woken_tasks: num_woken_tasks.clone(),
43+
num_spawned_tasks: num_spawned_tasks.clone(),
44+
observer: observer.clone(),
45+
rx_tick_event,
46+
};
47+
let ticker = TickedAsyncExecutorTicker {
48+
rx_channel,
49+
num_woken_tasks,
50+
num_spawned_tasks,
51+
observer,
52+
tx_tick_event,
53+
};
54+
(spawner, ticker)
55+
}
4756
}
4857

4958
pub struct TickedAsyncExecutorSpawner<O> {

src/ticked_async_executor.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::future::Future;
22

33
use crate::{
4-
new_split_ticked_async_executor, Task, TaskIdentifier, TaskState, TickedAsyncExecutorSpawner,
4+
SplitTickedAsyncExecutor, Task, TaskIdentifier, TaskState, TickedAsyncExecutorSpawner,
55
TickedAsyncExecutorTicker, TickedTimer,
66
};
77

@@ -21,7 +21,7 @@ where
2121
O: Fn(TaskState) + Clone + Send + Sync + 'static,
2222
{
2323
pub fn new(observer: O) -> Self {
24-
let (spawner, ticker) = new_split_ticked_async_executor(observer);
24+
let (spawner, ticker) = SplitTickedAsyncExecutor::new(observer);
2525
Self { spawner, ticker }
2626
}
2727

0 commit comments

Comments
 (0)