Initial Dever 0.0.1
This commit is contained in:
commit
81233d098c
1479 files changed
+163782
No files matched your search
@@ -0,0 +1,144 @@
|
||||
// 独立 Tokio 参照只实现本组一层任务工作负载,不调用 Dever 调度器。
|
||||
// 任务和 worker 分别限流;遇到失败或取消仍领取所有 JoinHandle,已启动阻塞工作不强停。
|
||||
use std::{sync::Arc, time::Duration};
|
||||
use tokio::{runtime, sync::Semaphore, task::JoinHandle};
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
||||
struct NativeTasks {
|
||||
runtime: runtime::Runtime,
|
||||
workers: Arc<Semaphore>,
|
||||
tasks: Arc<Semaphore>,
|
||||
}
|
||||
|
||||
fn task_fault(_: impl std::fmt::Debug) -> Fault {
|
||||
&FaultInfo {
|
||||
source: "task-reference",
|
||||
line: 1,
|
||||
column: 1,
|
||||
message: "task failure",
|
||||
}
|
||||
}
|
||||
|
||||
fn native_total(values: &[i64]) -> Result<i64, Fault> {
|
||||
values.iter().try_fold(0i64, |total, value| {
|
||||
total
|
||||
.checked_add(*value)
|
||||
.ok_or_else(|| task_fault("integer overflow"))
|
||||
})
|
||||
}
|
||||
|
||||
impl NativeTasks {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
runtime: runtime::Builder::new_multi_thread()
|
||||
.worker_threads(2)
|
||||
.max_blocking_threads(2)
|
||||
.enable_time()
|
||||
.build()
|
||||
.unwrap(),
|
||||
workers: Arc::new(Semaphore::new(2)),
|
||||
tasks: Arc::new(Semaphore::new(8)),
|
||||
}
|
||||
}
|
||||
|
||||
fn start(
|
||||
&self,
|
||||
values: Vec<i64>,
|
||||
asynchronous: bool,
|
||||
cancel: CancellationToken,
|
||||
) -> JoinHandle<Result<i64, Fault>> {
|
||||
let admission = self.tasks.clone().try_acquire_owned().unwrap();
|
||||
let workers = self.workers.clone();
|
||||
tokio::spawn(async move {
|
||||
let result = if asynchronous {
|
||||
tokio::select! {
|
||||
biased;
|
||||
result = async { native_total(&values) } => result,
|
||||
() = cancel.cancelled() => Err(task_fault("cancelled")),
|
||||
}
|
||||
} else {
|
||||
let worker = tokio::select! {
|
||||
biased;
|
||||
() = cancel.cancelled() => return Err(task_fault("cancelled")),
|
||||
worker = workers.acquire_owned() => worker.unwrap(),
|
||||
};
|
||||
let result = tokio::task::spawn_blocking(move || native_total(&values))
|
||||
.await
|
||||
.map_err(task_fault)?;
|
||||
drop(worker);
|
||||
result
|
||||
};
|
||||
drop(admission);
|
||||
result
|
||||
})
|
||||
}
|
||||
|
||||
fn pair(&self, values: &[i64], asynchronous: bool) -> Result<i64, Fault> {
|
||||
self.runtime.block_on(async {
|
||||
let cancel = CancellationToken::new();
|
||||
let first = self.start(values.to_vec(), asynchronous, cancel.child_token());
|
||||
let second = self.start(values.to_vec(), asynchronous, cancel.child_token());
|
||||
let first = first.await.map_err(task_fault).and_then(|value| value);
|
||||
if first.is_err() {
|
||||
cancel.cancel();
|
||||
}
|
||||
let second = second.await.map_err(task_fault).and_then(|value| value);
|
||||
cancel.cancel();
|
||||
first?
|
||||
.checked_add(second?)
|
||||
.ok_or_else(|| task_fault("integer overflow"))
|
||||
})
|
||||
}
|
||||
|
||||
fn blocking(&self, values: &[i64], sleep: bool) -> Result<i64, Fault> {
|
||||
let values = values.to_vec();
|
||||
self.runtime.block_on(async {
|
||||
let worker = self.workers.clone().acquire_owned().await.unwrap();
|
||||
let result = tokio::task::spawn_blocking(move || {
|
||||
if sleep {
|
||||
std::time::Instant::now()
|
||||
.checked_add(Duration::ZERO)
|
||||
.ok_or_else(|| task_fault("sleep deadline"))?;
|
||||
std::thread::sleep(Duration::ZERO);
|
||||
}
|
||||
native_total(&values)
|
||||
})
|
||||
.await
|
||||
.map_err(task_fault)?;
|
||||
drop(worker);
|
||||
result
|
||||
})
|
||||
}
|
||||
|
||||
fn cancel(&self) -> Result<i64, Fault> {
|
||||
self.runtime.block_on(async {
|
||||
let admission = self.tasks.clone().try_acquire_owned().unwrap();
|
||||
let cancel = CancellationToken::new();
|
||||
let child = cancel.child_token();
|
||||
let task = tokio::spawn(async move {
|
||||
let deadline = tokio::time::Instant::now()
|
||||
.checked_add(Duration::from_millis(60000))
|
||||
.unwrap();
|
||||
tokio::select! {
|
||||
biased;
|
||||
() = tokio::time::sleep_until(deadline) => panic!("cancelled timer completed"),
|
||||
() = child.cancelled() => (),
|
||||
}
|
||||
drop(admission);
|
||||
});
|
||||
cancel.cancel();
|
||||
task.await.map_err(task_fault)?;
|
||||
Ok(1)
|
||||
})
|
||||
}
|
||||
|
||||
fn timer(&self) -> Result<i64, Fault> {
|
||||
self.runtime.block_on(async {
|
||||
let deadline = tokio::time::Instant::now()
|
||||
.checked_add(Duration::ZERO)
|
||||
.ok_or_else(|| task_fault("sleep deadline"))?;
|
||||
tokio::time::sleep_until(deadline).await;
|
||||
Ok(1)
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user