OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 #ifndef CHROME_BROWSER_SYNC_GLUE_BOOKMARK_MODEL_WORKER_H_ | 5 #ifndef CHROME_BROWSER_SYNC_GLUE_BOOKMARK_MODEL_WORKER_H_ |
6 #define CHROME_BROWSER_SYNC_GLUE_BOOKMARK_MODEL_WORKER_H_ | 6 #define CHROME_BROWSER_SYNC_GLUE_BOOKMARK_MODEL_WORKER_H_ |
7 | 7 |
| 8 #include "base/condition_variable.h" |
8 #include "base/lock.h" | 9 #include "base/lock.h" |
9 #include "base/task.h" | 10 #include "base/task.h" |
10 #include "base/waitable_event.h" | 11 #include "base/waitable_event.h" |
11 #include "chrome/browser/sync/engine/syncapi.h" | 12 #include "chrome/browser/sync/engine/syncapi.h" |
12 | 13 |
13 class MessageLoop; | 14 class MessageLoop; |
14 | 15 |
15 namespace browser_sync { | 16 namespace browser_sync { |
16 | 17 |
17 // A ModelSafeWorker for bookmarks that accepts work requests from the syncapi | 18 // A ModelSafeWorker for bookmarks that accepts work requests from the syncapi |
18 // that need to be fulfilled from the MessageLoop home to the BookmarkModel | 19 // that need to be fulfilled from the MessageLoop home to the BookmarkModel |
19 // (this is typically the "main" UI thread). | 20 // (this is typically the "main" UI thread). |
20 // | 21 // |
21 // Lifetime note: Instances of this class will generally be owned by the | 22 // Lifetime note: Instances of this class will generally be owned by the |
22 // SyncerThread. When the SyncerThread _object_ is destroyed, the | 23 // SyncerThread. When the SyncerThread _object_ is destroyed, the |
23 // BookmarkModelWorker will be destroyed. The SyncerThread object is destroyed | 24 // BookmarkModelWorker will be destroyed. The SyncerThread object is destroyed |
24 // after the actual syncer pthread has exited. | 25 // after the actual syncer pthread has exited. |
25 class BookmarkModelWorker | 26 class BookmarkModelWorker |
26 : public sync_api::ModelSafeWorkerInterface { | 27 : public sync_api::ModelSafeWorkerInterface { |
27 public: | 28 public: |
28 explicit BookmarkModelWorker(MessageLoop* bookmark_model_loop) | 29 explicit BookmarkModelWorker(MessageLoop* bookmark_model_loop) |
29 : state_(WORKING), | 30 : state_(WORKING), |
30 pending_work_(NULL), | 31 pending_work_(NULL), |
31 syncapi_has_shutdown_(false), | 32 syncapi_has_shutdown_(false), |
32 bookmark_model_loop_(bookmark_model_loop), | 33 bookmark_model_loop_(bookmark_model_loop), |
33 syncapi_event_(false, false) { | 34 syncapi_event_(&lock_) { |
34 } | 35 } |
35 virtual ~BookmarkModelWorker(); | 36 virtual ~BookmarkModelWorker(); |
36 | 37 |
37 // A simple task to signal a waitable event after calling DoWork on a visitor. | 38 // A simple task to signal a waitable event after calling DoWork on a visitor. |
38 class CallDoWorkAndSignalTask : public Task { | 39 class CallDoWorkAndSignalTask : public Task { |
39 public: | 40 public: |
40 CallDoWorkAndSignalTask(ModelSafeWorkerInterface::Visitor* visitor, | 41 CallDoWorkAndSignalTask(ModelSafeWorkerInterface::Visitor* visitor, |
41 base::WaitableEvent* work_done, | 42 base::WaitableEvent* work_done, |
42 BookmarkModelWorker* scheduler) | 43 BookmarkModelWorker* scheduler) |
43 : visitor_(visitor), work_done_(work_done), scheduler_(scheduler) { | 44 : visitor_(visitor), work_done_(work_done), scheduler_(scheduler) { |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
98 | 99 |
99 // This is set by the UI thread, but is not explicitly thread safe, so only | 100 // This is set by the UI thread, but is not explicitly thread safe, so only |
100 // read this value from other threads when you know it is absolutely safe (e.g | 101 // read this value from other threads when you know it is absolutely safe (e.g |
101 // there is _no_ way we can be in CallDoWork with state_ = STOPPED, so it is | 102 // there is _no_ way we can be in CallDoWork with state_ = STOPPED, so it is |
102 // safe to read / compare in this case). | 103 // safe to read / compare in this case). |
103 State state_; | 104 State state_; |
104 | 105 |
105 // We keep a reference to any task we have scheduled so we can gracefully | 106 // We keep a reference to any task we have scheduled so we can gracefully |
106 // force them to run if the syncer is trying to shutdown. | 107 // force them to run if the syncer is trying to shutdown. |
107 Task* pending_work_; | 108 Task* pending_work_; |
108 Lock pending_work_lock_; | |
109 | 109 |
110 // Set by the SyncCoreThread when Syncapi shutdown has completed and the | 110 // Set by the SyncCoreThread when Syncapi shutdown has completed and the |
111 // SyncerThread has terminated, so no more work will be scheduled. Read by | 111 // SyncerThread has terminated, so no more work will be scheduled. Read by |
112 // the UI thread in Stop(). | 112 // the UI thread in Stop(). |
113 bool syncapi_has_shutdown_; | 113 bool syncapi_has_shutdown_; |
114 | 114 |
115 // The BookmarkModel's home-sweet-home MessageLoop. | 115 // The BookmarkModel's home-sweet-home MessageLoop. |
116 MessageLoop* const bookmark_model_loop_; | 116 MessageLoop* const bookmark_model_loop_; |
117 | 117 |
| 118 // We use a Lock for all data members and a ConditionVariable to synchronize. |
| 119 // We do this instead of using a WaitableEvent and a bool condition in order |
| 120 // to guard against races that could arise due to the fact that the lack of a |
| 121 // barrier permits instructions to be reordered by compiler optimizations. |
| 122 // Possible or not, that route makes for very fragile code due to existence |
| 123 // of theoretical races. |
| 124 Lock lock_; |
| 125 |
118 // Used as a barrier at shutdown to ensure the SyncerThread terminates before | 126 // Used as a barrier at shutdown to ensure the SyncerThread terminates before |
119 // we allow the UI thread to return from Stop(). This gets signalled whenever | 127 // we allow the UI thread to return from Stop(). This gets signalled whenever |
120 // one of two events occur: a new pending_work_ task was scheduled, or the | 128 // one of two events occur: a new pending_work_ task was scheduled, or the |
121 // SyncerThread has terminated. We only care about (1) when we are in Stop(), | 129 // SyncerThread has terminated. We only care about (1) when we are in Stop(), |
122 // because we have to manually Run() the task. | 130 // because we have to manually Run() the task. |
123 base::WaitableEvent syncapi_event_; | 131 ConditionVariable syncapi_event_; |
124 | 132 |
125 DISALLOW_COPY_AND_ASSIGN(BookmarkModelWorker); | 133 DISALLOW_COPY_AND_ASSIGN(BookmarkModelWorker); |
126 }; | 134 }; |
127 | 135 |
128 } // namespace browser_sync | 136 } // namespace browser_sync |
129 | 137 |
130 #endif // CHROME_BROWSER_SYNC_GLUE_BOOKMARK_MODEL_WORKER_H_ | 138 #endif // CHROME_BROWSER_SYNC_GLUE_BOOKMARK_MODEL_WORKER_H_ |
OLD | NEW |