timerwheel 0.1.0

Hierarchical timer wheel for delayed task scheduling with pluggable executors.
Documentation
// Copyright © 2026-present The Timerwheel Authors. All rights reserved.
//
// 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.

#![cfg(feature = "tokio")]

use std::time::Duration;

use timerwheel::executor::{BoxTask, Executor as ExecutorTrait};
use tokio::sync::oneshot;

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn tokio_executor_rejects_after_shutdown_with_task_ownership() {
    let executor = timerwheel::tokio::Executor::current().expect("executor builds");
    ExecutorTrait::shutdown(&executor).expect("executor shuts down");

    let task: BoxTask = Box::new(|| {});
    let rejected = match ExecutorTrait::try_execute(&executor, task) {
        Ok(()) => panic!("closed executor should reject task"),
        Err(rejected) => rejected,
    };

    assert_eq!(rejected.error(), &timerwheel::Error::Closed);
}

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn tokio_timer_uses_tokio_executor_without_async_facade() {
    let timer = timerwheel::tokio::Timer::builder()
        .tick(Duration::from_millis(1))
        .bucket_count(64)
        .build()
        .expect("timer builds");
    let (tx, rx) = oneshot::channel();

    timer
        .schedule(Duration::from_millis(10), move || {
            tx.send("fired").expect("send succeeds");
        })
        .expect("schedule succeeds");

    assert_eq!(
        tokio::time::timeout(Duration::from_secs(1), rx)
            .await
            .expect("task should fire")
            .expect("sender should complete"),
        "fired"
    );
    assert!(timer.shutdown().is_ok());
}