Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: src/Timeout.cpp

Issue 29370876: Issue #4692, #3595 - Stop sleeping in the implementation of `SetTimeout`
Patch Set: Created Jan. 9, 2017, 1:22 p.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/Timeout.h ('k') | test/PausePoint.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/Timeout.cpp
===================================================================
new file mode 100644
--- /dev/null
+++ b/src/Timeout.cpp
@@ -0,0 +1,120 @@
+/*
+ * This file is part of Adblock Plus <https://adblockplus.org/>,
+ * Copyright (C) 2006-2017 Eyeo GmbH
+ *
+ * Adblock Plus is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * Adblock Plus is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "JsEngineInternal.h"
+#include "JsEngineTransition.h"
+#include "Scheduler.h"
+#include "Timeout.h"
+#include "Utils.h"
+
+namespace
+{
+ class TimeoutTask
+ : public TaskFunctionInterface
+ {
+ typedef int64_t delayType; // return type of v8::Value::GetInteger()
+ /**
+ * shared_ptr ensures the engine remains in existence
+ * while we're waiting for the task to complete.
+ * The scheduler ought to undertake this responsibility,
+ * but until then we must do it ourselves.
+ */
+ JsEngineInternal* engine;
+ V8PersistentNG<v8::Function> function;
+ delayType delay;
+ PersistentValueArray functionArguments;
+ DelayedExecutor executor;
+
+ void body()
+ {
+ V8ExecutionScope sentry(engine);
+ auto isolate = engine->GetIsolate();
+ engine->ApplyFunction(function.Get(isolate), functionArguments.GetAsLocal(isolate));
+ }
+
+ public:
+ TimeoutTask(
+ JsEngineInternal *engine,
+ V8PersistentNG<v8::Function> function,
+ delayType delay,
+ PersistentValueArray functionArguments
+ ) :
+ engine(engine),
+ function(function),
+ delay(delay),
+ functionArguments(std::move(functionArguments)),
+ executor([this]() { body(); })
+ {}
+
+ void operator()() override
+ {
+ executor.RunWithDelay(std::chrono::milliseconds(delay));
+ }
+
+ void Interrupt() override
+ {
+ executor.ForestallExecution();
+ }
+ };
+}
+
+/**
+ * Callback function registered to v8 to implement `SetTimeout`
+ *
+ * Note that this implementation does not support the "evaluate code" version
+ * of `SetTimeout`, only the "apply function" version.
+ *
+ * \par Reference
+ * https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout
+ */
+v8::Handle<v8::Value> CallbackForSetTimeout(const v8::Arguments& arguments)
+{
+ auto engine = JsEngineInternal::ExtractEngine(arguments);
+ try
+ {
+ if (arguments.Length() < 2)
+ {
+ throw std::runtime_error("setTimeout: must have at least 2 arguments");
+ }
+ if (!arguments[0]->IsFunction())
+ {
+ throw std::runtime_error("setTimeout: argument 1 must be a function");
+ }
+ auto isolate = engine->GetIsolate();
+ size_t n = arguments.Length() - 2;
+ PersistentValueArray functionArguments(n);
+ for (size_t i = 0; i < n; i++)
+ {
+ functionArguments[i] = V8PersistentNG<v8::Value>(isolate, arguments[i + 2]);
+ }
+ /*
+ * Run the task
+ */
+ auto task(std::make_shared<TimeoutTask>(engine,
+ V8PersistentNG<v8::Function>(isolate, v8::Local<v8::Function>::Cast(arguments[0])),
+ arguments[1]->IntegerValue(), std::move(functionArguments)));
+ engine->ScheduleTask(std::move(task), ImmediateSingleUseThread);
+ // We should actually return the timer ID here, which could be
+ // used via clearTimeout(). But since we don't seem to need
+ // clearTimeout(), we can save that for later.
+ return v8::Undefined();
+ }
+ catch (const std::exception& e)
+ {
+ return v8::ThrowException(engine->ToV8String(e.what()));
+ }
+}
« no previous file with comments | « src/Timeout.h ('k') | test/PausePoint.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld