]> git.sesse.net Git - casparcg/blob - common/os/linux/prec_timer.cpp
9a700740c4d95ef46cdde1d9a6dddbe2895c5034
[casparcg] / common / os / linux / prec_timer.cpp
1 /*
2 * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>
3 *
4 * This file is part of CasparCG (www.casparcg.com).
5 *
6 * CasparCG is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * CasparCG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with CasparCG. If not, see <http://www.gnu.org/licenses/>.
18 *
19 * Author: Robert Nagy, ronag89@gmail.com
20 */
21
22 #include "../../stdafx.h"
23
24 #include "../../prec_timer.h"
25
26 #include <boost/thread.hpp>
27 #include <boost/chrono/system_clocks.hpp>
28
29 #include <time.h>
30
31 #include <cmath>
32
33 using namespace boost::chrono;
34
35 namespace caspar {
36         
37 prec_timer::prec_timer()
38         : time_(0)
39 {
40 }
41
42 void prec_timer::tick_millis(int64_t ticks_to_wait)
43 {
44         ticks_to_wait *= 1000000;
45         auto t = duration_cast<nanoseconds>(high_resolution_clock::now().time_since_epoch()).count();
46
47         if (time_ != 0)
48         {
49                 bool done = 0;
50                 do
51                 {
52                         auto ticks_passed = t - time_;
53                         auto ticks_left = ticks_to_wait - ticks_passed;
54
55                         if (t < time_)    // time wrap
56                                 done = 1;
57                         if (ticks_passed >= ticks_to_wait)
58                                 done = 1;
59
60                         if (!done)
61                         {
62                                 timespec spec;
63
64                                 if (ticks_left > 2000000)
65                                 {
66                                         spec.tv_sec = ticks_left / 1000000000;
67                                         spec.tv_nsec = 1000000;
68                                 }
69                                 else
70                                 {
71                                         spec.tv_sec = 0;
72                                         spec.tv_nsec = ticks_left / 100;
73                                 }
74
75                                 nanosleep(&spec, nullptr);
76                         }
77
78                         t = duration_cast<nanoseconds>(high_resolution_clock::now().time_since_epoch()).count();
79                 } while (!done);
80         }
81
82         time_ = t;
83 }
84
85 }