• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #ifndef SYNC_INTERNAL_API_PUBLIC_ENGINE_MODEL_SAFE_WORKER_H_
6 #define SYNC_INTERNAL_API_PUBLIC_ENGINE_MODEL_SAFE_WORKER_H_
7 
8 #include <map>
9 #include <string>
10 #include <vector>
11 
12 #include "base/callback.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/synchronization/lock.h"
16 #include "base/synchronization/waitable_event.h"
17 #include "sync/base/sync_export.h"
18 #include "sync/internal_api/public/base/model_type.h"
19 #include "sync/internal_api/public/util/syncer_error.h"
20 
21 namespace base {
22 class DictionaryValue;
23 }  // namespace
24 
25 namespace syncer {
26 
27 // TODO(akalin): Move the non-exported functions in this file to a
28 // private header.
29 
30 typedef base::Callback<enum SyncerError(void)> WorkCallback;
31 
32 enum ModelSafeGroup {
33   GROUP_PASSIVE = 0,   // Models that are just "passively" being synced; e.g.
34                        // changes to these models don't need to be pushed to a
35                        // native model.
36   GROUP_UI,            // Models that live on UI thread and are being synced.
37   GROUP_DB,            // Models that live on DB thread and are being synced.
38   GROUP_FILE,          // Models that live on FILE thread and are being synced.
39   GROUP_HISTORY,       // Models that live on history thread and are being
40                        // synced.
41   GROUP_PASSWORD,      // Models that live on the password thread and are
42                        // being synced.  On windows and linux, this runs on the
43                        // DB thread.
44   MODEL_SAFE_GROUP_COUNT,
45 };
46 
47 SYNC_EXPORT std::string ModelSafeGroupToString(ModelSafeGroup group);
48 
49 // WorkerLoopDestructionObserver is notified when the thread where it works
50 // is going to be destroyed.
51 class WorkerLoopDestructionObserver {
52  public:
53   virtual void OnWorkerLoopDestroyed(ModelSafeGroup group) = 0;
54 };
55 
56 // The Syncer uses a ModelSafeWorker for all tasks that could potentially
57 // modify syncable entries (e.g under a WriteTransaction). The ModelSafeWorker
58 // only knows how to do one thing, and that is take some work (in a fully
59 // pre-bound callback) and have it performed (as in Run()) from a thread which
60 // is guaranteed to be "model-safe", where "safe" refers to not allowing us to
61 // cause an embedding application model to fall out of sync with the
62 // syncable::Directory due to a race. Each ModelSafeWorker is affiliated with
63 // a thread and does actual work on that thread. On the destruction of that
64 // thread, the affiliated worker is effectively disabled to do more
65 // work and will notify its observer.
66 class SYNC_EXPORT ModelSafeWorker
67     : public base::RefCountedThreadSafe<ModelSafeWorker>,
68       public base::MessageLoop::DestructionObserver {
69  public:
70   // Subclass should implement to observe destruction of the loop where
71   // it actually does work. Called on UI thread immediately after worker is
72   // created.
73   virtual void RegisterForLoopDestruction() = 0;
74 
75   // Called on sync loop from SyncBackendRegistrar::ShutDown(). Post task to
76   // working loop to stop observing loop destruction and invoke
77   // |unregister_done_callback|.
78   virtual void UnregisterForLoopDestruction(
79       base::Callback<void(ModelSafeGroup)> unregister_done_callback);
80 
81   // If not stopped, call DoWorkAndWaitUntilDoneImpl() to do work. Otherwise
82   // return CANNOT_DO_WORK.
83   SyncerError DoWorkAndWaitUntilDone(const WorkCallback& work);
84 
85   // Soft stop worker by setting stopped_ flag. Called when sync is disabled
86   // or browser is shutting down. Called on UI loop.
87   virtual void RequestStop();
88 
89   virtual ModelSafeGroup GetModelSafeGroup() = 0;
90 
91   // MessageLoop::DestructionObserver implementation.
92   virtual void WillDestroyCurrentMessageLoop() OVERRIDE;
93 
94  protected:
95   friend class base::RefCountedThreadSafe<ModelSafeWorker>;
96 
97   explicit ModelSafeWorker(WorkerLoopDestructionObserver* observer);
98   virtual ~ModelSafeWorker();
99 
100   // Any time the Syncer performs model modifications (e.g employing a
101   // WriteTransaction), it should be done by this method to ensure it is done
102   // from a model-safe thread.
103   virtual SyncerError DoWorkAndWaitUntilDoneImpl(const WorkCallback& work) = 0;
104 
work_done_or_stopped()105   base::WaitableEvent* work_done_or_stopped() {
106     return &work_done_or_stopped_;
107   }
108 
109   // Return true if the worker was stopped. Thread safe.
110   bool IsStopped();
111 
112   // Subclass should call this in RegisterForLoopDestruction() from the loop
113   // where work is done.
114   void SetWorkingLoopToCurrent();
115 
116  private:
117   void UnregisterForLoopDestructionAsync(
118       base::Callback<void(ModelSafeGroup)> unregister_done_callback);
119 
120   // Whether the worker should/can do more work. Set when sync is disabled or
121   // when the worker's working thread is to be destroyed.
122   base::Lock stopped_lock_;
123   bool stopped_;
124 
125   // Signal set when work on native thread is finished or when native thread
126   // is to be destroyed so no more work can be done.
127   base::WaitableEvent work_done_or_stopped_;
128 
129   // Notified when working thread of the worker is to be destroyed.
130   WorkerLoopDestructionObserver* observer_;
131 
132   // Remember working loop for posting task to unregister destruction
133   // observation from sync thread when shutting down sync.
134   base::Lock working_loop_lock_;
135   base::MessageLoop* working_loop_;
136 
137   // Callback passed with UnregisterForLoopDestruction. Normally this
138   // remains unset/unused and is stored only if |working_loop_| isn't
139   // initialized by the time UnregisterForLoopDestruction is called.
140   // It is safe to copy and thread safe.
141   // See comments in model_safe_worker.cc for more details.
142   base::Callback<void(ModelSafeGroup)> unregister_done_callback_;
143 };
144 
145 // A map that details which ModelSafeGroup each ModelType
146 // belongs to.  Routing info can change in response to the user enabling /
147 // disabling sync for certain types, as well as model association completions.
148 typedef std::map<ModelType, ModelSafeGroup> ModelSafeRoutingInfo;
149 
150 // Caller takes ownership of return value.
151 SYNC_EXPORT_PRIVATE base::DictionaryValue* ModelSafeRoutingInfoToValue(
152     const ModelSafeRoutingInfo& routing_info);
153 
154 SYNC_EXPORT std::string ModelSafeRoutingInfoToString(
155     const ModelSafeRoutingInfo& routing_info);
156 
157 SYNC_EXPORT ModelTypeSet GetRoutingInfoTypes(
158     const ModelSafeRoutingInfo& routing_info);
159 
160 SYNC_EXPORT ModelSafeGroup GetGroupForModelType(
161     const ModelType type,
162     const ModelSafeRoutingInfo& routes);
163 
164 }  // namespace syncer
165 
166 #endif  // SYNC_INTERNAL_API_PUBLIC_ENGINE_MODEL_SAFE_WORKER_H_
167