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 d7bf906ef9f007feec43925789b22a3367a3e15c..3e2096a9423d6f79e6cb1f961347ea1788a8d28f 100644 |
--- a/sync/internal_api/public/engine/model_safe_worker.cc |
+++ b/sync/internal_api/public/engine/model_safe_worker.cc |
@@ -80,6 +80,58 @@ std::string ModelSafeGroupToString(ModelSafeGroup group) { |
} |
} |
+ModelSafeWorker::ModelSafeWorker(WorkerLoopDestructionObserver* observer) |
+ : stopped_(false), |
+ work_done_or_stopped_(false, false), |
+ observer_(observer) {} |
+ |
ModelSafeWorker::~ModelSafeWorker() {} |
+void ModelSafeWorker::RequestStop() { |
+ base::AutoLock al(stopped_lock_); |
+ |
+ // Set stop flag but don't signal work_done_or_stopped_ to unblock sync loop |
+ // because the worker may be working and depending on sync command object |
+ // living on sync thread. his prevents any *further* tasks from being posted |
+ // to worker threads (see DoWorkAndWaitUntilDone below), but note that one |
+ // may already be posted. |
+ stopped_ = true; |
+} |
+ |
+SyncerError ModelSafeWorker::DoWorkAndWaitUntilDone(const WorkCallback& work) { |
+ { |
+ base::AutoLock al(stopped_lock_); |
+ if (stopped_) |
+ return CANNOT_DO_WORK; |
+ |
+ CHECK(!work_done_or_stopped_.IsSignaled()); |
+ } |
+ |
+ return DoWorkAndWaitUntilDoneImpl(work); |
+} |
+ |
+bool ModelSafeWorker::IsStopped() { |
+ base::AutoLock al(stopped_lock_); |
+ return stopped_; |
+} |
+ |
+void ModelSafeWorker::WillDestroyCurrentMessageLoop() { |
+ { |
+ base::AutoLock al(stopped_lock_); |
+ stopped_ = true; |
+ |
+ // Must signal to unblock syncer if it's waiting for a posted task to |
+ // finish. At this point, all pending tasks posted to the loop have been |
+ // destroyed (see MessageLoop::~MessageLoop). So syncer will be blocked |
+ // indefinitely without signaling here. |
+ work_done_or_stopped_.Signal(); |
+ |
+ DVLOG(1) << ModelSafeGroupToString(GetModelSafeGroup()) |
+ << " worker stops on destruction of its working thread."; |
+ } |
+ |
+ if (observer_) |
+ observer_->OnWorkerLoopDestroyed(GetModelSafeGroup()); |
+} |
+ |
} // namespace syncer |