1 module nyinaa.timers;
2 
3 // import std.stdio : writeln;
4 import core.thread.osthread : Thread;
5 import std.datetime.stopwatch : Duration, StopWatch, msecs;
6 import std.concurrency : receiveTimeout, receive, spawn, Tid, send, thisTid;
7 
8 /**
9 * Runs a callback function at certain interval
10 *
11 * Params:
12 *       duration = The time interval as a duration
13 *       callback = callback function at every tick
14 *
15 * Example:
16 * ---
17 *       import nyinaa.timers: setInterval;
18 *       
19 *       import std.stdio : writeln;
20 *       import std.datetime : msecs;
21 *       import core.thread.osthread : Thread;
22 
23 *       void main()
24 *       {
25 *           setInterval(1000.msecs, (){ writeln("tick"); });
26 *           setInterval(2000.msecs, (){ writeln("tock"); });
27 * 
28 *           // wait a little before exit
29 *           Thread.sleep(4000.msecs);
30 *       }
31 * ---
32 */
33 
34 Tid setInterval(Duration duration, void function() callback)
35 {
36     static void worker(Duration d, void function() cb)
37     {
38         // writeln("Starting ", thisTid, "...");
39         bool done = false;
40 
41         StopWatch sw;
42         sw.start;
43         while (true)
44         {
45             // wait for messages for a timespan of at least `d`
46             // wait for messages for a timespan of at least `d`
47             receiveTimeout(d, (string text) {
48                 //writeln("Received string: ", text);
49                 if (text == "cancel")
50                     done = true;
51             });
52 
53             if (done)
54                 break;
55 
56             // if "cancel" message is not received,
57             //  check timeout for the callback
58             if (sw.peek >= d)
59             {
60                 cb();
61                 sw.reset;
62             }
63         }
64     }
65 
66     Tid id = spawn(&worker, duration, callback);
67     return id;
68 }
69 
70 /**
71 * Cancels a setInterval() timer
72 *
73 * Params:
74 *       threadId = Thread id of the setInterval() timer to be cancelled
75 *
76 * Example:
77 * ---
78 *       import nyinaa.timers: setInterval, stopInterval;
79 *
80 *       import std.stdio : writeln;
81 *       import std.datetime : msecs;
82 *       import std.concurrency : Tid;
83 *       import core.thread.osthread : Thread;
84 *
85 *       void main()
86 *       {
87 *           Tid b = setInterval(1000.msecs, (){ writeln("Hello from spawned thread B"); });
88 *           // Let wait for 2 seconds
89 *           Thread.sleep(2000.msecs);
90 *
91 *           // cancel timer
92 *           stopInterval(b);
93 *       }
94 * ---
95 */
96 void stopInterval(Tid threadId)
97 {
98     send(threadId, "cancel");
99 }
100 
101 /**
102 * Runs a callback function at certain interval
103 *
104 * Params:
105 *       duration = The time interval as a duration
106 *
107 * Example:
108 * ---
109 *       import nyinaa.timers: setInterval;
110 *
111 *       import std.datetime : msecs;
112 *       import std.concurrency : Tid;
113 *       import std.stdio : writeln;
114 *
115 *       void main()
116 *       {
117 *           auto b = setInterval(1000.msecs, (){ writeln("Hello from spawned thread B"); });
118 *           // Let this one run a little
119 *           Thread.sleep(2500.msecs);
120 *           stopInterval(b);
121 *       }
122 * ---
123 */
124 // auto setTimeout(long milliseconds, void function() callback)
125 // {
126 //     static void worker(Duration d, void function() cb)
127 //     {
128 //         // writeln("Starting ", thisTid, "...");
129 
130 //         bool done = false;
131 
132 //         StopWatch sw;
133 //         sw.start;
134 //         while (true)
135 //         {
136 //             // wait for messages for a timespan of at least `d`
137 //             receiveTimeout(d, (string text) {
138 //                 //writeln("Received string: ", text);
139 //                 if (text == "cancel")
140 //                     done = true;
141 //             });
142 
143 //             if (done)
144 //                 break;
145 
146 //             // if "cancel" message is not received,
147 //             //  check timeout for the callback
148 //             if (sw.peek >= d)
149 //             {
150 //                 cb();
151 //                 done = true;
152 //             }
153 
154 //             //sw.reset;
155 //         }
156 //     }
157 
158 //     Tid id = spawn(&worker, milliseconds.msecs, callback);
159 
160 //     return id;
161 // }
162 
163 // void stopTimeout(Tid tid)
164 // {
165 //     send(tid, "cancel");
166 // }