]> git.sesse.net Git - casparcg/blob - common/prec_timer.cpp
1e4e8eb86b1c7f784c855221c1752ca03221edf9
[casparcg] / common / prec_timer.cpp
1 /*\r
2 * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
3 *\r
4 * This file is part of CasparCG (www.casparcg.com).\r
5 *\r
6 * CasparCG is free software: you can redistribute it and/or modify\r
7 * it under the terms of the GNU General Public License as published by\r
8 * the Free Software Foundation, either version 3 of the License, or\r
9 * (at your option) any later version.\r
10 *\r
11 * CasparCG is distributed in the hope that it will be useful,\r
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14 * GNU General Public License for more details.\r
15 *\r
16 * You should have received a copy of the GNU General Public License\r
17 * along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
18 *\r
19 * Author: Robert Nagy, ronag89@gmail.com\r
20 */\r
21 \r
22 #include "stdafx.h"\r
23 \r
24 #include "prec_timer.h"\r
25 \r
26 #include "os/windows/windows.h"\r
27 \r
28 #include <Mmsystem.h>\r
29 \r
30 namespace caspar {\r
31         \r
32 prec_timer::prec_timer()\r
33         : time_(0)\r
34 {\r
35 }\r
36 \r
37 // Author: Ryan M. Geiss\r
38 // http://www.geisswerks.com/ryan/FAQS/timing.html\r
39 void prec_timer::tick(double interval)\r
40 {       \r
41         auto t = ::timeGetTime();\r
42 \r
43         if (time_ != 0)\r
44         {\r
45                 auto ticks_to_wait = static_cast<DWORD>(interval*1000.0);\r
46                 bool done = 0;\r
47                 do\r
48                 {                               \r
49                         auto ticks_passed = t - time_;\r
50                         auto ticks_left   = ticks_to_wait - ticks_passed;\r
51 \r
52                         if (t < time_)    // time wrap\r
53                                 done = 1;\r
54                         if (ticks_passed >= ticks_to_wait)\r
55                                 done = 1;\r
56                                 \r
57                         if (!done)\r
58                         {\r
59                                 // if > 0.002s left, do Sleep(1), which will actually sleep some \r
60                                 //   steady amount, probably 1-2 ms,\r
61                                 //   and do so in a nice way (cpu meter drops; laptop battery spared).\r
62                                 // otherwise, do a few Sleep(0)'s, which just give up the timeslice,\r
63                                 //   but don't really save cpu or battery, but do pass a tiny\r
64                                 //   amount of time.\r
65                                 if (ticks_left > 2)\r
66                                         Sleep(1);\r
67                                 else                        \r
68                                         for (int i = 0; i < 10; ++i) \r
69                                                 Sleep(0);  // causes thread to give up its timeslice\r
70                         }\r
71 \r
72                         t = ::timeGetTime();\r
73                 }\r
74                 while (!done);            \r
75         }\r
76 \r
77         time_ = t;\r
78 }       \r
79 \r
80 }