Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5960)

Unified Diff: chromecast/base/device_capabilities.h

Issue 1409173006: Making DeviceCapabilities threadsafe with locking. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Clean up unit test. Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chromecast/base/device_capabilities.h
diff --git a/chromecast/base/device_capabilities.h b/chromecast/base/device_capabilities.h
index bffd37a0e6a60782dcfe8b8b690c2bc188428529..9782505c571793c1efa8d8a160aadc948bfd30c5 100644
--- a/chromecast/base/device_capabilities.h
+++ b/chromecast/base/device_capabilities.h
@@ -28,14 +28,22 @@ namespace chromecast {
// system beforehand and are introduced by external parties. These capabilites
// are stored and then forwarded to app servers that use them to determine how
// to interact with the device.
+//
+// Thread Safety:
+// Observers can be added from any thread. Each Observer is guaranteed to be
+// notified on same thread that it was added on and must be removed on the same
+// thread that it was added on.
+//
+// Validators can be registered from any thread. Each Validator's Validate()
+// method is guaranteed to be called on same thread that the Validator was
+// registered on. The Validator must be unregistered on the same thread
+// that it was registered on.
+//
+// All other methods can be called safely from any thread.
// TODO(esum):
-// 1) A pure virtual interface with implementation files is no longer needed
-// now that this file resides in chromecast/base. Change it such that there
-// is just device_capabilities.h/cc.
-// 2) Make class thread-safe with locking.
-// 3) Add WifiSupported, HotspotSupported, and MultizoneSupported capabilities.
-// 4) It's not ideal to have the accessors (BluetoothSupported(), etc.) not
+// 1) Add WifiSupported, HotspotSupported, and MultizoneSupported capabilities.
+// 2) It's not ideal to have the accessors (BluetoothSupported(), etc.) not
// be valid initially until the capability gets registered. We might want
// to use some kind of builder class to solve this.
class DeviceCapabilities {
@@ -90,6 +98,9 @@ class DeviceCapabilities {
static const char kKeyBluetoothSupported[];
static const char kKeyDisplaySupported[];
+ // This class should get destroyed after all Validators have been
+ // unregistered, all Observers have been removed, and the class is no longer
+ // being accessed.
virtual ~DeviceCapabilities() {}
// Create empty instance with no capabilities. Although the class is not
@@ -109,16 +120,17 @@ class DeviceCapabilities {
// farther down. For example, "foo" is a valid value for |key|, but "foo.bar"
// is not. Note that if "foo.bar" is updated in SetCapability(), the
// Validate() method for "foo"'s Validator will be called, with a |path| of
- // "foo.bar". Both Register() and Unregister() must be called on cast
- // receiver main thread; the Validator provided will also be called on cast
- // receiver main thread. Note that this method does not add or modify
- // the capability. To do this, SetCapability() should be called, or
- // Validators can call SetValidatedValue().
+ // "foo.bar". Note that this method does not add or modify the capability.
+ // To do this, SetCapability() should be called, or Validators can call
+ // SetValidatedValue(). This method is synchronous to ensure Validators know
+ // exactly when they may start receiving validation requests.
virtual void Register(const std::string& key,
Validator* validator) = 0;
// Unregisters Validator for |key|. |validator| argument must match
// |validator| argument that was passed in to Register() for |key|. Note that
- // the capability and its value remain untouched.
+ // the capability and its value remain untouched. This method is synchronous
+ // to ensure Validators know exactly when they will stop receiving validation
+ // requests.
virtual void Unregister(const std::string& key,
const Validator* validator) = 0;
// Gets the Validator currently registered for |key|. Returns nullptr if
@@ -131,18 +143,16 @@ class DeviceCapabilities {
virtual bool BluetoothSupported() const = 0;
virtual bool DisplaySupported() const = 0;
- // Gets the value of |path|. If capability at |path| does not exist,
- // |out_value| remains untouched. Returns true if the capability has been
- // successfully retrieved. Note that this does NOT perform a deep copy, and
- // DeviceCapabilities still owns the memory returned through |out_value|.
- virtual bool GetCapability(const std::string& path,
- const base::Value** out_value) const = 0;
+ // Returns a deep copy of the value at |path|. If the capability at |path|
+ // does not exist, a null scoped_ptr is returned.
+ virtual scoped_ptr<base::Value> GetCapability(
+ const std::string& path) const = 0;
// Returns the complete capability string (JSON format).
- virtual const std::string& GetCapabilitiesString() const = 0;
+ virtual std::string GetCapabilitiesString() const = 0;
- // Returns the capabilities dictionary.
- virtual const base::DictionaryValue* GetCapabilities() const = 0;
+ // Returns deep copy of the capabilities dictionary.
+ virtual scoped_ptr<base::DictionaryValue> GetCapabilities() const = 0;
// Updates the value at |path| to |proposed_value| if |path| already exists
// and adds new capability if |path| doesn't. Note that if a key has been
@@ -151,11 +161,11 @@ class DeviceCapabilities {
// Ex: If "foo" has a Validator registered, a |path| of "foo.bar"
// will cause |proposed_value| to go through the Validator's Validate()
// method. Client code may use the Observer interface to determine the
- // ultimate value used.
+ // ultimate value used. This method is asynchronous.
virtual void SetCapability(const std::string& path,
scoped_ptr<base::Value> proposed_value) = 0;
// Iterates through entries in |dict_value| and calls SetCapability() for
- // each one.
+ // each one. This method is asynchronous.
virtual void MergeDictionary(const base::DictionaryValue& dict_value) = 0;
// Adds/removes an observer. It doesn't take the ownership of |observer|.
@@ -167,8 +177,8 @@ class DeviceCapabilities {
private:
// Does actual internal update of |path| to |new_value|.
- virtual void SetValidatedValueInternal(const std::string& path,
- scoped_ptr<base::Value> new_value) = 0;
+ virtual void SetValidatedValue(const std::string& path,
+ scoped_ptr<base::Value> new_value) = 0;
DISALLOW_COPY_AND_ASSIGN(DeviceCapabilities);
};
« no previous file with comments | « no previous file | chromecast/base/device_capabilities_impl.h » ('j') | chromecast/base/device_capabilities_impl.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698