1 // Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights 2 // reserved. Use of this source code is governed by a BSD-style license that 3 // can be found in the LICENSE file. 4 5 #ifndef CEF_LIBCEF_COMMON_VALUE_BASE_H_ 6 #define CEF_LIBCEF_COMMON_VALUE_BASE_H_ 7 #pragma once 8 9 #include <map> 10 #include <set> 11 #include "include/cef_base.h" 12 13 #include "base/logging.h" 14 #include "base/memory/ref_counted.h" 15 #include "base/notreached.h" 16 #include "base/synchronization/lock.h" 17 #include "base/thread_annotations.h" 18 #include "base/threading/platform_thread.h" 19 20 // Controller implementation base class. 21 class CefValueController 22 : public base::RefCountedThreadSafe<CefValueController> { 23 public: 24 // Implemented by a class controlled using the access controller. 25 class Object { 26 public: ~Object()27 virtual ~Object() {} 28 29 // Called when the value has been removed. 30 virtual void OnControlRemoved() = 0; 31 }; 32 33 // Encapsulates context locking and verification logic. 34 class AutoLock { 35 public: AutoLock(CefValueController * impl)36 explicit AutoLock(CefValueController* impl) 37 : impl_(impl), verified_(impl && impl->VerifyThread()) { 38 DCHECK(impl); 39 if (verified_) 40 impl_->lock(); 41 } ~AutoLock()42 ~AutoLock() { 43 if (verified_) 44 impl_->unlock(); 45 } 46 verified()47 inline bool verified() { return verified_; } 48 49 private: 50 scoped_refptr<CefValueController> impl_; 51 bool verified_; 52 53 DISALLOW_COPY_AND_ASSIGN(AutoLock); 54 }; 55 56 CefValueController(); 57 58 // Returns true if this controller is thread safe. 59 virtual bool thread_safe() = 0; 60 61 // Returns true if the current thread is allowed to access this controller. 62 virtual bool on_correct_thread() = 0; 63 64 // Lock the controller. 65 virtual void lock() = 0; 66 67 // Unlock the controller. 68 virtual void unlock() = 0; 69 70 // Returns true if the controller is locked on the current thread. 71 virtual bool locked() = 0; 72 73 // Assert that the lock has been acquired. 74 virtual void AssertLockAcquired() = 0; 75 76 // Verify that the current thread is correct for accessing the controller. VerifyThread()77 inline bool VerifyThread() { 78 if (!thread_safe() && !on_correct_thread()) { 79 // This object should only be accessed from the thread that created it. 80 NOTREACHED() << "object accessed from incorrect thread."; 81 return false; 82 } 83 return true; 84 } 85 86 // The controller must already be locked before calling the below methods. 87 88 // Set the owner for this controller. 89 void SetOwner(void* value, Object* object); 90 91 // Add a reference value and associated object. 92 void AddReference(void* value, Object* object); 93 94 // Remove the value. If |notify_object| is true the removed object will be 95 // notified. If |value| is the owner all reference objects will be removed. 96 // If |value| has dependencies those objects will also be removed. 97 void Remove(void* value, bool notify_object); 98 99 // Returns the object for the specified value. 100 Object* Get(void* value); 101 102 // Add a dependency between |parent| and |child|. 103 void AddDependency(void* parent, void* child); 104 105 // Recursively removes any dependent values. 106 void RemoveDependencies(void* value); 107 108 // Takes ownership of all references and dependencies currently controlled by 109 // |other|. The |other| controller must already be locked. 110 void TakeFrom(CefValueController* other); 111 112 // Replace all instances of |old_value| with |new_value|. Used in cases where 113 // move semantics may move the contents of an object without retaining the 114 // object pointer itself. 115 void Swap(void* old_value, void* new_value); 116 117 protected: 118 friend class base::RefCountedThreadSafe<CefValueController>; 119 120 virtual ~CefValueController(); 121 122 private: 123 // Owner object. 124 void* owner_value_; 125 Object* owner_object_; 126 127 // Map of reference objects. 128 typedef std::map<void*, Object*> ReferenceMap; 129 ReferenceMap reference_map_; 130 131 // Map of dependency objects. 132 typedef std::set<void*> DependencySet; 133 typedef std::map<void*, DependencySet> DependencyMap; 134 DependencyMap dependency_map_; 135 136 DISALLOW_COPY_AND_ASSIGN(CefValueController); 137 }; 138 139 // Thread-safe access control implementation. 140 class CefValueControllerThreadSafe : public CefValueController { 141 public: CefValueControllerThreadSafe()142 explicit CefValueControllerThreadSafe() : locked_thread_id_(0) {} 143 144 // CefValueController methods. thread_safe()145 bool thread_safe() override { return true; } on_correct_thread()146 bool on_correct_thread() override { return true; } lock()147 void lock() override NO_THREAD_SAFETY_ANALYSIS { 148 lock_.Acquire(); 149 locked_thread_id_ = base::PlatformThread::CurrentId(); 150 } unlock()151 void unlock() override NO_THREAD_SAFETY_ANALYSIS { 152 locked_thread_id_ = 0; 153 lock_.Release(); 154 } locked()155 bool locked() override { 156 return (locked_thread_id_ == base::PlatformThread::CurrentId()); 157 } AssertLockAcquired()158 void AssertLockAcquired() override { lock_.AssertAcquired(); } 159 160 private: 161 base::Lock lock_; 162 base::PlatformThreadId locked_thread_id_; 163 164 DISALLOW_COPY_AND_ASSIGN(CefValueControllerThreadSafe); 165 }; 166 167 // Non-thread-safe access control implementation. 168 class CefValueControllerNonThreadSafe : public CefValueController { 169 public: CefValueControllerNonThreadSafe()170 explicit CefValueControllerNonThreadSafe() 171 : thread_id_(base::PlatformThread::CurrentId()) {} 172 173 // CefValueController methods. thread_safe()174 bool thread_safe() override { return false; } on_correct_thread()175 bool on_correct_thread() override { 176 return (thread_id_ == base::PlatformThread::CurrentId()); 177 } lock()178 void lock() override {} unlock()179 void unlock() override {} locked()180 bool locked() override { return on_correct_thread(); } AssertLockAcquired()181 void AssertLockAcquired() override { DCHECK(locked()); } 182 183 private: 184 base::PlatformThreadId thread_id_; 185 186 DISALLOW_COPY_AND_ASSIGN(CefValueControllerNonThreadSafe); 187 }; 188 189 // Helper macros for verifying context. 190 191 #define CEF_VALUE_VERIFY_RETURN_VOID_EX(object, modify) \ 192 if (!VerifyAttached()) \ 193 return; \ 194 AutoLock auto_lock(object, modify); \ 195 if (!auto_lock.verified()) \ 196 return; 197 198 #define CEF_VALUE_VERIFY_RETURN_VOID(modify) \ 199 CEF_VALUE_VERIFY_RETURN_VOID_EX(this, modify) 200 201 #define CEF_VALUE_VERIFY_RETURN_EX(object, modify, error_val) \ 202 if (!VerifyAttached()) \ 203 return error_val; \ 204 AutoLock auto_lock(object, modify); \ 205 if (!auto_lock.verified()) \ 206 return error_val; 207 208 #define CEF_VALUE_VERIFY_RETURN(modify, error_val) \ 209 CEF_VALUE_VERIFY_RETURN_EX(this, modify, error_val) 210 211 // Template class for implementing CEF wrappers of other types. 212 template <class CefType, class ValueType> 213 class CefValueBase : public CefType, public CefValueController::Object { 214 public: 215 // Specifies how the value will be used. 216 enum ValueMode { 217 // A reference to a value managed by an existing controller. These values 218 // can be safely detached but ownership should not be transferred (make a 219 // copy of the value instead). 220 kReference, 221 222 // The value has its own controller and will be deleted on destruction. 223 // These values can only be detached to another controller otherwise any 224 // references will not be properly managed. 225 kOwnerWillDelete, 226 227 // The value has its own controller and will not be deleted on destruction. 228 // This should only be used for global values or scope-limited values that 229 // will be explicitly detached. 230 kOwnerNoDelete, 231 }; 232 233 // Create a new object. 234 // If |read_only| is true mutable access will not be allowed. 235 // If |parent_value| is non-NULL and the value mode is kReference a dependency 236 // will be added. CefValueBase(ValueType * value,void * parent_value,ValueMode value_mode,bool read_only,CefValueController * controller)237 CefValueBase(ValueType* value, 238 void* parent_value, 239 ValueMode value_mode, 240 bool read_only, 241 CefValueController* controller) 242 : value_(value), 243 value_mode_(value_mode), 244 read_only_(read_only), 245 controller_(controller) { 246 DCHECK(value_); 247 248 // Specifying a parent value for a non-reference doesn't make sense. 249 DCHECK(!(!reference() && parent_value)); 250 251 if (!reference() && !controller_.get()) { 252 // For owned values default to using a new multi-threaded controller. 253 controller_ = new CefValueControllerThreadSafe(); 254 SetOwnsController(); 255 } 256 257 // A controller is required. 258 DCHECK(controller_.get()); 259 260 if (reference()) { 261 // Register the reference with the controller. 262 controller_->AddReference(value_, this); 263 264 // Add a dependency on the parent value. 265 if (parent_value) 266 controller_->AddDependency(parent_value, value_); 267 } 268 } 269 ~CefValueBase()270 ~CefValueBase() override { 271 if (controller_.get() && value_) 272 Delete(); 273 } 274 275 // True if the underlying value is referenced instead of owned. reference()276 inline bool reference() const { return (value_mode_ == kReference); } 277 278 // True if the underlying value will be deleted. will_delete()279 inline bool will_delete() const { return (value_mode_ == kOwnerWillDelete); } 280 281 // True if access to the underlying value is read-only. read_only()282 inline bool read_only() const { return read_only_; } 283 284 // True if the underlying value has been detached. detached()285 inline bool detached() { return !controller_.get(); } 286 287 // Returns the controller. controller()288 inline CefValueController* controller() { return controller_.get(); } 289 290 // Deletes the underlying value. Delete()291 void Delete() { 292 CEF_VALUE_VERIFY_RETURN_VOID(false); 293 294 // Remove the object from the controller. If this is the owner object any 295 // references will be detached. 296 controller()->Remove(value_, false); 297 298 if (will_delete()) { 299 // Remove any dependencies. 300 controller()->RemoveDependencies(value_); 301 302 // Delete the value. 303 DeleteValue(value_); 304 } 305 306 controller_ = nullptr; 307 value_ = nullptr; 308 } 309 310 // Detaches the underlying value and returns a pointer to it. If this is an 311 // owner and a |new_controller| value is specified any existing references 312 // will be passed to the new controller. Detach(CefValueController * new_controller)313 ValueType* Detach(CefValueController* new_controller) { 314 CEF_VALUE_VERIFY_RETURN(false, nullptr); 315 316 // A |new_controller| value is required for mode kOwnerWillDelete. 317 DCHECK(!will_delete() || new_controller); 318 319 if (new_controller && !reference()) { 320 // Pass any existing references and dependencies to the new controller. 321 // They will be removed from this controller. 322 new_controller->TakeFrom(controller()); 323 } 324 325 // Remove the object from the controller. If this is the owner object any 326 // references will be detached. 327 controller()->Remove(value_, false); 328 controller_ = nullptr; 329 330 // Return the old value. 331 ValueType* old_val = value_; 332 value_ = nullptr; 333 return old_val; 334 } 335 336 // Verify that the value is attached. VerifyAttached()337 inline bool VerifyAttached() { 338 if (detached()) { 339 // This object should not be accessed after being detached. 340 NOTREACHED() << "object accessed after being detached."; 341 return false; 342 } 343 return true; 344 } 345 346 protected: 347 // CefValueController::Object methods. OnControlRemoved()348 void OnControlRemoved() override { 349 DCHECK(controller()->locked()); 350 351 // Only references should be removed in this manner. 352 DCHECK(reference()); 353 354 controller_ = nullptr; 355 value_ = nullptr; 356 } 357 358 // Override to customize value deletion. DeleteValue(ValueType * value)359 virtual void DeleteValue(ValueType* value) { delete value; } 360 361 // Returns a mutable reference to the value. mutable_value()362 inline ValueType* mutable_value() { 363 DCHECK(value_); 364 DCHECK(!read_only_); 365 DCHECK(controller()->locked()); 366 return value_; 367 } 368 // Returns a const reference to the value. const_value()369 inline const ValueType& const_value() { 370 DCHECK(value_); 371 DCHECK(controller()->locked()); 372 return *value_; 373 } 374 375 // Verify that the value can be accessed. VerifyAccess(bool modify)376 inline bool VerifyAccess(bool modify) { 377 // The controller must already be locked. 378 DCHECK(controller()->locked()); 379 380 if (read_only() && modify) { 381 // This object cannot be modified. 382 NOTREACHED() << "mutation attempted on read-only object."; 383 return false; 384 } 385 386 return true; 387 } 388 389 // Used to indicate that this object owns the controller. SetOwnsController()390 inline void SetOwnsController() { 391 CefValueController::AutoLock lock_scope(controller_.get()); 392 if (lock_scope.verified()) 393 controller_->SetOwner(value_, this); 394 } 395 396 // Encapsulates value locking and verification logic. 397 class AutoLock { 398 public: AutoLock(CefValueBase * impl,bool modify)399 explicit AutoLock(CefValueBase* impl, bool modify) 400 : auto_lock_(impl->controller()) { 401 verified_ = (auto_lock_.verified() && impl->VerifyAccess(modify)); 402 } 403 verified()404 inline bool verified() { return verified_; } 405 406 private: 407 CefValueController::AutoLock auto_lock_; 408 bool verified_; 409 410 DISALLOW_COPY_AND_ASSIGN(AutoLock); 411 }; 412 413 private: 414 ValueType* value_; 415 ValueMode value_mode_; 416 bool read_only_; 417 scoped_refptr<CefValueController> controller_; 418 419 IMPLEMENT_REFCOUNTING(CefValueBase); 420 421 DISALLOW_COPY_AND_ASSIGN(CefValueBase); 422 }; 423 424 #endif // CEF_LIBCEF_COMMON_VALUE_BASE_H_ 425