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