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..8510f6f9a29d4841f57c7bc6b48a63d41197a1b6 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::WorkerObserver* 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)); |
@@ -77,7 +54,7 @@ void UIModelWorker::Stop() { |
} |
syncer::SyncerError UIModelWorker::DoWorkAndWaitUntilDone( |
- const syncer::WorkCallback& work) { |
+ 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(); |
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 |
+ // 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 (!Stopped()) |
+ *error_info = work.Run(); |
+ else |
+ *error_info = syncer::CANNOT_DO_WORK; |
+ |
+ // Notify the UIModelWorker that scheduled us that we have run |
+ // successfully. |
+ OnTaskCompleted(); |
+ work_done->Signal(); // Unblock the syncer thread that scheduled us. |
+} |
+ |
syncer::ModelSafeGroup UIModelWorker::GetModelSafeGroup() { |
return syncer::GROUP_UI; |
} |