Repository navigation
Expand file tree
/
Copy pathtimeout.h
More file actions
148 lines (122 loc) · 3.12 KB
/
Copy pathtimeout.h
File metadata and controls
148 lines (122 loc) · 3.12 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
138
139
140
141
142
143
144
145
146
147
/**
* Timeout.h
*
* Class that terminates a running script when it runs for too long
*
* @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
* @copyright 2025 Copernica BV
*/
/**
* Include guard
*/
#pragma once
/**
* Dependencies
*/
#include <chrono>
#include <condition_variable>
/**
* Begin of namespace
*/
namespace JS {
/**
* Class definition
*/
class Timeout
{
private:
/**
* Mutex to protect resources
* @var std::mutex
*/
std::mutex _mutex;
/**
* The isolate that must be terminated
* @var v8::Isolate
*/
v8::Isolate *_isolate;
/**
* Point in time when to expire
* @var std::chrono::time_point
*/
std::chrono::steady_clock::time_point _expire;
/**
* Condition variable to wake up the other thread
* @var std::condition_variable
*/
std::condition_variable _cv;
/**
* The thread that is running
* @var std::thread
*/
std::thread _thread;
/**
* Run the thread
*/
void run()
{
// obtain a lock to access the shared resource
std::unique_lock<std::mutex> lock(_mutex);
// while the isolate has not yet been killed
while (_isolate != nullptr)
{
// wait for the conditio variable
auto result = _cv.wait_until(lock, _expire);
// proceed if the timeout has not yet been reached
if (result != std::cv_status::timeout) continue;
// double-check
if (_isolate == nullptr) break;
// terminate execution
_isolate->TerminateExecution();
// forget the isolate, we no longer have to terminate
_isolate = nullptr;
}
}
/**
* Helper method to wakeup the thread
* This is a separate method to ensure that the must is freed after the call, so that the thread can finish
*/
void finalize()
{
// obtain a lock to access the shared resource
std::unique_lock<std::mutex> lock(_mutex);
// reset the isolate so that the thread can no longer terminate execution
_isolate = nullptr;
// wake up the other thread
_cv.notify_one();
}
public:
/**
* Constructor
* @param isolate
* @param timeout
*/
Timeout(v8::Isolate *isolate, time_t timeout) : _isolate(isolate), _expire(std::chrono::steady_clock::now() + std::chrono::seconds(timeout))
{
// if there is no timeout
if (timeout == 0) return;
// start a thread
_thread = std::thread(std::bind(&Timeout::run, this));
}
/**
* No copying
* @param that
*/
Timeout(const Timeout &that) = delete;
/**
* Destructor
*/
virtual ~Timeout()
{
// if never started in the first place
if (!_thread.joinable()) return;
// finalize the thread
finalize();
// join the thread
_thread.join();
}
};
/**
* End of namespace
*/
}