1 module logdefer.timer; 2 3 4 import std.typecons : RefCounted; 5 6 import logdefer.time.duration : Nanos; 7 import logdefer.time.utils : toDuration; 8 9 import unixtime : ClockType, UnixTimeHiRes; 10 11 @safe 12 class Timer 13 { 14 public: 15 16 // This is what triggers the timer to stop when it goes out of scope 17 private struct Trigger 18 { 19 public: 20 @disable this(); 21 22 this(Timer timer) 23 { 24 timer_ = timer; 25 } 26 27 ~this() 28 { 29 timer_.stop(); 30 } 31 32 private: 33 Timer timer_; 34 } 35 36 this(string timerName, const UnixTimeHiRes startTime) 37 { 38 startTime_ = startTime; 39 timerName_ = timerName; 40 } 41 42 // Starts timer and returns struct which when destroyed will 43 // stop timer 44 auto startTimer() 45 { 46 startOffset_ = toDuration!Nanos(startTime_, UnixTimeHiRes.now!(ClockType.MONOTONIC)()); 47 return Trigger(this); 48 } 49 50 @property 51 string name() const 52 { 53 return timerName_; 54 } 55 56 @property 57 Nanos start() const 58 { 59 return startOffset_; 60 } 61 62 @property 63 Nanos end() const 64 { 65 return endOffset_; 66 } 67 68 private: 69 const UnixTimeHiRes startTime_; 70 71 Nanos startOffset_; 72 Nanos endOffset_; 73 74 Trigger* trigger_; 75 76 immutable string timerName_; 77 78 void stop() 79 { 80 endOffset_ = toDuration!Nanos(startTime_, UnixTimeHiRes.now!(ClockType.MONOTONIC)()); 81 } 82 } 83 84 version (unittest) 85 { 86 import core.thread; 87 import std.stdio; 88 89 import logdefer.time.duration : Millis; 90 } 91 92 unittest 93 { 94 writeln("[UnitTest Timer] - aprox duration"); 95 96 auto now = UnixTimeHiRes.now!(ClockType.MONOTONIC)(); 97 auto timer1 = new Timer("test1", now); 98 auto timer2 = new Timer("test2", now); 99 100 { 101 auto scope1 = timer1.startTimer(); 102 { 103 auto scope2 = timer2.startTimer(); 104 Thread.sleep(dur!"msecs"(250)); 105 } 106 Thread.sleep(dur!"msecs"(250)); 107 } 108 109 assert(timer1.name == "test1"); 110 assert(timer1.start > 0); 111 assert(timer1.end > Millis(450)); 112 assert(timer1.end < Millis(600)); 113 114 assert(timer2.name == "test2"); 115 assert(timer2.start > 0); 116 assert(timer2.end > Millis(200)); 117 assert(timer2.end < Millis(400)); 118 }