egra: more strict checks before applying asm optimisations
[iv.d.git] / timer.d
blobe7e6ad54b32fc03a31c6b9ab8e924587756da7cc
1 /* Invisible Vector Library
2 * coded by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
3 * Understanding is not required. Only obedience.
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3 of the License ONLY.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 // this essentially duplicates std.datetime.StopWatch, but meh...
18 module iv.timer;
20 import iv.pxclock;
23 struct Timer {
24 private:
25 ulong mSTimeMicro;
26 ulong mAccumMicro;
27 State mState = State.Stopped;
29 public:
30 enum State {
31 Stopped,
32 Running,
33 Paused,
36 public:
37 string toString () const @trusted {
38 char[128] buf = void;
39 auto t = toBuffer(buf[]);
40 return t.idup;
43 nothrow @trusted @nogc:
44 this (State initState) @trusted {
45 if (initState == State.Running) start();
48 this (bool startit) @trusted {
49 if (startit) start();
52 @property const pure {
53 auto state () { pragma(inline, true); return mState; }
54 bool stopped () { pragma(inline, true); return (mState == State.Stopped); }
55 bool running () { pragma(inline, true); return (mState == State.Running); }
56 bool paused () { pragma(inline, true); return (mState == State.Paused); }
59 @property ulong micro () const {
60 final switch (mState) {
61 case State.Stopped: case State.Paused: return mAccumMicro;
62 case State.Running: return mAccumMicro+(clockMicro-mSTimeMicro);
66 // this also pauses it
67 @property void micro (ulong value) {
68 mAccumMicro = value;
69 mSTimeMicro = 0;
70 mState = State.Stopped;
73 @property ulong milli () const { pragma(inline, true); return micro/1000; }
74 @property ulong milliRounded () const { pragma(inline, true); return micro/1000+(micro%500 >= 500); }
76 void reset () {
77 mAccumMicro = 0;
78 mSTimeMicro = clockMicro;
81 void restart () {
82 mAccumMicro = 0;
83 mState = State.Running;
84 mSTimeMicro = clockMicro;
87 void start () {
88 mAccumMicro = 0;
89 mState = State.Running;
90 mSTimeMicro = clockMicro;
93 void stop () {
94 if (mState == State.Running) {
95 mAccumMicro += clockMicro-mSTimeMicro;
96 mState = State.Stopped;
100 void pause () {
101 if (mState == State.Running) {
102 mAccumMicro += clockMicro-mSTimeMicro;
103 mState = State.Paused;
107 void resume () {
108 if (mState == State.Paused) {
109 mState = State.Running;
110 mSTimeMicro = clockMicro;
111 } else if (mState == State.Stopped) {
112 start();
116 // 128 chars should be enough for everyone
117 char[] toBuffer (char[] dest) const nothrow @trusted @nogc {
118 import core.stdc.stdio : snprintf;
119 char[128] buf = void;
120 ulong d;
121 final switch (mState) {
122 case State.Stopped: case State.Paused: d = mAccumMicro; break;
123 case State.Running: d = mAccumMicro+(clockMicro-mSTimeMicro); break;
125 immutable uint micro = cast(uint)(d%1000);
126 d /= 1000;
127 immutable uint milli = cast(uint)(d%1000);
128 d /= 1000;
129 immutable uint seconds = cast(uint)(d%60);
130 d /= 60;
131 immutable uint minutes = cast(uint)(d%60);
132 d /= 60;
133 immutable uint hours = cast(uint)d;
134 uint len;
135 if (hours) len = cast(uint)snprintf(buf.ptr, buf.length, "%u:%02u:%02u.%03u", hours, minutes, seconds, milli);
136 else if (minutes) len = cast(uint)snprintf(buf.ptr, buf.length, "%u:%02u.%03u", minutes, seconds, milli);
137 else if (seconds) len = cast(uint)snprintf(buf.ptr, buf.length, "%u.%03u", seconds, milli);
138 else if (milli >= 10) len = cast(uint)snprintf(buf.ptr, buf.length, "%ums", milli);
139 else if (micro != 0) len = cast(uint)snprintf(buf.ptr, buf.length, "%ums:%umcs", milli, micro);
140 else len = cast(uint)snprintf(buf.ptr, buf.length, "%ums", milli);
141 if (len > dest.length) len = cast(uint)dest.length;
142 dest.ptr[0..len] = buf.ptr[0..len];
143 return dest.ptr[0..len];