1 module hunt.util.thread.Task;
2 
3 import hunt.logging;
4 
5 import core.atomic;
6 import core.time;
7 import std.format;
8 
9 
10 enum TaskStatus : ubyte {
11     Ready,
12     Processing,
13     Terminated,
14     Done
15 }
16 
17 
18 /**
19  * 
20  */
21 abstract class Task {
22     protected shared TaskStatus _status;
23 
24     private string _name;
25     
26     private MonoTime _createTime;
27     private MonoTime _startTime;
28     private MonoTime _endTime;
29 
30     this(string name) {
31         _name = name;
32         _status = TaskStatus.Ready;
33         _createTime = MonoTime.currTime;
34     }
35 
36     string name() {
37         return _name;
38     }
39 
40     Duration survivalTime() {
41         return _endTime - _createTime;
42     }
43 
44     Duration executionTime() {
45         return _endTime - _startTime;
46     }
47 
48     Duration lifeTime() {
49         if(_endTime > _createTime) {
50             return survivalTime();
51         } else {
52             return MonoTime.currTime - _createTime;
53         }
54     }
55 
56     TaskStatus status() {
57         return _status;
58     }
59 
60     bool isReady() {
61         return _status == TaskStatus.Ready;
62     }
63 
64     bool isProcessing() {
65         return _status == TaskStatus.Processing;
66     }
67 
68     bool isTerminated() {
69         return _status == TaskStatus.Terminated;
70     }
71 
72     bool isDone() {
73         return _status == TaskStatus.Done;
74     }
75 
76     void stop() {
77         
78         version(HUNT_POOL_DEBUG_MORE) {
79             tracef("The task status: %s", _status);
80         }
81 
82         if(!cas(&_status, TaskStatus.Processing, TaskStatus.Terminated) && 
83             !cas(&_status, TaskStatus.Ready, TaskStatus.Terminated)) {
84             version(HUNT_POOL_DEBUG) {
85                 warningf("The task [%s] stopped. The status is %s",  _name, _status);
86             }
87         }
88     }
89 
90     void finish() {
91         version(HUNT_POOL_DEBUG_MORE) {
92             tracef("The status of task [%s]: %s", _name, _status);
93         }
94 
95         if(cas(&_status, TaskStatus.Processing, TaskStatus.Done) || 
96             cas(&_status, TaskStatus.Ready, TaskStatus.Done)) {
97                 
98             _endTime = MonoTime.currTime;
99             version(HUNT_POOL_DEBUG) {
100                 infof("The task [%s] done.", _name);
101             }
102         } else {
103             version(HUNT_POOL_DEBUG) {
104                 warningf("Failed to set the status of task [%s] to Done: %s", _name, _status);
105             }
106         }
107     }
108 
109     protected void doExecute();
110 
111     void execute() {
112         if(cas(&_status, TaskStatus.Ready, TaskStatus.Processing)) {
113             version(HUNT_POOL_DEBUG_MORE) {
114                 tracef("Task %s executing... status: %s", _name, _status);
115             }
116             _startTime = MonoTime.currTime;
117             scope(exit) {
118                 finish();
119                 version(HUNT_POOL_DEBUG_MORE) {
120                     infof("The task [%s] is done!", _name);
121                 }
122             }
123 
124             try {
125                 doExecute();
126             } catch(Throwable t) {
127                 warningf("task [%s] failed: %s", _name, t.msg);
128                 version(HUNT_POOL_DEBUG_MORE) {
129                     warning(t);
130                 }
131             }
132         } else {
133             warningf("Failed to execute task [%s]. Its status is: %s", _name, _status);
134         }
135     }
136 
137     override string toString() {
138         return format("name: %s, status: %s", _name, _status);
139     }
140 
141 }
142