• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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