1 module yu.task; 2 3 import std.traits; 4 import std.experimental.allocator; 5 import std.variant; 6 import core.atomic; 7 import yu.exception; 8 9 ReturnType!F run(F, Args...)(F fpOrDelegate, ref Args args) { 10 return fpOrDelegate(args); 11 } 12 13 enum TaskStatus : ubyte { 14 LDLE = 0x00, 15 Runing = 0x01, 16 Finsh = 0x02, 17 InVaild = 0x03, 18 } 19 20 @trusted class AbstractTask { 21 alias TaskFun = bool function(AbstractTask); 22 alias FinishCall = void delegate(AbstractTask) nothrow; 23 24 final void job() nothrow { 25 if (atomicLoad(_status) != TaskStatus.LDLE) 26 return; 27 atomicStore(_status, TaskStatus.Runing); 28 scope (failure) 29 atomicStore(_status, TaskStatus.InVaild); 30 bool rv = false; 31 if (_runTask){ 32 _e = yuCathException(_runTask(this),rv); 33 } 34 if (rv) 35 atomicStore(_status, TaskStatus.Finsh); 36 else 37 atomicStore(_status, TaskStatus.InVaild); 38 if(_finish) 39 _finish(this); 40 } 41 42 final bool rest() { 43 if (isRuning) 44 return false; 45 atomicStore(_status, TaskStatus.LDLE); 46 return true; 47 } 48 49 final @property TaskStatus status() { 50 return atomicLoad(_status); 51 } 52 53 pragma(inline, true) final bool isRuning() { 54 return (atomicLoad(_status) == TaskStatus.Runing); 55 } 56 57 @property Variant returnValue(){return _rvalue;} 58 @property Exception throwExecption(){return _e;} 59 60 @property FinishCall finishedCall(){return _finish;} 61 @property void finishedCall(FinishCall finish){_finish = finish;} 62 protected: 63 this(TaskFun fun) { 64 _runTask = fun; 65 } 66 67 private: 68 TaskFun _runTask; 69 shared TaskStatus _status = TaskStatus.LDLE; 70 private: //return 71 Exception _e; 72 Variant _rvalue; 73 FinishCall _finish; 74 private: // Use in queue 75 AbstractTask next; 76 } 77 78 @trusted final class Task(alias fun, Args...) : AbstractTask { 79 static if (Args.length > 0) { 80 this(Args args) { 81 _args = args; 82 super(&impl); 83 } 84 85 Args _args; 86 } else { 87 this() { 88 super(&impl); 89 } 90 91 alias _args = void; 92 } 93 94 static bool impl(AbstractTask myTask) { 95 auto myCastedTask = cast(typeof(this)) myTask; 96 if (myCastedTask is null) 97 return false; 98 alias RType = typeof(fun(_args)); 99 static if (is(RType == void)) 100 fun(myCastedTask._args); 101 else 102 myCastedTask._rvalue = fun(myCastedTask._args); 103 return true; 104 } 105 } 106 107 @trusted auto makeTask(alias fun, Alloc, Args...)(Alloc alloc, Args args) { 108 return make!(Task!(fun, Args))(alloc, args); 109 } 110 111 @trusted auto makeTask(F, Alloc, Args...)(Alloc alloc, F delegateOrFp, Args args) if ( 112 is(typeof(delegateOrFp(args)))) { 113 return make!(Task!(run, F, Args))(alloc, delegateOrFp, args); 114 } 115 116 ///Note:from GC 117 @trusted auto newTask(alias fun, Args...)(Args args) { 118 return new Task!(fun, Args)(args); 119 } 120 121 ///Note:from GC 122 @trusted auto newTask(F, Args...)(F delegateOrFp, Args args) if (is(typeof(delegateOrFp(args)))) { 123 return new Task!(run, F, Args)(delegateOrFp, args); 124 } 125 126 struct TaskQueue { 127 AbstractTask front() nothrow { 128 return _frist; 129 } 130 131 bool empty() nothrow { 132 return _frist is null; 133 } 134 135 void enQueue(AbstractTask task) nothrow 136 in { 137 assert(task); 138 } 139 body { 140 if (_last) { 141 _last.next = task; 142 } else { 143 _frist = task; 144 } 145 task.next = null; 146 _last = task; 147 } 148 149 AbstractTask deQueue() nothrow 150 in { 151 assert(_frist && _last); 152 } 153 body { 154 AbstractTask task = _frist; 155 _frist = _frist.next; 156 if (_frist is null) 157 _last = null; 158 return task; 159 } 160 161 private: 162 @disable this(this); 163 AbstractTask _last = null; 164 AbstractTask _frist = null; 165 } 166 167 unittest { 168 import std.functional; 169 int tfun() { 170 return 10; 171 } 172 173 void finish(AbstractTask task) nothrow @trusted 174 { 175 import yu.exception; 176 showException(yuCathException((){ 177 import std.stdio; 178 int a = task.returnValue.get!int(); 179 assert(task.status == TaskStatus.Finsh); 180 assert(a == 10); 181 writeln("-------------task call finish!!"); 182 }())); 183 } 184 185 AbstractTask test = newTask(&tfun); 186 test.finishedCall = toDelegate(&finish); 187 assert(test.status == TaskStatus.LDLE); 188 test.job(); 189 int a = test.returnValue.get!int(); 190 assert(test.status == TaskStatus.Finsh); 191 assert(a == 10); 192 193 }