1 /*
2  * Kiss - A refined core library for D programming language.
3  *
4  * Copyright (C) 2015-2018  Shanghai Putao Technology Co., Ltd
5  *
6  * Developer: HuntLabs.cn
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11  
12 module kiss.event.timer.epoll;
13 
14 // dfmt off
15 version (linux) : 
16 // dfmt on
17 
18 import kiss.event.core;
19 import kiss.event.timer.common;
20 
21 import core.sys.posix.unistd;
22 import core.sys.posix.time : itimerspec, CLOCK_MONOTONIC;
23 
24 import core.time;
25 import std.datetime;
26 import std.exception;
27 import kiss.logger;
28 import std.socket;
29 
30 /**
31 */
32 abstract class AbstractTimer : TimerChannelBase
33 {
34     this(Selector loop)
35     {
36         super(loop);
37         init();
38     }
39 
40     private void init()
41     {
42         setFlag(WatchFlag.Read, true);
43         _readBuffer = new UintObject();
44         this.handle = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
45     }
46 
47     ~this()
48     {
49         close();
50     }    
51 
52     bool setTimer()
53     {
54         itimerspec its;
55         ulong sec, nsec;
56         sec = time / 1000;
57         nsec = (time % 1000) * 1_000_000;
58         its.it_value.tv_sec = cast(typeof(its.it_value.tv_sec)) sec;
59         its.it_value.tv_nsec = cast(typeof(its.it_value.tv_nsec)) nsec;
60         its.it_interval.tv_sec = its.it_value.tv_sec;
61         its.it_interval.tv_nsec = its.it_value.tv_nsec;
62         const int err = timerfd_settime(this.handle, 0, &its, null);
63         if (err == -1)
64         {
65             return false;
66         }
67         return true;
68     }
69 
70     bool readTimer(scope ReadCallBack read)
71     {
72         this.clearError();
73         uint value;
74         core.sys.posix.unistd.read(this.handle, &value, 8);
75         this._readBuffer.data = value;
76         if (read)
77             read(this._readBuffer);
78         return false;
79     }
80 
81     UintObject _readBuffer;
82 }
83 
84 
85 /**
86 C APIs for timerfd
87 */
88 enum TFD_TIMER_ABSTIME = 1 << 0;
89 enum TFD_CLOEXEC = 0x80000;
90 enum TFD_NONBLOCK = 0x800;
91 
92 extern (C)
93 {
94     socket_t timerfd_create(int clockid, int flags) nothrow;
95     int timerfd_settime(int fd, int flags, const itimerspec* new_value, itimerspec* old_value) nothrow;
96     int timerfd_gettime(int fd, itimerspec* curr_value) nothrow;
97 }