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 2aea5cf8378b0b9dbc1350410bdea6b19f8fe2a1..eb3fc1f1c3ec286c961e743b23b05e77a7eae358 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_(NULL), |
+ working_loop_set_wait_(true, false) {} |
ModelSafeWorker::~ModelSafeWorker() {} |
@@ -135,42 +135,26 @@ void ModelSafeWorker::WillDestroyCurrentMessageLoop() { |
void ModelSafeWorker::SetWorkingLoopToCurrent() { |
base::AutoLock l(working_loop_lock_); |
DCHECK(!working_loop_); |
- |
- 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()); |
- } |
+ working_loop_ = base::MessageLoop::current(); |
+ working_loop_set_wait_.Signal(); |
} |
void ModelSafeWorker::UnregisterForLoopDestruction( |
base::Callback<void(ModelSafeGroup)> 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; |
+ // 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)); |
+ } |
} |
} |