| 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;
|
| }
|
|
|