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

Side by Side Diff: components/sync/engine/model_safe_worker.cc

Issue 2471183003: Do not observe MessageLoop destruction from ModelSafeWorker. (Closed)
Patch Set: CR maxbogue #22 Created 4 years, 1 month 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
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/sync/engine/model_safe_worker.h" 5 #include "components/sync/engine/model_safe_worker.h"
6 6
7 #include "base/bind.h"
8 #include "base/json/json_writer.h" 7 #include "base/json/json_writer.h"
9 #include "base/threading/thread_task_runner_handle.h"
10 #include "base/values.h" 8 #include "base/values.h"
11 9
12 namespace syncer { 10 namespace syncer {
13 11
14 std::unique_ptr<base::DictionaryValue> ModelSafeRoutingInfoToValue( 12 std::unique_ptr<base::DictionaryValue> ModelSafeRoutingInfoToValue(
15 const ModelSafeRoutingInfo& routing_info) { 13 const ModelSafeRoutingInfo& routing_info) {
16 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); 14 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
17 for (ModelSafeRoutingInfo::const_iterator it = routing_info.begin(); 15 for (ModelSafeRoutingInfo::const_iterator it = routing_info.begin();
18 it != routing_info.end(); ++it) { 16 it != routing_info.end(); ++it) {
19 dict->SetString(ModelTypeToString(it->first), 17 dict->SetString(ModelTypeToString(it->first),
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
64 case GROUP_PASSWORD: 62 case GROUP_PASSWORD:
65 return "GROUP_PASSWORD"; 63 return "GROUP_PASSWORD";
66 case GROUP_NON_BLOCKING: 64 case GROUP_NON_BLOCKING:
67 return "GROUP_NON_BLOCKING"; 65 return "GROUP_NON_BLOCKING";
68 default: 66 default:
69 NOTREACHED(); 67 NOTREACHED();
70 return "INVALID"; 68 return "INVALID";
71 } 69 }
72 } 70 }
73 71
74 ModelSafeWorker::ModelSafeWorker(WorkerLoopDestructionObserver* observer) 72 ModelSafeWorker::ModelSafeWorker() = default;
maxbogue 2016/11/04 17:34:57 Is there some reason "= default;" is preferable to
fdoray 2016/11/04 17:56:50 For copy/move constructor yes, but not for default
75 : stopped_(false), 73 ModelSafeWorker::~ModelSafeWorker() = default;
76 observer_(observer) {}
77
78 ModelSafeWorker::~ModelSafeWorker() {}
79 74
80 void ModelSafeWorker::RequestStop() { 75 void ModelSafeWorker::RequestStop() {
81 base::AutoLock al(stopped_lock_);
82
83 // Set stop flag. This prevents any *further* tasks from being posted to 76 // Set stop flag. This prevents any *further* tasks from being posted to
84 // worker threads (see DoWorkAndWaitUntilDone below), but note that one may 77 // worker threads (see DoWorkAndWaitUntilDone below), but note that one may
85 // already be posted. 78 // already be posted.
86 stopped_ = true; 79 stopped_.Set();
87 } 80 }
88 81
89 SyncerError ModelSafeWorker::DoWorkAndWaitUntilDone(const WorkCallback& work) { 82 SyncerError ModelSafeWorker::DoWorkAndWaitUntilDone(const WorkCallback& work) {
90 { 83 if (stopped_.IsSet())
91 base::AutoLock al(stopped_lock_); 84 return CANNOT_DO_WORK;
92 if (stopped_)
93 return CANNOT_DO_WORK;
94 }
95
96 return DoWorkAndWaitUntilDoneImpl(work); 85 return DoWorkAndWaitUntilDoneImpl(work);
97 } 86 }
98 87
99 bool ModelSafeWorker::IsStopped() { 88 bool ModelSafeWorker::IsStopped() {
100 base::AutoLock al(stopped_lock_); 89 return stopped_.IsSet();
101 return stopped_;
102 }
103
104 void ModelSafeWorker::WillDestroyCurrentMessageLoop() {
105 {
106 base::AutoLock al(stopped_lock_);
107 stopped_ = true;
108
109 DVLOG(1) << ModelSafeGroupToString(GetModelSafeGroup())
110 << " worker stops on destruction of its working thread.";
111 }
112
113 {
114 base::AutoLock l(working_task_runner_lock_);
115 working_task_runner_ = nullptr;
116 }
117
118 if (observer_)
119 observer_->OnWorkerLoopDestroyed(GetModelSafeGroup());
120 }
121
122 void ModelSafeWorker::SetWorkingLoopToCurrent() {
123 base::Callback<void(ModelSafeGroup)> unregister_done_callback;
124
125 {
126 base::AutoLock l(working_task_runner_lock_);
127 DCHECK(!working_task_runner_);
128
129 if (unregister_done_callback_.is_null()) {
130 // Expected case - UnregisterForLoopDestruction hasn't been called yet.
131 base::MessageLoop::current()->AddDestructionObserver(this);
132 working_task_runner_ = base::ThreadTaskRunnerHandle::Get();
133 } else {
134 // Rare case which is possible when the model type thread remains
135 // blocked for the entire session and UnregisterForLoopDestruction ends
136 // up being called before this method. This method is posted unlike
137 // UnregisterForLoopDestruction - that's why they can end up being called
138 // out of order.
139 // In this case we skip the destruction observer registration
140 // and just invoke the callback stored at UnregisterForLoopDestruction.
141 DCHECK(stopped_);
142 unregister_done_callback = unregister_done_callback_;
143 unregister_done_callback_.Reset();
144 }
145 }
146
147 if (!unregister_done_callback.is_null()) {
148 unregister_done_callback.Run(GetModelSafeGroup());
149 }
150 }
151
152 void ModelSafeWorker::UnregisterForLoopDestruction(
153 base::Callback<void(ModelSafeGroup)> unregister_done_callback) {
154 base::AutoLock l(working_task_runner_lock_);
155 if (working_task_runner_) {
156 // Normal case - observer registration has been already done.
157 // Delegate to the sync thread to do the actual unregistration in
158 // UnregisterForLoopDestructionAsync.
159 DCHECK(!working_task_runner_->BelongsToCurrentThread());
160 working_task_runner_->PostTask(
161 FROM_HERE,
162 base::Bind(&ModelSafeWorker::UnregisterForLoopDestructionAsync, this,
163 unregister_done_callback));
164 } else {
165 // The working loop is still unknown, probably because the model type
166 // thread is blocked. Store the callback to be called from
167 // SetWorkingLoopToCurrent.
168 unregister_done_callback_ = unregister_done_callback;
169 }
170 }
171
172 void ModelSafeWorker::UnregisterForLoopDestructionAsync(
173 base::Callback<void(ModelSafeGroup)> unregister_done_callback) {
174 {
175 base::AutoLock l(working_task_runner_lock_);
176 if (!working_task_runner_)
177 return;
178 DCHECK(working_task_runner_->BelongsToCurrentThread());
179 }
180
181 DCHECK(stopped_);
182 base::MessageLoop::current()->RemoveDestructionObserver(this);
183 unregister_done_callback.Run(GetModelSafeGroup());
184 } 90 }
185 91
186 } // namespace syncer 92 } // namespace syncer
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698