1pub mod config;
160pub mod error;
161mod service;
162pub mod task;
163pub mod timer;
164pub mod wheel;
165
166#[doc(hidden)]
167pub mod readme_docs;
168
169#[cfg(test)]
170mod tests;
171
172pub use error::TimerError;
174pub use lite_sync::spsc;
175pub use service::{TaskNotification, TimerService};
176pub use task::CompletionReceiver;
177pub use task::{CallbackWrapper, TaskCompletion, TaskId, TimerTask};
178pub use timer::TimerWheel;
179pub use timer::handle::{
180 BatchHandle, BatchHandleWithCompletion, TimerHandle, TimerHandleWithCompletion,
181};
182
183#[cfg(test)]
184mod integration_tests {
185 use super::*;
186 use std::sync::Arc;
187 use std::sync::atomic::{AtomicU32, Ordering};
188 use std::time::Duration;
189
190 #[tokio::test]
191 async fn test_basic_timer() {
192 let timer = TimerWheel::with_defaults();
193 let counter = Arc::new(AtomicU32::new(0));
194 let counter_clone = Arc::clone(&counter);
195
196 let handle = timer.allocate_handle();
197 let task = TimerTask::new_oneshot(
198 Duration::from_millis(50),
199 Some(CallbackWrapper::new(move || {
200 let counter = Arc::clone(&counter_clone);
201 async move {
202 counter.fetch_add(1, Ordering::SeqCst);
203 }
204 })),
205 );
206 timer.register(handle, task).unwrap();
207
208 tokio::time::sleep(Duration::from_millis(100)).await;
209 assert_eq!(counter.load(Ordering::SeqCst), 1);
210 }
211
212 #[tokio::test]
213 async fn test_multiple_timers() {
214 let timer = TimerWheel::with_defaults();
215 let counter = Arc::new(AtomicU32::new(0));
216
217 for i in 0..10 {
219 let counter_clone = Arc::clone(&counter);
220 let handle = timer.allocate_handle();
221 let task = TimerTask::new_oneshot(
222 Duration::from_millis(10 * (i + 1)),
223 Some(CallbackWrapper::new(move || {
224 let counter = Arc::clone(&counter_clone);
225 async move {
226 counter.fetch_add(1, Ordering::SeqCst);
227 }
228 })),
229 );
230 timer.register(handle, task).unwrap();
231 }
232
233 tokio::time::sleep(Duration::from_millis(200)).await;
234 assert_eq!(counter.load(Ordering::SeqCst), 10);
235 }
236
237 #[tokio::test]
238 async fn test_timer_cancellation() {
239 let timer = TimerWheel::with_defaults();
240 let counter = Arc::new(AtomicU32::new(0));
241
242 let mut handles = Vec::new();
244 for _ in 0..5 {
245 let counter_clone = Arc::clone(&counter);
246 let alloc_handle = timer.allocate_handle();
247 let task = TimerTask::new_oneshot(
248 Duration::from_millis(100),
249 Some(CallbackWrapper::new(move || {
250 let counter = Arc::clone(&counter_clone);
251 async move {
252 counter.fetch_add(1, Ordering::SeqCst);
253 }
254 })),
255 );
256 let handle = timer.register(alloc_handle, task).unwrap();
257 handles.push(handle);
258 }
259
260 for handle in handles.iter().take(3) {
262 let cancel_result = handle.cancel().unwrap();
263 assert!(cancel_result);
264 }
265
266 tokio::time::sleep(Duration::from_millis(200)).await;
267 assert_eq!(counter.load(Ordering::SeqCst), 2);
269 }
270
271 #[tokio::test]
272 async fn test_completion_notification_once() {
273 let timer = TimerWheel::with_defaults();
274 let counter = Arc::new(AtomicU32::new(0));
275 let counter_clone = Arc::clone(&counter);
276
277 let alloc_handle = timer.allocate_handle();
278 let task = TimerTask::new_oneshot(
279 Duration::from_millis(50),
280 Some(CallbackWrapper::new(move || {
281 let counter = Arc::clone(&counter_clone);
282 async move {
283 counter.fetch_add(1, Ordering::SeqCst);
284 }
285 })),
286 );
287 let handle = timer.register(alloc_handle, task).unwrap();
288
289 let (rx, _handle) = handle.into_parts();
291 match rx {
292 task::CompletionReceiver::OneShot(receiver) => {
293 receiver.recv().await.unwrap();
294 }
295 _ => panic!("Expected OneShot completion receiver"),
296 }
297
298 tokio::time::sleep(Duration::from_millis(20)).await;
300 assert_eq!(counter.load(Ordering::SeqCst), 1);
301 }
302
303 #[tokio::test]
304 async fn test_notify_only_timer_once() {
305 let timer = TimerWheel::with_defaults();
306
307 let alloc_handle = timer.allocate_handle();
308 let task = TimerTask::new_oneshot(Duration::from_millis(50), None);
309 let handle = timer.register(alloc_handle, task).unwrap();
310
311 let (rx, _handle) = handle.into_parts();
313 match rx {
314 task::CompletionReceiver::OneShot(receiver) => {
315 receiver.recv().await.unwrap();
316 }
317 _ => panic!("Expected OneShot completion receiver"),
318 }
319 }
320
321 #[tokio::test]
322 async fn test_batch_completion_notifications() {
323 let timer = TimerWheel::with_defaults();
324 let counter = Arc::new(AtomicU32::new(0));
325
326 let handles = timer.allocate_handles(5);
328
329 let tasks: Vec<_> = (0..5)
331 .map(|i| {
332 let counter = Arc::clone(&counter);
333 let delay = Duration::from_millis(50 + i as u64 * 10);
334 let callback = CallbackWrapper::new(move || {
335 let counter = Arc::clone(&counter);
336 async move {
337 counter.fetch_add(1, Ordering::SeqCst);
338 }
339 });
340 TimerTask::new_oneshot(delay, Some(callback))
341 })
342 .collect();
343
344 let batch = timer
346 .register_batch(handles, tasks)
347 .expect("register_batch should succeed");
348 let (receivers, _batch_handle) = batch.into_parts();
349
350 for rx in receivers {
352 match rx {
353 task::CompletionReceiver::OneShot(receiver) => {
354 receiver.recv().await.unwrap();
355 }
356 _ => panic!("Expected OneShot completion receiver"),
357 }
358 }
359
360 tokio::time::sleep(Duration::from_millis(50)).await;
362
363 assert_eq!(counter.load(Ordering::SeqCst), 5);
365 }
366
367 #[tokio::test]
368 async fn test_completion_reason_expired() {
369 let timer = TimerWheel::with_defaults();
370
371 let alloc_handle = timer.allocate_handle();
372 let task = TimerTask::new_oneshot(Duration::from_millis(50), None);
373 let handle = timer.register(alloc_handle, task).unwrap();
374
375 let (rx, _handle) = handle.into_parts();
377 let result = match rx {
378 task::CompletionReceiver::OneShot(receiver) => receiver.recv().await.unwrap(),
379 _ => panic!("Expected OneShot completion receiver"),
380 };
381 assert_eq!(result, TaskCompletion::Called);
382 }
383
384 #[tokio::test]
385 async fn test_completion_reason_cancelled() {
386 let timer = TimerWheel::with_defaults();
387
388 let alloc_handle = timer.allocate_handle();
389 let task = TimerTask::new_oneshot(Duration::from_secs(10), None);
390 let handle = timer.register(alloc_handle, task).unwrap();
391
392 let cancelled = handle.cancel().unwrap();
394 assert!(cancelled);
395
396 let (rx, _handle) = handle.into_parts();
398 let result = match rx {
399 task::CompletionReceiver::OneShot(receiver) => receiver.recv().await.unwrap(),
400 _ => panic!("Expected OneShot completion receiver"),
401 };
402 assert_eq!(result, TaskCompletion::Cancelled);
403 }
404
405 #[tokio::test]
406 async fn test_batch_completion_reasons() {
407 let timer = TimerWheel::with_defaults();
408
409 let handles = timer.allocate_handles(5);
411
412 let tasks: Vec<_> = (0..5)
414 .map(|_| TimerTask::new_oneshot(Duration::from_secs(10), None))
415 .collect();
416
417 let batch = timer
419 .register_batch(handles, tasks)
420 .expect("register_batch should succeed");
421 let task_ids: Vec<_> = batch.task_ids().to_vec();
422 let (mut receivers, _batch_handle) = batch.into_parts();
423
424 timer.cancel_batch(&task_ids[0..3]).unwrap();
426
427 for rx in receivers.drain(0..3) {
429 let result = match rx {
430 task::CompletionReceiver::OneShot(receiver) => receiver.recv().await.unwrap(),
431 _ => panic!("Expected OneShot completion receiver"),
432 };
433 assert_eq!(result, TaskCompletion::Cancelled);
434 }
435
436 timer.cancel_batch(&task_ids[3..5]).unwrap();
438 for rx in receivers {
439 let result = match rx {
440 task::CompletionReceiver::OneShot(receiver) => receiver.recv().await.unwrap(),
441 _ => panic!("Expected OneShot completion receiver"),
442 };
443 assert_eq!(result, TaskCompletion::Cancelled);
444 }
445 }
446
447 #[tokio::test]
448 async fn test_task_ids_and_handles_are_bound_to_their_wheel() {
449 let source = TimerWheel::with_defaults();
450 let target = TimerWheel::with_defaults();
451
452 let foreign_handle = source.allocate_handle();
453 let foreign_id = foreign_handle.task_id();
454 let registration = target.register(
455 foreign_handle,
456 TimerTask::new_oneshot(Duration::from_secs(10), None),
457 );
458 assert!(matches!(registration, Err(TimerError::WrongWheel)));
459
460 let target_handle = target.allocate_handle();
461 let target_id = target_handle.task_id();
462 let target_timer = target
463 .register(
464 target_handle,
465 TimerTask::new_oneshot(Duration::from_secs(10), None),
466 )
467 .unwrap();
468
469 assert_eq!(foreign_id.raw(), target_id.raw());
470 assert_ne!(foreign_id, target_id);
471 assert!(matches!(
472 target.cancel(foreign_id),
473 Err(TimerError::WrongWheel)
474 ));
475 assert!(matches!(
476 target.postpone(foreign_id, Duration::from_secs(1), None),
477 Err(TimerError::WrongWheel)
478 ));
479 assert!(target.cancel(target_id).unwrap());
480 drop(target_timer);
481
482 let _next_handle = source.allocate_handle();
485 }
486
487 #[tokio::test]
488 async fn test_batch_operations_reject_foreign_task_ids_atomically() {
489 let source = TimerWheel::with_defaults();
490 let target = TimerWheel::with_defaults();
491
492 let source_handle = source.allocate_handle();
493 let source_id = source_handle.task_id();
494 source
495 .register(
496 source_handle,
497 TimerTask::new_oneshot(Duration::from_secs(10), None),
498 )
499 .unwrap();
500
501 let target_handle = target.allocate_handle();
502 let target_id = target_handle.task_id();
503 let target_timer = target
504 .register(
505 target_handle,
506 TimerTask::new_oneshot(Duration::from_secs(10), None),
507 )
508 .unwrap();
509
510 assert!(matches!(
511 target.cancel_batch(&[target_id, source_id]),
512 Err(TimerError::WrongWheel)
513 ));
514 assert!(matches!(
515 target.postpone_batch(vec![
516 (target_id, Duration::from_secs(1)),
517 (source_id, Duration::from_secs(1)),
518 ]),
519 Err(TimerError::WrongWheel)
520 ));
521 assert!(target.cancel(target_id).unwrap());
522 drop(target_timer);
523 assert!(source.cancel(source_id).unwrap());
524 }
525}