Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3136)

Unified Diff: chrome/browser/sync/glue/ui_model_worker.cc

Issue 14046031: Worker changes to prepare for lock-free shutdown. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/sync/glue/ui_model_worker.cc
diff --git a/chrome/browser/sync/glue/ui_model_worker.cc b/chrome/browser/sync/glue/ui_model_worker.cc
index c0336ba2ed8994b746bd6dfa766b010d1f10d2b9..beac8f84727e1100c03c2f76ca5d86b6fbdb25e3 100644
--- a/chrome/browser/sync/glue/ui_model_worker.cc
+++ b/chrome/browser/sync/glue/ui_model_worker.cc
@@ -16,41 +16,18 @@ using content::BrowserThread;
namespace browser_sync {
-namespace {
-
-// A simple callback to signal a waitable event after running a closure.
-void CallDoWorkAndSignalCallback(const syncer::WorkCallback& work,
- base::WaitableEvent* work_done,
- UIModelWorker* const scheduler,
- syncer::SyncerError* error_info) {
- if (work.is_null()) {
- // This can happen during tests or cases where there are more than just the
- // default UIModelWorker in existence and it gets destroyed before
- // the main UI loop has terminated. There is no easy way to assert the
- // loop is running / not running at the moment, so we just provide cancel
- // semantics here and short-circuit.
- // TODO(timsteele): Maybe we should have the message loop destruction
- // observer fire when the loop has ended, just a bit before it
- // actually gets destroyed.
- return;
- }
-
- *error_info = work.Run();
-
- // Notify the UIModelWorker that scheduled us that we have run
- // successfully.
- scheduler->OnTaskCompleted();
- work_done->Signal(); // Unblock the syncer thread that scheduled us.
-}
-
-} // namespace
-
-UIModelWorker::UIModelWorker()
- : state_(WORKING),
+UIModelWorker::UIModelWorker(syncer::WorkerLoopDestructionObserver* observer)
+ : syncer::ModelSafeWorker(observer),
+ state_(WORKING),
syncapi_has_shutdown_(false),
syncapi_event_(&lock_) {
}
+void UIModelWorker::RegisterForLoopDestruction() {
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ MessageLoop::current()->AddDestructionObserver(this);
+}
+
void UIModelWorker::Stop() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -76,8 +53,8 @@ void UIModelWorker::Stop() {
state_ = STOPPED;
}
-syncer::SyncerError UIModelWorker::DoWorkAndWaitUntilDone(
- const syncer::WorkCallback& work) {
+syncer::SyncerError UIModelWorker::DoWorkAndWaitUntilDoneImpl(
+ const syncer::WorkCallback& work, base::WaitableEvent* done) {
// In most cases, this method is called in WORKING state. It is possible this
// gets called when we are in the RUNNING_MANUAL_SHUTDOWN_PUMP state, because
// the UI loop has initiated shutdown but the syncer hasn't got the memo yet.
@@ -92,16 +69,14 @@ syncer::SyncerError UIModelWorker::DoWorkAndWaitUntilDone(
return work.Run();
}
- // Create an unsignaled event to wait on.
- base::WaitableEvent work_done(false, false);
{
// We lock only to avoid PostTask'ing a NULL pending_work_ (because it
// could get Run() in Stop() and call OnTaskCompleted before we post).
// The task is owned by the message loop as per usual.
base::AutoLock lock(lock_);
DCHECK(pending_work_.is_null());
- pending_work_ = base::Bind(&CallDoWorkAndSignalCallback, work, &work_done,
- base::Unretained(this), &error_info);
+ pending_work_ = base::Bind(&UIModelWorker::CallDoWorkAndSignalCallback,
+ this, work, done, &error_info);
if (!BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, pending_work_)) {
DLOG(WARNING) << "Could not post work to UI loop.";
error_info = syncer::CANNOT_DO_WORK;
@@ -111,10 +86,37 @@ syncer::SyncerError UIModelWorker::DoWorkAndWaitUntilDone(
}
}
syncapi_event_.Signal(); // Notify that the syncapi produced work for us.
- work_done.Wait();
+ done->Wait();
tim (not reviewing) 2013/05/17 20:51:33 Do we need to pass the event around? It's a membe
haitaol1 2013/05/17 22:06:57 Added protected accessor. On 2013/05/17 20:51:33,
return error_info;
}
+void UIModelWorker::CallDoWorkAndSignalCallback(
+ const syncer::WorkCallback& work,
+ base::WaitableEvent* work_done,
+ syncer::SyncerError* error_info) {
+ if (work.is_null()) {
+ // This can happen during tests or cases where there are more than just the
+ // default UIModelWorker in existence and it gets destroyed before
tim (not reviewing) 2013/05/17 20:51:33 You're not passing UIModelWorker* to a static func
haitaol1 2013/05/17 22:06:57 The UI worker (or any worker) will not be destroye
+ // the main UI loop has terminated. There is no easy way to assert the
+ // loop is running / not running at the moment, so we just provide cancel
+ // semantics here and short-circuit.
+ // TODO(timsteele): Maybe we should have the message loop destruction
+ // observer fire when the loop has ended, just a bit before it
+ // actually gets destroyed.
+ return;
+ }
+
+ if (!IsStopped())
tim (not reviewing) 2013/05/17 20:51:33 This is hard to follow because RequestStop sets st
haitaol1 2013/05/17 22:06:57 Reverted. On 2013/05/17 20:51:33, timsteele wrote
+ *error_info = work.Run();
+ else
+ *error_info = syncer::CANNOT_DO_WORK;
+
+ // Notify the UIModelWorker that scheduled us that we have run
+ // successfully.
+ OnTaskCompleted();
tim (not reviewing) 2013/05/17 20:51:33 OnTaskCompleted is now notifying |this| instead of
haitaol1 2013/05/17 22:06:57 Yes
+ work_done->Signal(); // Unblock the syncer thread that scheduled us.
+}
+
syncer::ModelSafeGroup UIModelWorker::GetModelSafeGroup() {
return syncer::GROUP_UI;
}

Powered by Google App Engine
This is Rietveld 408576698