@@ -6,8 +6,9 @@ use crate::common::ordered_work_steal::{OrderedLocalQueue, OrderedWorkStealQueue
66use crate :: common:: { get_timeout_time, now, CondvarBlocker } ;
77use crate :: coroutine:: suspender:: Suspender ;
88use crate :: scheduler:: { SchedulableCoroutine , Scheduler } ;
9- use crate :: { error, impl_current_for, impl_display_by_debug, impl_for_named, trace} ;
9+ use crate :: { error, impl_current_for, impl_display_by_debug, impl_for_named, trace, warn } ;
1010use dashmap:: { DashMap , DashSet } ;
11+ use once_cell:: sync:: Lazy ;
1112use std:: cell:: Cell ;
1213use std:: ffi:: c_longlong;
1314use std:: io:: { Error , ErrorKind } ;
@@ -25,6 +26,11 @@ mod state;
2526/// Creator for coroutine pool.
2627mod creator;
2728
29+ /// `task_name` -> `co_name`
30+ static RUNNING_TASKS : Lazy < DashMap < & str , & str > > = Lazy :: new ( DashMap :: new) ;
31+
32+ static CANCEL_TASKS : Lazy < DashSet < & str > > = Lazy :: new ( DashSet :: new) ;
33+
2834/// The coroutine pool impls.
2935#[ repr( C ) ]
3036#[ derive( Debug ) ]
@@ -383,7 +389,17 @@ impl<'p> CoroutinePool<'p> {
383389
384390 fn try_run ( & self ) -> Option < ( ) > {
385391 self . task_queue . pop ( ) . map ( |task| {
392+ let tname = task. get_name ( ) . to_string ( ) . leak ( ) ;
393+ if CANCEL_TASKS . contains ( tname) {
394+ _ = CANCEL_TASKS . remove ( tname) ;
395+ warn ! ( "Cancel task:{} successfully !" , tname) ;
396+ return ;
397+ }
398+ if let Some ( co) = SchedulableCoroutine :: current ( ) {
399+ _ = RUNNING_TASKS . insert ( tname, co. name ( ) ) ;
400+ }
386401 let ( task_name, result) = task. run ( ) ;
402+ _ = RUNNING_TASKS . remove ( tname) ;
387403 let n = task_name. clone ( ) . leak ( ) ;
388404 if self . no_waits . contains ( n) {
389405 _ = self . no_waits . remove ( n) ;
@@ -406,6 +422,44 @@ impl<'p> CoroutinePool<'p> {
406422 }
407423 }
408424
425+ /// Try to cancel a task.
426+ pub fn try_cancel_task ( task_name : & str ) {
427+ // 检查正在运行的任务是否是要取消的任务
428+ if let Some ( info) = RUNNING_TASKS . get ( task_name) {
429+ let co_name = * info;
430+ // todo windows support
431+ #[ allow( unused_variables) ]
432+ if let Some ( pthread) = Scheduler :: get_scheduling_thread ( co_name) {
433+ // 发送SIGVTALRM信号,在运行时取消任务
434+ #[ cfg( unix) ]
435+ if nix:: sys:: pthread:: pthread_kill ( pthread, nix:: sys:: signal:: Signal :: SIGVTALRM )
436+ . is_ok ( )
437+ {
438+ warn ! (
439+ "Attempt to cancel task:{} running on coroutine:{} by thread:{}, cancelling..." ,
440+ task_name, co_name, pthread
441+ ) ;
442+ } else {
443+ error ! (
444+ "Attempt to cancel task:{} running on coroutine:{} by thread:{} failed !" ,
445+ task_name, co_name, pthread
446+ ) ;
447+ }
448+ } else {
449+ // 添加到待取消队列
450+ Scheduler :: try_cancel_coroutine ( co_name) ;
451+ warn ! (
452+ "Attempt to cancel task:{} running on coroutine:{}, cancelling..." ,
453+ task_name, co_name
454+ ) ;
455+ }
456+ } else {
457+ // 添加到待取消队列
458+ _ = CANCEL_TASKS . insert ( Box :: leak ( Box :: from ( task_name) ) ) ;
459+ warn ! ( "Attempt to cancel task:{}, cancelling..." , task_name) ;
460+ }
461+ }
462+
409463 /// Schedule the tasks.
410464 ///
411465 /// Allow multiple threads to concurrently submit task to the pool,
0 commit comments