-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtimer.h
More file actions
137 lines (109 loc) · 3.38 KB
/
timer.h
File metadata and controls
137 lines (109 loc) · 3.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// Copyright (C) 2016 Tetsui Ohkubo.
#ifndef TIMER_H_
#define TIMER_H_
#include <unistd.h>
#if defined __MACH__
#include <mach/mach_time.h>
#elif defined _POSIX_MONOTONIC_CLOCK
#include <time.h>
#else
#error no way to get accurate time.
#endif
#include <cstdint>
#include <mutex> // NOLINT
#include <thread> // NOLINT
static const uint64_t kNanosecondsToMilliseconds = 1000000;
static const uint64_t kNanosecondsToSeconds = 1000000000;
class Timer {
public:
// Check() will always return false (the timer will never expire)
// by setting timeout_ms negative.
// The timer will start right after the constructor is called.
explicit Timer(int timeout_ms = -1)
: timeout_ms_(timeout_ms)
, node_count_(0)
, completed_depth_(0)
, mutex_() {
GetAccurateCurrentTime(&begin_time_);
GetAccurateCurrentTime(¤t_time_);
}
// Return true if the timer is expired.
bool CheckTimeout(bool allow_false_negative = false) {
if (allow_false_negative) {
if (node_count_ % 100 > 0) {
return false;
}
}
// std::lock_guard<std::mutex> lock(mutex_);
GetAccurateCurrentTime(¤t_time_);
if (timeout_ms_ < 0) {
return false;
}
if (DiffAccurateTime(current_time_, begin_time_) >
static_cast<uint64_t>(timeout_ms_) * kNanosecondsToMilliseconds) {
return true;
}
return false;
}
// Should be called from the bottom of the search.
void IncrementNodeCounter() {
// std::lock_guard<std::mutex> lock(mutex_);
++node_count_;
}
// Return node per second value.
int nps() {
uint64_t diff = DiffAccurateTime(current_time_, begin_time_);
if (diff == 0) {
return 0;
}
return node_count_ * kNanosecondsToSeconds / diff;
}
// Return elapsed milliseconds since the Timer constructor is called.
int elapsed_ms() {
return DiffAccurateTime(current_time_, begin_time_) /
kNanosecondsToMilliseconds;
}
int timeout_ms() { return timeout_ms_; }
int completed_depth() { return completed_depth_; }
void set_completed_depth(int completed_depth) {
std::lock_guard<std::mutex> lock(mutex_);
if (completed_depth_ < completed_depth) {
completed_depth_ = completed_depth;
}
}
private:
#if defined __MACH__
using TimeType = uint64_t;
static void GetAccurateCurrentTime(TimeType *current_time) {
mach_timebase_info_data_t base;
mach_timebase_info(&base);
*current_time = mach_absolute_time() / base.denom;
}
static uint64_t DiffAccurateTime(const TimeType& after,
const TimeType& before) {
return after - before;
}
#elif defined _POSIX_MONOTONIC_CLOCK
using TimeType = struct timespec;
static void GetAccurateCurrentTime(TimeType *current_time) {
clock_gettime(CLOCK_MONOTONIC, current_time);
}
static uint64_t DiffAccurateTime(const TimeType& after,
const TimeType& before) {
if (after.tv_nsec - before.tv_nsec < 0) {
return (after.tv_sec - before.tv_sec - 1) * kNanosecondsToSeconds +
(kNanosecondsToSeconds + after.tv_nsec - before.tv_nsec);
} else {
return (after.tv_sec - before.tv_sec) * kNanosecondsToSeconds +
(after.tv_nsec - before.tv_nsec);
}
}
#endif
int timeout_ms_;
TimeType begin_time_;
TimeType current_time_;
uint64_t node_count_;
int completed_depth_;
std::mutex mutex_;
};
#endif // TIMER_H_