OLD | NEW |
---|---|
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 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/history/core/browser/history_model_worker.h" | 5 #include "components/history/core/browser/history_model_worker.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/synchronization/waitable_event.h" | 9 #include "base/memory/ptr_util.h" |
10 #include "components/history/core/browser/history_db_task.h" | 10 #include "components/history/core/browser/history_db_task.h" |
11 #include "components/history/core/browser/history_service.h" | 11 #include "components/history/core/browser/history_service.h" |
12 #include "components/sync/base/scoped_event_signal.h" | |
13 | 12 |
14 namespace browser_sync { | 13 namespace browser_sync { |
15 | 14 |
16 class WorkerTask : public history::HistoryDBTask { | 15 class WorkerTask : public history::HistoryDBTask { |
17 public: | 16 public: |
18 WorkerTask(const syncer::WorkCallback& work, | 17 WorkerTask(base::OnceClosure work) : work_(std::move(work)) {} |
19 syncer::ScopedEventSignal scoped_event_signal, | |
20 syncer::SyncerError* error) | |
21 : work_(work), | |
22 scoped_event_signal_(std::move(scoped_event_signal)), | |
23 error_(error) {} | |
24 | 18 |
25 bool RunOnDBThread(history::HistoryBackend* backend, | 19 bool RunOnDBThread(history::HistoryBackend* backend, |
26 history::HistoryDatabase* db) override { | 20 history::HistoryDatabase* db) override { |
27 // Signal the completion event at the end of this scope. | 21 std::move(work_).Run(); |
28 auto scoped_event_signal = std::move(scoped_event_signal_); | |
29 | |
30 // Run the task. | |
31 *error_ = work_.Run(); | |
32 | |
33 return true; | 22 return true; |
34 } | 23 } |
35 | 24 |
36 // Since the DoWorkAndWaitUntilDone() is synchronous, we don't need to run | 25 // Since the DoWorkAndWaitUntilDone() is synchronous, we don't need to run |
37 // any code asynchronously on the main thread after completion. | 26 // any code asynchronously on the main thread after completion. |
38 void DoneRunOnMainThread() override {} | 27 void DoneRunOnMainThread() override {} |
39 | 28 |
40 protected: | 29 private: |
41 ~WorkerTask() override { | 30 // A OnceClosure is deleted right after it runs. This is important to unblock |
42 // The event in |scoped_event_signal_| is signaled at the end of this | 31 // DoWorkAndWaitUntilDone() right after the task runs. |
43 // scope if this is destroyed before RunOnDBThread runs. | 32 base::OnceClosure work_; |
44 } | |
45 | 33 |
46 syncer::WorkCallback work_; | 34 DISALLOW_COPY_AND_ASSIGN(WorkerTask); |
47 syncer::ScopedEventSignal scoped_event_signal_; | |
48 syncer::SyncerError* error_; | |
49 }; | |
50 | |
51 class AddDBThreadObserverTask : public history::HistoryDBTask { | |
52 public: | |
53 explicit AddDBThreadObserverTask(base::Closure register_callback) | |
54 : register_callback_(register_callback) {} | |
55 | |
56 bool RunOnDBThread(history::HistoryBackend* backend, | |
57 history::HistoryDatabase* db) override { | |
58 register_callback_.Run(); | |
59 return true; | |
60 } | |
61 | |
62 void DoneRunOnMainThread() override {} | |
63 | |
64 private: | |
65 ~AddDBThreadObserverTask() override {} | |
66 | |
67 base::Closure register_callback_; | |
68 }; | 35 }; |
69 | 36 |
70 namespace { | 37 namespace { |
71 | 38 |
72 // Post the work task on |history_service|'s DB thread from the UI | 39 // Post the work task on |history_service|'s DB thread from the UI |
73 // thread. | 40 // thread. |
74 void PostWorkerTask( | 41 void PostWorkerTask( |
75 const base::WeakPtr<history::HistoryService>& history_service, | 42 const base::WeakPtr<history::HistoryService>& history_service, |
76 const syncer::WorkCallback& work, | 43 base::OnceClosure work, |
77 syncer::ScopedEventSignal scoped_event_signal, | 44 base::CancelableTaskTracker* cancelable_tracker) { |
78 base::CancelableTaskTracker* cancelable_tracker, | |
79 syncer::SyncerError* error) { | |
80 if (history_service.get()) { | 45 if (history_service.get()) { |
81 std::unique_ptr<history::HistoryDBTask> task( | 46 history_service->ScheduleDBTask( |
82 new WorkerTask(work, std::move(scoped_event_signal), error)); | 47 base::MakeUnique<WorkerTask>(std::move(work)), cancelable_tracker); |
83 history_service->ScheduleDBTask(std::move(task), cancelable_tracker); | |
84 } else { | |
85 *error = syncer::CANNOT_DO_WORK; | |
86 // The event in |scoped_event_signal| is signaled at the end of this | |
87 // scope. | |
88 } | 48 } |
89 } | 49 } |
90 | 50 |
91 } // namespace | 51 } // namespace |
92 | 52 |
93 HistoryModelWorker::HistoryModelWorker( | 53 HistoryModelWorker::HistoryModelWorker( |
94 const base::WeakPtr<history::HistoryService>& history_service, | 54 const base::WeakPtr<history::HistoryService>& history_service, |
95 const scoped_refptr<base::SingleThreadTaskRunner>& ui_thread) | 55 const scoped_refptr<base::SingleThreadTaskRunner>& ui_thread) |
96 : history_service_(history_service), ui_thread_(ui_thread) { | 56 : history_service_(history_service), ui_thread_(ui_thread) { |
97 CHECK(history_service.get()); | 57 CHECK(history_service.get()); |
98 DCHECK(ui_thread_->BelongsToCurrentThread()); | 58 DCHECK(ui_thread_->BelongsToCurrentThread()); |
99 cancelable_tracker_.reset(new base::CancelableTaskTracker); | 59 cancelable_tracker_.reset(new base::CancelableTaskTracker); |
100 } | 60 } |
101 | 61 |
102 syncer::SyncerError HistoryModelWorker::DoWorkAndWaitUntilDoneImpl( | |
103 const syncer::WorkCallback& work) { | |
104 syncer::SyncerError error = syncer::UNSET; | |
105 | |
106 // Signaled after the task runs or when it is abandoned. | |
107 base::WaitableEvent work_done_or_abandoned( | |
108 base::WaitableEvent::ResetPolicy::AUTOMATIC, | |
109 base::WaitableEvent::InitialState::NOT_SIGNALED); | |
110 | |
111 if (ui_thread_->PostTask(FROM_HERE, | |
112 base::Bind(&PostWorkerTask, history_service_, work, | |
113 base::Passed(syncer::ScopedEventSignal( | |
114 &work_done_or_abandoned)), | |
115 cancelable_tracker_.get(), &error))) { | |
116 work_done_or_abandoned.Wait(); | |
117 } else { | |
118 error = syncer::CANNOT_DO_WORK; | |
119 } | |
120 return error; | |
121 } | |
122 | |
123 syncer::ModelSafeGroup HistoryModelWorker::GetModelSafeGroup() { | 62 syncer::ModelSafeGroup HistoryModelWorker::GetModelSafeGroup() { |
124 return syncer::GROUP_HISTORY; | 63 return syncer::GROUP_HISTORY; |
125 } | 64 } |
126 | 65 |
127 bool HistoryModelWorker::IsOnModelThread() { | 66 bool HistoryModelWorker::IsOnModelThread() { |
128 // Ideally HistoryService would expose a way to check whether this is the | 67 // Ideally HistoryService would expose a way to check whether this is the |
129 // history DB thread. Since it doesn't, just return true to bypass a CHECK in | 68 // history DB thread. Since it doesn't, just return true to bypass a CHECK in |
130 // the sync code. | 69 // the sync code. |
131 return true; | 70 return true; |
132 } | 71 } |
133 | 72 |
134 HistoryModelWorker::~HistoryModelWorker() { | 73 HistoryModelWorker::~HistoryModelWorker() { |
135 // The base::CancelableTaskTracker class is not thread-safe and must only be | 74 // The base::CancelableTaskTracker class is not thread-safe and must only be |
136 // used from a single thread but the current object may not be destroyed from | 75 // used from a single thread but the current object may not be destroyed from |
137 // the UI thread, so delete it from the UI thread. | 76 // the UI thread, so delete it from the UI thread. |
138 ui_thread_->DeleteSoon(FROM_HERE, cancelable_tracker_.release()); | 77 ui_thread_->DeleteSoon(FROM_HERE, cancelable_tracker_.release()); |
139 } | 78 } |
140 | 79 |
80 void HistoryModelWorker::ScheduleWork(base::Closure work) { | |
81 ui_thread_->PostTask( | |
82 FROM_HERE, base::Bind(&PostWorkerTask, history_service_, std::move(work), | |
skym
2017/04/06 00:34:54
Is the Closure implicitly converted to a OnceClosu
fdoray
2017/04/06 18:10:55
Yes, a Closure can be implicitly converted to Once
| |
83 cancelable_tracker_.get())); | |
84 } | |
85 | |
141 } // namespace browser_sync | 86 } // namespace browser_sync |
OLD | NEW |