| Index: sync/internal_api/public/engine/model_safe_worker.cc
|
| diff --git a/sync/internal_api/public/engine/model_safe_worker.cc b/sync/internal_api/public/engine/model_safe_worker.cc
|
| index eb3fc1f1c3ec286c961e743b23b05e77a7eae358..2aea5cf8378b0b9dbc1350410bdea6b19f8fe2a1 100644
|
| --- a/sync/internal_api/public/engine/model_safe_worker.cc
|
| +++ b/sync/internal_api/public/engine/model_safe_worker.cc
|
| @@ -75,8 +75,8 @@ ModelSafeWorker::ModelSafeWorker(WorkerLoopDestructionObserver* observer)
|
| : stopped_(false),
|
| work_done_or_stopped_(false, false),
|
| observer_(observer),
|
| - working_loop_(NULL),
|
| - working_loop_set_wait_(true, false) {}
|
| + working_loop_(NULL) {
|
| +}
|
|
|
| ModelSafeWorker::~ModelSafeWorker() {}
|
|
|
| @@ -135,26 +135,42 @@ void ModelSafeWorker::WillDestroyCurrentMessageLoop() {
|
| void ModelSafeWorker::SetWorkingLoopToCurrent() {
|
| base::AutoLock l(working_loop_lock_);
|
| DCHECK(!working_loop_);
|
| - working_loop_ = base::MessageLoop::current();
|
| - working_loop_set_wait_.Signal();
|
| +
|
| + if (unregister_done_callback_.is_null()) {
|
| + // Expected case - UnregisterForLoopDestruction hasn't been called yet.
|
| + base::MessageLoop::current()->AddDestructionObserver(this);
|
| + working_loop_ = base::MessageLoop::current();
|
| + } else {
|
| + // Rare case which is possible when the model type thread remains
|
| + // blocked for the entire session and UnregisterForLoopDestruction ends
|
| + // up being called before this method. This method is posted unlike
|
| + // UnregisterForLoopDestruction - that's why they can end up being called
|
| + // out of order.
|
| + // In this case we skip the destruction observer registration
|
| + // and just invoke the callback stored at UnregisterForLoopDestruction.
|
| + DCHECK(stopped_);
|
| + unregister_done_callback_.Run(GetModelSafeGroup());
|
| + }
|
| }
|
|
|
| void ModelSafeWorker::UnregisterForLoopDestruction(
|
| base::Callback<void(ModelSafeGroup)> unregister_done_callback) {
|
| - // Ok to wait until |working_loop_| is set because this is called on sync
|
| - // loop.
|
| - working_loop_set_wait_.Wait();
|
| -
|
| - {
|
| - base::AutoLock l(working_loop_lock_);
|
| - if (working_loop_ != NULL) {
|
| - // Should be called on sync loop.
|
| - DCHECK_NE(base::MessageLoop::current(), working_loop_);
|
| - working_loop_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&ModelSafeWorker::UnregisterForLoopDestructionAsync,
|
| - this, unregister_done_callback));
|
| - }
|
| + base::AutoLock l(working_loop_lock_);
|
| + if (working_loop_ != NULL) {
|
| + // Normal case - observer registration has been already done.
|
| + // Delegate to the sync thread to do the actual unregistration in
|
| + // UnregisterForLoopDestructionAsync.
|
| + DCHECK_NE(base::MessageLoop::current(), working_loop_);
|
| + working_loop_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&ModelSafeWorker::UnregisterForLoopDestructionAsync,
|
| + this,
|
| + unregister_done_callback));
|
| + } else {
|
| + // The working loop is still unknown, probably because the model type
|
| + // thread is blocked. Store the callback to be called from
|
| + // SetWorkingLoopToCurrent.
|
| + unregister_done_callback_ = unregister_done_callback;
|
| }
|
| }
|
|
|
|
|