21
21
#include " isolate.h"
22
22
#include < cstring>
23
23
#include < cstdlib>
24
- #include < iostream>
25
24
26
25
/* *
27
26
* Start namespace
@@ -69,6 +68,10 @@ Isolate::Isolate()
69
68
// create the actual isolate
70
69
_isolate = v8::Isolate::New (params);
71
70
71
+ // associate ourselves with this isolate
72
+ // so that we can find it back from the pointer
73
+ _isolate->SetData (0 , this );
74
+
72
75
// and enter it
73
76
_isolate->Enter ();
74
77
}
@@ -78,13 +81,85 @@ Isolate::Isolate()
78
81
*/
79
82
Isolate::~Isolate ()
80
83
{
84
+ // run all tasks still awaiting executing
85
+ runTasks ();
86
+
87
+ /* *
88
+ * the tasks that are still there are scheduled
89
+ * somewhere in the future, we just delete these
90
+ * - this seems like a strange thing to do, but
91
+ * executing them now seems to throw v8 off guard
92
+ * and results in either a deadlock or some weird
93
+ * error message about garbage collection running
94
+ * in some old "space" or something equally weird
95
+ * and confusing.
96
+ */
97
+ _tasks.clear ();
98
+
81
99
// leave the isolate scope
82
100
_isolate->Exit ();
83
101
84
102
// clean it up
85
103
_isolate->Dispose ();
86
104
}
87
105
106
+ /* *
107
+ * Perform all waiting tasks for this isolate
108
+ */
109
+ void Isolate::runTasks ()
110
+ {
111
+ // no tasks? then we're done fast!
112
+ if (_tasks.empty ()) return ;
113
+
114
+ // determine the current time
115
+ auto now = std::chrono::system_clock::now ();
116
+
117
+ // loop over all the tasks
118
+ for (auto iter = _tasks.begin (); iter != _tasks.end (); ++iter)
119
+ {
120
+ // is the execution time still in the future?
121
+ if (now < iter->first )
122
+ {
123
+ // first task? then don't remove anything
124
+ if (iter == _tasks.begin ()) return ;
125
+
126
+ // remove from the beginning up until the task
127
+ // since we already moved past the last task we
128
+ // need to go back one so we don't remove a task
129
+ // we have not actually executed yet
130
+ _tasks.erase (_tasks.begin (), --iter);
131
+
132
+ // tasks executed and removed
133
+ return ;
134
+ }
135
+
136
+ // execute the task
137
+ iter->second ->Run ();
138
+ }
139
+
140
+ // we ran through all the tasks and executed all of them
141
+ _tasks.clear ();
142
+ }
143
+
144
+ /* *
145
+ * Schedule a task to be executed
146
+ *
147
+ * @param isolate The isolate to execute the task under
148
+ * @param task The task to execute
149
+ * @param delay Number of seconds to wait before executing
150
+ */
151
+ void Isolate::scheduleTask (v8::Isolate *isolate, v8::Task *task, double delay)
152
+ {
153
+ // first retrieve the isolate to schedule it under
154
+ auto *real = static_cast <Isolate*>(isolate->GetData (0 ));
155
+
156
+ // determine the time at which the task should be executed
157
+ auto expire = std::chrono::system_clock::now () + std::chrono::microseconds{ static_cast <int64_t >(delay * 1000000 ) };
158
+
159
+ // schedule the task to be executed
160
+ real->_tasks .emplace (std::make_pair (expire, std::unique_ptr<v8::Task>{ task }));
161
+ }
162
+
88
163
/* *
89
164
* Get the isolate for this thread
90
165
*
@@ -95,6 +170,9 @@ v8::Isolate *Isolate::get()
95
170
// do we still have to create the isolate?
96
171
if (!isolate) isolate.reset (new Isolate);
97
172
173
+ // execute tasks for this isolate
174
+ isolate->runTasks ();
175
+
98
176
// return the isolate
99
177
return *isolate;
100
178
}
0 commit comments