| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chromecast/base/device_capabilities_impl.h" | 5 #include "chromecast/base/device_capabilities_impl.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <utility> |
| 8 | 9 |
| 9 #include "base/logging.h" | 10 #include "base/logging.h" |
| 10 #include "base/single_thread_task_runner.h" | 11 #include "base/single_thread_task_runner.h" |
| 11 #include "base/thread_task_runner_handle.h" | 12 #include "base/thread_task_runner_handle.h" |
| 12 #include "base/values.h" | 13 #include "base/values.h" |
| 13 #include "chromecast/base/serializers.h" | 14 #include "chromecast/base/serializers.h" |
| 14 | 15 |
| 15 namespace chromecast { | 16 namespace chromecast { |
| 16 | 17 |
| 17 namespace { | 18 namespace { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 63 return make_scoped_ptr(capabilities); | 64 return make_scoped_ptr(capabilities); |
| 64 } | 65 } |
| 65 | 66 |
| 66 scoped_refptr<DeviceCapabilities::Data> DeviceCapabilities::CreateData() { | 67 scoped_refptr<DeviceCapabilities::Data> DeviceCapabilities::CreateData() { |
| 67 return make_scoped_refptr(new Data); | 68 return make_scoped_refptr(new Data); |
| 68 } | 69 } |
| 69 | 70 |
| 70 scoped_refptr<DeviceCapabilities::Data> DeviceCapabilities::CreateData( | 71 scoped_refptr<DeviceCapabilities::Data> DeviceCapabilities::CreateData( |
| 71 scoped_ptr<const base::DictionaryValue> dictionary) { | 72 scoped_ptr<const base::DictionaryValue> dictionary) { |
| 72 DCHECK(dictionary.get()); | 73 DCHECK(dictionary.get()); |
| 73 return make_scoped_refptr(new Data(dictionary.Pass())); | 74 return make_scoped_refptr(new Data(std::move(dictionary))); |
| 74 } | 75 } |
| 75 | 76 |
| 76 DeviceCapabilities::Validator::Validator(DeviceCapabilities* capabilities) | 77 DeviceCapabilities::Validator::Validator(DeviceCapabilities* capabilities) |
| 77 : capabilities_(capabilities) { | 78 : capabilities_(capabilities) { |
| 78 DCHECK(capabilities); | 79 DCHECK(capabilities); |
| 79 } | 80 } |
| 80 | 81 |
| 81 void DeviceCapabilities::Validator::SetValidatedValue( | 82 void DeviceCapabilities::Validator::SetValidatedValue( |
| 82 const std::string& path, | 83 const std::string& path, |
| 83 scoped_ptr<base::Value> new_value) const { | 84 scoped_ptr<base::Value> new_value) const { |
| 84 capabilities_->SetValidatedValue(path, new_value.Pass()); | 85 capabilities_->SetValidatedValue(path, std::move(new_value)); |
| 85 } | 86 } |
| 86 | 87 |
| 87 DeviceCapabilities::Data::Data() | 88 DeviceCapabilities::Data::Data() |
| 88 : dictionary_(new base::DictionaryValue), | 89 : dictionary_(new base::DictionaryValue), |
| 89 json_string_(SerializeToJson(*dictionary_)) { | 90 json_string_(SerializeToJson(*dictionary_)) { |
| 90 DCHECK(json_string_.get()); | 91 DCHECK(json_string_.get()); |
| 91 } | 92 } |
| 92 | 93 |
| 93 DeviceCapabilities::Data::Data( | 94 DeviceCapabilities::Data::Data( |
| 94 scoped_ptr<const base::DictionaryValue> dictionary) | 95 scoped_ptr<const base::DictionaryValue> dictionary) |
| 95 : dictionary_(dictionary.Pass()), | 96 : dictionary_(std::move(dictionary)), |
| 96 json_string_(SerializeToJson(*dictionary_)) { | 97 json_string_(SerializeToJson(*dictionary_)) { |
| 97 DCHECK(dictionary_.get()); | 98 DCHECK(dictionary_.get()); |
| 98 DCHECK(json_string_.get()); | 99 DCHECK(json_string_.get()); |
| 99 } | 100 } |
| 100 | 101 |
| 101 DeviceCapabilitiesImpl::Data::~Data() {} | 102 DeviceCapabilitiesImpl::Data::~Data() {} |
| 102 | 103 |
| 103 DeviceCapabilitiesImpl::ValidatorInfo::ValidatorInfo(Validator* validator) | 104 DeviceCapabilitiesImpl::ValidatorInfo::ValidatorInfo(Validator* validator) |
| 104 : validator_(validator), task_runner_(base::ThreadTaskRunnerHandle::Get()) { | 105 : validator_(validator), task_runner_(base::ThreadTaskRunnerHandle::Get()) { |
| 105 DCHECK(validator_); | 106 DCHECK(validator_); |
| 106 DCHECK(task_runner_.get()); | 107 DCHECK(task_runner_.get()); |
| 107 } | 108 } |
| 108 | 109 |
| 109 DeviceCapabilitiesImpl::ValidatorInfo::~ValidatorInfo() { | 110 DeviceCapabilitiesImpl::ValidatorInfo::~ValidatorInfo() { |
| 110 // Check that ValidatorInfo is being destroyed on the same thread that it was | 111 // Check that ValidatorInfo is being destroyed on the same thread that it was |
| 111 // constructed on. | 112 // constructed on. |
| 112 DCHECK(task_runner_->BelongsToCurrentThread()); | 113 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 113 } | 114 } |
| 114 | 115 |
| 115 void DeviceCapabilitiesImpl::ValidatorInfo::Validate( | 116 void DeviceCapabilitiesImpl::ValidatorInfo::Validate( |
| 116 const std::string& path, | 117 const std::string& path, |
| 117 scoped_ptr<base::Value> proposed_value) const { | 118 scoped_ptr<base::Value> proposed_value) const { |
| 118 // Check that we are running Validate on the same thread that ValidatorInfo | 119 // Check that we are running Validate on the same thread that ValidatorInfo |
| 119 // was constructed on. | 120 // was constructed on. |
| 120 DCHECK(task_runner_->BelongsToCurrentThread()); | 121 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 121 validator_->Validate(path, proposed_value.Pass()); | 122 validator_->Validate(path, std::move(proposed_value)); |
| 122 } | 123 } |
| 123 | 124 |
| 124 DeviceCapabilitiesImpl::DeviceCapabilitiesImpl() | 125 DeviceCapabilitiesImpl::DeviceCapabilitiesImpl() |
| 125 : data_(CreateData()), | 126 : data_(CreateData()), |
| 126 task_runner_for_writes_(base::ThreadTaskRunnerHandle::Get()), | 127 task_runner_for_writes_(base::ThreadTaskRunnerHandle::Get()), |
| 127 observer_list_(new base::ObserverListThreadSafe<Observer>) { | 128 observer_list_(new base::ObserverListThreadSafe<Observer>) { |
| 128 DCHECK(task_runner_for_writes_.get()); | 129 DCHECK(task_runner_for_writes_.get()); |
| 129 } | 130 } |
| 130 | 131 |
| 131 DeviceCapabilitiesImpl::~DeviceCapabilitiesImpl() { | 132 DeviceCapabilitiesImpl::~DeviceCapabilitiesImpl() { |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 231 // Validator gets unregistered, the call to Validate will get skipped. | 232 // Validator gets unregistered, the call to Validate will get skipped. |
| 232 validator_it->second->task_runner()->PostTask( | 233 validator_it->second->task_runner()->PostTask( |
| 233 FROM_HERE, base::Bind(&ValidatorInfo::Validate, | 234 FROM_HERE, base::Bind(&ValidatorInfo::Validate, |
| 234 validator_it->second->AsWeakPtr(), path, | 235 validator_it->second->AsWeakPtr(), path, |
| 235 base::Passed(&proposed_value))); | 236 base::Passed(&proposed_value))); |
| 236 return; | 237 return; |
| 237 } | 238 } |
| 238 } | 239 } |
| 239 // Since we are done checking for a registered Validator at this point, we | 240 // Since we are done checking for a registered Validator at this point, we |
| 240 // can release the lock. All further member access will be for capabilities. | 241 // can release the lock. All further member access will be for capabilities. |
| 241 SetValidatedValue(path, proposed_value.Pass()); | 242 SetValidatedValue(path, std::move(proposed_value)); |
| 242 } | 243 } |
| 243 | 244 |
| 244 void DeviceCapabilitiesImpl::MergeDictionary( | 245 void DeviceCapabilitiesImpl::MergeDictionary( |
| 245 const base::DictionaryValue& dict_value) { | 246 const base::DictionaryValue& dict_value) { |
| 246 for (base::DictionaryValue::Iterator it(dict_value); !it.IsAtEnd(); | 247 for (base::DictionaryValue::Iterator it(dict_value); !it.IsAtEnd(); |
| 247 it.Advance()) { | 248 it.Advance()) { |
| 248 SetCapability(it.key(), it.value().CreateDeepCopy()); | 249 SetCapability(it.key(), it.value().CreateDeepCopy()); |
| 249 } | 250 } |
| 250 } | 251 } |
| 251 | 252 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 285 return; | 286 return; |
| 286 } | 287 } |
| 287 | 288 |
| 288 // In this sequence, we create a deep copy, modify the deep copy, and then | 289 // In this sequence, we create a deep copy, modify the deep copy, and then |
| 289 // do a pointer swap. We do this to have minimal time spent in the | 290 // do a pointer swap. We do this to have minimal time spent in the |
| 290 // data_lock_. If we were to lock and modify the capabilities | 291 // data_lock_. If we were to lock and modify the capabilities |
| 291 // dictionary directly, there may be expensive writes that block other | 292 // dictionary directly, there may be expensive writes that block other |
| 292 // threads. | 293 // threads. |
| 293 scoped_ptr<base::DictionaryValue> dictionary_deep_copy( | 294 scoped_ptr<base::DictionaryValue> dictionary_deep_copy( |
| 294 data_->dictionary().CreateDeepCopy()); | 295 data_->dictionary().CreateDeepCopy()); |
| 295 dictionary_deep_copy->Set(path, new_value.Pass()); | 296 dictionary_deep_copy->Set(path, std::move(new_value)); |
| 296 scoped_refptr<Data> new_data(CreateData(dictionary_deep_copy.Pass())); | 297 scoped_refptr<Data> new_data(CreateData(std::move(dictionary_deep_copy))); |
| 297 | 298 |
| 298 { | 299 { |
| 299 base::AutoLock auto_lock(data_lock_); | 300 base::AutoLock auto_lock(data_lock_); |
| 300 // Using swap instead of assignment operator here because it's a little | 301 // Using swap instead of assignment operator here because it's a little |
| 301 // faster. Avoids an extra call to AddRef()/Release(). | 302 // faster. Avoids an extra call to AddRef()/Release(). |
| 302 data_.swap(new_data); | 303 data_.swap(new_data); |
| 303 } | 304 } |
| 304 | 305 |
| 305 // Even though ObseverListThreadSafe notifications are always asynchronous | 306 // Even though ObseverListThreadSafe notifications are always asynchronous |
| 306 // (posts task even if to same thread), no locks should be held at this point | 307 // (posts task even if to same thread), no locks should be held at this point |
| 307 // in the code. This is just to be safe that no deadlocks occur if Observers | 308 // in the code. This is just to be safe that no deadlocks occur if Observers |
| 308 // call DeviceCapabilities methods in OnCapabilitiesChanged(). | 309 // call DeviceCapabilities methods in OnCapabilitiesChanged(). |
| 309 observer_list_->Notify(FROM_HERE, &Observer::OnCapabilitiesChanged, path); | 310 observer_list_->Notify(FROM_HERE, &Observer::OnCapabilitiesChanged, path); |
| 310 } | 311 } |
| 311 | 312 |
| 312 } // namespace chromecast | 313 } // namespace chromecast |
| OLD | NEW |