• 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     }
~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