Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(858)

Side by Side Diff: sync/internal_api/public/engine/model_safe_worker.cc

Issue 2130453004: [Sync] Move //sync to //components/sync. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "sync/internal_api/public/engine/model_safe_worker.h"
6
7 #include <memory>
8
9 #include "base/bind.h"
10 #include "base/json/json_writer.h"
11 #include "base/threading/thread_task_runner_handle.h"
12 #include "base/values.h"
13
14 namespace syncer {
15
16 std::unique_ptr<base::DictionaryValue> ModelSafeRoutingInfoToValue(
17 const ModelSafeRoutingInfo& routing_info) {
18 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
19 for (ModelSafeRoutingInfo::const_iterator it = routing_info.begin();
20 it != routing_info.end(); ++it) {
21 dict->SetString(ModelTypeToString(it->first),
22 ModelSafeGroupToString(it->second));
23 }
24 return dict;
25 }
26
27 std::string ModelSafeRoutingInfoToString(
28 const ModelSafeRoutingInfo& routing_info) {
29 std::string json;
30 base::JSONWriter::Write(*ModelSafeRoutingInfoToValue(routing_info), &json);
31 return json;
32 }
33
34 ModelTypeSet GetRoutingInfoTypes(const ModelSafeRoutingInfo& routing_info) {
35 ModelTypeSet types;
36 for (ModelSafeRoutingInfo::const_iterator it = routing_info.begin();
37 it != routing_info.end(); ++it) {
38 types.Put(it->first);
39 }
40 return types;
41 }
42
43 ModelSafeGroup GetGroupForModelType(const ModelType type,
44 const ModelSafeRoutingInfo& routes) {
45 ModelSafeRoutingInfo::const_iterator it = routes.find(type);
46 if (it == routes.end()) {
47 if (type != UNSPECIFIED && type != TOP_LEVEL_FOLDER)
48 DVLOG(1) << "Entry does not belong to active ModelSafeGroup!";
49 return GROUP_PASSIVE;
50 }
51 return it->second;
52 }
53
54 std::string ModelSafeGroupToString(ModelSafeGroup group) {
55 switch (group) {
56 case GROUP_UI:
57 return "GROUP_UI";
58 case GROUP_DB:
59 return "GROUP_DB";
60 case GROUP_FILE:
61 return "GROUP_FILE";
62 case GROUP_HISTORY:
63 return "GROUP_HISTORY";
64 case GROUP_PASSIVE:
65 return "GROUP_PASSIVE";
66 case GROUP_PASSWORD:
67 return "GROUP_PASSWORD";
68 case GROUP_NON_BLOCKING:
69 return "GROUP_NON_BLOCKING";
70 default:
71 NOTREACHED();
72 return "INVALID";
73 }
74 }
75
76 ModelSafeWorker::ModelSafeWorker(WorkerLoopDestructionObserver* observer)
77 : stopped_(false),
78 work_done_or_stopped_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
79 base::WaitableEvent::InitialState::NOT_SIGNALED),
80 observer_(observer) {}
81
82 ModelSafeWorker::~ModelSafeWorker() {}
83
84 void ModelSafeWorker::RequestStop() {
85 base::AutoLock al(stopped_lock_);
86
87 // Set stop flag but don't signal work_done_or_stopped_ to unblock sync loop
88 // because the worker may be working and depending on sync command object
89 // living on sync thread. This prevents any *further* tasks from being posted
90 // to worker threads (see DoWorkAndWaitUntilDone below), but note that one
91 // may already be posted.
92 stopped_ = true;
93 }
94
95 SyncerError ModelSafeWorker::DoWorkAndWaitUntilDone(const WorkCallback& work) {
96 {
97 base::AutoLock al(stopped_lock_);
98 if (stopped_)
99 return CANNOT_DO_WORK;
100
101 CHECK(!work_done_or_stopped_.IsSignaled());
102 }
103
104 return DoWorkAndWaitUntilDoneImpl(work);
105 }
106
107 bool ModelSafeWorker::IsStopped() {
108 base::AutoLock al(stopped_lock_);
109 return stopped_;
110 }
111
112 void ModelSafeWorker::WillDestroyCurrentMessageLoop() {
113 {
114 base::AutoLock al(stopped_lock_);
115 stopped_ = true;
116
117 // Must signal to unblock syncer if it's waiting for a posted task to
118 // finish. At this point, all pending tasks posted to the loop have been
119 // destroyed (see MessageLoop::~MessageLoop). So syncer will be blocked
120 // indefinitely without signaling here.
121 work_done_or_stopped_.Signal();
122
123 DVLOG(1) << ModelSafeGroupToString(GetModelSafeGroup())
124 << " worker stops on destruction of its working thread.";
125 }
126
127 {
128 base::AutoLock l(working_task_runner_lock_);
129 working_task_runner_ = NULL;
130 }
131
132 if (observer_)
133 observer_->OnWorkerLoopDestroyed(GetModelSafeGroup());
134 }
135
136 void ModelSafeWorker::SetWorkingLoopToCurrent() {
137 base::Callback<void(ModelSafeGroup)> unregister_done_callback;
138
139 {
140 base::AutoLock l(working_task_runner_lock_);
141 DCHECK(!working_task_runner_);
142
143 if (unregister_done_callback_.is_null()) {
144 // Expected case - UnregisterForLoopDestruction hasn't been called yet.
145 base::MessageLoop::current()->AddDestructionObserver(this);
146 working_task_runner_ = base::ThreadTaskRunnerHandle::Get();
147 } else {
148 // Rare case which is possible when the model type thread remains
149 // blocked for the entire session and UnregisterForLoopDestruction ends
150 // up being called before this method. This method is posted unlike
151 // UnregisterForLoopDestruction - that's why they can end up being called
152 // out of order.
153 // In this case we skip the destruction observer registration
154 // and just invoke the callback stored at UnregisterForLoopDestruction.
155 DCHECK(stopped_);
156 unregister_done_callback = unregister_done_callback_;
157 unregister_done_callback_.Reset();
158 }
159 }
160
161 if (!unregister_done_callback.is_null()) {
162 unregister_done_callback.Run(GetModelSafeGroup());
163 }
164 }
165
166 void ModelSafeWorker::UnregisterForLoopDestruction(
167 base::Callback<void(ModelSafeGroup)> unregister_done_callback) {
168 base::AutoLock l(working_task_runner_lock_);
169 if (working_task_runner_) {
170 // Normal case - observer registration has been already done.
171 // Delegate to the sync thread to do the actual unregistration in
172 // UnregisterForLoopDestructionAsync.
173 DCHECK(!working_task_runner_->BelongsToCurrentThread());
174 working_task_runner_->PostTask(
175 FROM_HERE,
176 base::Bind(&ModelSafeWorker::UnregisterForLoopDestructionAsync, this,
177 unregister_done_callback));
178 } else {
179 // The working loop is still unknown, probably because the model type
180 // thread is blocked. Store the callback to be called from
181 // SetWorkingLoopToCurrent.
182 unregister_done_callback_ = unregister_done_callback;
183 }
184 }
185
186 void ModelSafeWorker::UnregisterForLoopDestructionAsync(
187 base::Callback<void(ModelSafeGroup)> unregister_done_callback) {
188 {
189 base::AutoLock l(working_task_runner_lock_);
190 if (!working_task_runner_)
191 return;
192 DCHECK(working_task_runner_->BelongsToCurrentThread());
193 }
194
195 DCHECK(stopped_);
196 base::MessageLoop::current()->RemoveDestructionObserver(this);
197 unregister_done_callback.Run(GetModelSafeGroup());
198 }
199
200 } // namespace syncer
OLDNEW
« no previous file with comments | « sync/internal_api/public/engine/model_safe_worker.h ('k') | sync/internal_api/public/engine/model_safe_worker_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698