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