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