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

Unified Diff: src/FilterEngine.cpp

Issue 29377064: Issue 4944 - Make creation of FilterEngine asynchronous. (Closed)
Patch Set: Created Feb. 28, 2017, 2:21 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
Index: src/FilterEngine.cpp
diff --git a/src/FilterEngine.cpp b/src/FilterEngine.cpp
index 9b5662a052a0d81444bb40a93d80c0823d0242e6..fd4ff4d3634dbd141d13d847b36aea9910bcb5a9 100644
--- a/src/FilterEngine.cpp
+++ b/src/FilterEngine.cpp
@@ -23,6 +23,8 @@
#include <AdblockPlus.h>
#include "JsContext.h"
#include "Thread.h"
+#include <mutex>
+#include <condition_variable>
using namespace AdblockPlus;
@@ -134,34 +136,85 @@ bool Subscription::operator==(const Subscription& subscription) const
return GetProperty("url")->AsString() == subscription.GetProperty("url")->AsString();
}
-FilterEngine::FilterEngine(JsEnginePtr jsEngine,
- const FilterEngine::Prefs& preconfiguredPrefs)
- : jsEngine(jsEngine), initialized(false), firstRun(false), updateCheckId(0)
+namespace
{
- jsEngine->SetEventCallback("_init", std::bind(&FilterEngine::InitDone,
- this, std::placeholders::_1));
-
+ class Sync
{
- // Lock the JS engine while we are loading scripts, no timeouts should fire
- // until we are done.
- const JsContext context(jsEngine);
-
- // Set the preconfigured prefs
- JsValuePtr preconfiguredPrefsObject = jsEngine->NewObject();
- for (FilterEngine::Prefs::const_iterator it = preconfiguredPrefs.begin();
- it != preconfiguredPrefs.end(); it++)
+ public:
+ Sync()
+ :initialized(false)
{
- preconfiguredPrefsObject->SetProperty(it->first, it->second);
+
}
- jsEngine->SetGlobalProperty("_preconfiguredPrefs", preconfiguredPrefsObject);
- // Load adblockplus scripts
- for (int i = 0; !jsSources[i].empty(); i += 2)
- jsEngine->Evaluate(jsSources[i + 1], jsSources[i]);
- }
+ void Wait()
+ {
+ std::unique_lock<std::mutex> lock(mutex);
+ while (!initialized)
+ cv.wait(lock);
+ }
+ void Set()
+ {
+ {
+ std::unique_lock<std::mutex> lock(mutex);
+ initialized = true;
+ }
+ cv.notify_all();
+ }
+ private:
+ std::mutex mutex;
+ std::condition_variable cv;
+ bool initialized;
+ };
+}
+
+FilterEngine::FilterEngine(const JsEnginePtr& jsEngine)
+ : jsEngine(jsEngine), firstRun(false), updateCheckId(0)
+{
+}
+
+void FilterEngine::CreateAsync(const JsEnginePtr& jsEngine,
+ const FilterEngine::OnCreatedCallback& onCreated,
+ const FilterEngine::CreateParameters& params)
+{
+ FilterEnginePtr filterEngine(new FilterEngine(jsEngine));
+ auto sync = std::make_shared<Sync>();
+ jsEngine->SetEventCallback("_init", [jsEngine, filterEngine, onCreated, sync](JsValueList& params)
+ {
+ filterEngine->firstRun = params.size() && params[0]->AsBool();
+ sync->Set();
+ onCreated(filterEngine);
+ jsEngine->RemoveEventCallback("_init");
+ });
+
+ // Lock the JS engine while we are loading scripts, no timeouts should fire
+ // until we are done.
+ const JsContext context(jsEngine);
- // TODO: This should really be implemented via a conditional variable
- while (!initialized)
- ::Sleep(10);
+ // Set the preconfigured prefs
+ JsValuePtr preconfiguredPrefsObject = jsEngine->NewObject();
+ for (FilterEngine::Prefs::const_iterator it = params.preconfiguredPrefs.begin();
+ it != params.preconfiguredPrefs.end(); it++)
+ {
+ preconfiguredPrefsObject->SetProperty(it->first, it->second);
+ }
+ jsEngine->SetGlobalProperty("_preconfiguredPrefs", preconfiguredPrefsObject);
+ // Load adblockplus scripts
+ for (int i = 0; !jsSources[i].empty(); i += 2)
+ jsEngine->Evaluate(jsSources[i + 1], jsSources[i]);
+}
+
+FilterEnginePtr FilterEngine::Create(const JsEnginePtr& jsEngine,
+ const FilterEngine::CreateParameters& params)
+{
+ FilterEnginePtr retValue;
+ Sync sync;
+ CreateAsync(jsEngine, [&retValue, &sync](const FilterEnginePtr& filterEngine)
+ {
+ retValue = filterEngine;
+ sync.Set();
+ }, params);
+ sync.Wait();
+ return retValue;
}
namespace
@@ -213,13 +266,6 @@ FilterEngine::ContentType FilterEngine::StringToContentType(const std::string& c
throw std::invalid_argument("Cannot convert argument to ContentType");
}
-void FilterEngine::InitDone(JsValueList& params)
-{
- jsEngine->RemoveEventCallback("_init");
- initialized = true;
- firstRun = params.size() && params[0]->AsBool();
-}
-
bool FilterEngine::IsFirstRun() const
{
return firstRun;

Powered by Google App Engine
This is Rietveld