Replace shared_ptr With std::shared_ptr

(This is a merge of http://go/wvgerrit/65783)

Straightforward patch to replace our shared_ptr implementation with
std::shared_ptr, which works identically for all our use cases.

Bug: 111851141
Test: CE CDM Unit Tests
Test: Android Unit Tests
Change-Id: I9e8624dd3cab70a45941a45eb553c1ea0c077d2f
This commit is contained in:
John W. Bruce
2018-11-14 10:48:47 -08:00
parent 39cfe6037f
commit fb4d53bae6
9 changed files with 29 additions and 377 deletions

View File

@@ -104,7 +104,6 @@ try_adb_push policy_engine_constraints_unittest
try_adb_push policy_engine_unittest
try_adb_push request_license_test
try_adb_push service_certificate_unittest
try_adb_push shared_ptr_test
try_adb_push timer_unittest
try_adb_push usage_table_header_unittest
try_adb_push value_metric_unittest

View File

@@ -12,12 +12,11 @@
#include "cdm_session.h"
#include "disallow_copy_and_assign.h"
#include "lock.h"
#include "shared_ptr.h"
#include "wv_cdm_types.h"
namespace wvcdm {
typedef std::list<shared_ptr<CdmSession> > CdmSessionList;
typedef std::list<std::shared_ptr<CdmSession> > CdmSessionList;
// TODO(rfrias): Concurrency protection for this class has moved to CdmEngine.
// Add it back when locks to control access to session usage and destruction
@@ -40,16 +39,16 @@ class CdmSessionMap {
size_t Size() const { return sessions_.size(); }
bool FindSession(const CdmSessionId& id,
shared_ptr<CdmSession>* session);
std::shared_ptr<CdmSession>* session);
void GetSessionList(CdmSessionList& sessions);
private:
typedef std::map<CdmSessionId, shared_ptr<CdmSession> >
typedef std::map<CdmSessionId, std::shared_ptr<CdmSession> >
CdmIdToSessionMap;
bool FindSessionNoLock(const CdmSessionId& session_id,
shared_ptr<CdmSession>* session);
std::shared_ptr<CdmSession>* session);
CdmIdToSessionMap sessions_;

View File

@@ -1,209 +0,0 @@
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// from google3/util/gtl/shared_ptr.h
// from protobuf/src/google/protobuf/stubs/shared_ptr.h
#ifndef WVCDM_CORE_SHARED_PTR_H__
#define WVCDM_CORE_SHARED_PTR_H__
#include <algorithm> // for swap
#include <stddef.h>
#include <memory>
#include "lock.h"
#include "wv_cdm_types.h"
namespace wvcdm {
extern Lock shared_ptr_ref_count_lock_;
} // namespace wvcdm
namespace {
bool Barrier_AtomicIncrement(volatile uint32_t* ptr, uint32_t value) {
*ptr += value;
return *ptr;
}
bool NoBarrier_AtomicIncrement(volatile uint32_t* ptr, uint32_t value) {
*ptr += value;
return *ptr;
}
inline bool RefCountDec(volatile uint32_t *ptr) {
wvcdm::AutoLock auto_lock(wvcdm::shared_ptr_ref_count_lock_);
return Barrier_AtomicIncrement(ptr, -1) != 0;
}
inline void RefCountInc(volatile uint32_t *ptr) {
wvcdm::AutoLock auto_lock(wvcdm::shared_ptr_ref_count_lock_);
NoBarrier_AtomicIncrement(ptr, 1);
}
} // namespace
namespace wvcdm {
template <typename T> class shared_ptr;
// This class is an internal implementation detail for shared_ptr. If two
// shared_ptrs point to the same object, they also share a control block.
// An "empty" shared_pointer refers to NULL and also has a NULL control block.
// It contains all of the state that's needed for reference counting or any
// other kind of resource management. In this implementation the control block
// consists of a single reference count (the number of shared_ptrs that
// share ownership of the object).
class SharedPtrControlBlock {
template <typename T> friend class shared_ptr;
private:
SharedPtrControlBlock() : refcount_(1) {}
uint32_t refcount_;
};
// Forward declaration. The class is defined below.
template <typename T> class enable_shared_from_this;
template <typename T>
class shared_ptr {
public:
typedef T element_type;
shared_ptr() : ptr_(NULL), control_block_(NULL) {}
explicit shared_ptr(T* ptr)
: ptr_(ptr),
control_block_(ptr != NULL ? new SharedPtrControlBlock : NULL) {
}
// Copy constructor: makes this object a copy of ptr, and increments
// the reference count.
template <typename U>
shared_ptr(const shared_ptr<U>& ptr)
: ptr_(NULL),
control_block_(NULL) {
Initialize(ptr);
}
// Need non-templated version to prevent the compiler-generated default
shared_ptr(const shared_ptr<T>& ptr)
: ptr_(NULL),
control_block_(NULL) {
Initialize(ptr);
}
// Assignment operator. Replaces the existing shared_ptr with ptr.
// Increment ptr's reference count and decrement the one being replaced.
template <typename U>
shared_ptr<T>& operator=(const shared_ptr<U>& ptr) {
if (ptr_ != ptr.ptr_) {
shared_ptr<T> me(ptr); // will hold our previous state to be destroyed.
swap(me);
}
return *this;
}
// Need non-templated version to prevent the compiler-generated default
shared_ptr<T>& operator=(const shared_ptr<T>& ptr) {
if (ptr_ != ptr.ptr_) {
shared_ptr<T> me(ptr); // will hold our previous state to be destroyed.
swap(me);
}
return *this;
}
~shared_ptr() {
if (ptr_ != NULL) {
if (!RefCountDec(&control_block_->refcount_)) {
delete ptr_;
delete control_block_;
}
}
}
// Replaces underlying raw pointer with the one passed in. The reference
// count is set to one (or zero if the pointer is NULL) for the pointer
// being passed in and decremented for the one being replaced.
//
// If you have a compilation error with this code, make sure you aren't
// passing NULL, nullptr, or 0 to this function. Call reset without an
// argument to reset to a null ptr.
template <typename Y>
void reset(Y* p) {
if (p != ptr_) {
shared_ptr<T> tmp(p);
tmp.swap(*this);
}
}
void reset() {
reset(static_cast<T*>(NULL));
}
// Exchanges the contents of this with the contents of r. This function
// supports more efficient swapping since it eliminates the need for a
// temporary shared_ptr object.
void swap(shared_ptr<T>& r) {
using std::swap; // http://go/using-std-swap
swap(ptr_, r.ptr_);
swap(control_block_, r.control_block_);
}
// The following function is useful for gaining access to the underlying
// pointer when a shared_ptr remains in scope so the reference-count is
// known to be > 0 (e.g. for parameter passing).
T* get() const {
return ptr_;
}
T& operator*() const {
return *ptr_;
}
T* operator->() const {
return ptr_;
}
long use_count() const {
return control_block_ ? control_block_->refcount_ : 1;
}
bool unique() const {
return use_count() == 1;
}
private:
// If r is non-empty, initialize *this to share ownership with r,
// increasing the underlying reference count.
// If r is empty, *this remains empty.
// Requires: this is empty, namely this->ptr_ == NULL.
template <typename U>
void Initialize(const shared_ptr<U>& r) {
// This performs a static_cast on r.ptr_ to U*, which is a no-op since it
// is already a U*. So initialization here requires that r.ptr_ is
// implicitly convertible to T*.
InitializeWithStaticCast<U>(r);
}
// Initializes *this as described in Initialize, but additionally performs a
// static_cast from r.ptr_ (V*) to U*.
// NOTE(gfc): We'd need a more general form to support const_pointer_cast and
// dynamic_pointer_cast, but those operations are sufficiently discouraged
// that supporting static_pointer_cast is sufficient.
template <typename U, typename V>
void InitializeWithStaticCast(const shared_ptr<V>& r) {
if (r.control_block_ != NULL) {
RefCountInc(&r.control_block_->refcount_);
ptr_ = static_cast<U*>(r.ptr_);
control_block_ = r.control_block_;
}
}
T* ptr_;
SharedPtrControlBlock* control_block_;
};
} // namespace wvcdm
#endif // WVCDM_CORE_SHARED_PTR_H__

View File

@@ -5,10 +5,11 @@
#include "cdm_engine.h"
#include <assert.h>
#include <list>
#include <stdlib.h>
#include <iostream>
#include <list>
#include <memory>
#include <sstream>
#include "cdm_session.h"
@@ -30,8 +31,6 @@ const size_t kUsageReportsPerRequest = 1;
namespace wvcdm {
Lock shared_ptr_ref_count_lock_;
class UsagePropertySet : public CdmClientPropertySet {
public:
UsagePropertySet() {}
@@ -261,7 +260,7 @@ CdmResponseType CdmEngine::GenerateKeyRequest(
id = iter->second.first;
}
shared_ptr<CdmSession> session;
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(id, &session)) {
LOGE("CdmEngine::GenerateKeyRequest: session_id not found = %s",
id.c_str());
@@ -337,7 +336,7 @@ CdmResponseType CdmEngine::AddKey(const CdmSessionId& session_id,
id = iter->second.first;
}
shared_ptr<CdmSession> session;
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(id, &session)) {
LOGE("CdmEngine::AddKey: session id not found = %s", id.c_str());
return SESSION_NOT_FOUND_3;
@@ -381,7 +380,7 @@ CdmResponseType CdmEngine::RestoreKey(const CdmSessionId& session_id,
return EMPTY_KEYSET_ID_ENG_4;
}
shared_ptr<CdmSession> session;
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, &session)) {
LOGE("CdmEngine::RestoreKey: session_id not found = %s ",
session_id.c_str());
@@ -404,7 +403,7 @@ CdmResponseType CdmEngine::RestoreKey(const CdmSessionId& session_id,
CdmResponseType CdmEngine::RemoveKeys(const CdmSessionId& session_id) {
LOGI("CdmEngine::RemoveKeys");
shared_ptr<CdmSession> session;
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, &session)) {
LOGE("CdmEngine::RemoveKeys: session_id not found = %s",
session_id.c_str());
@@ -419,7 +418,7 @@ CdmResponseType CdmEngine::RemoveKeys(const CdmSessionId& session_id) {
CdmResponseType CdmEngine::RemoveLicense(const CdmSessionId& session_id) {
LOGI("CdmEngine::RemoveLicense");
shared_ptr<CdmSession> session;
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, &session)) {
LOGE("session_id not found = %s", session_id.c_str());
return SESSION_NOT_FOUND_19;
@@ -432,7 +431,7 @@ CdmResponseType CdmEngine::GenerateRenewalRequest(
const CdmSessionId& session_id, CdmKeyRequest* key_request) {
LOGI("CdmEngine::GenerateRenewalRequest");
shared_ptr<CdmSession> session;
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, &session)) {
LOGE("CdmEngine::GenerateRenewalRequest: session_id not found = %s",
session_id.c_str());
@@ -461,7 +460,7 @@ CdmResponseType CdmEngine::RenewKey(const CdmSessionId& session_id,
const CdmKeyResponse& key_data) {
LOGI("CdmEngine::RenewKey");
shared_ptr<CdmSession> session;
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, &session)) {
LOGE("CdmEngine::RenewKey: session_id not found = %s", session_id.c_str());
return SESSION_NOT_FOUND_7;
@@ -653,7 +652,7 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
CdmResponseType CdmEngine::QuerySessionStatus(const CdmSessionId& session_id,
CdmQueryMap* query_response) {
LOGI("CdmEngine::QuerySessionStatus");
shared_ptr<CdmSession> session;
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, &session)) {
LOGE("CdmEngine::QuerySessionStatus: session_id not found = %s",
session_id.c_str());
@@ -664,7 +663,7 @@ CdmResponseType CdmEngine::QuerySessionStatus(const CdmSessionId& session_id,
bool CdmEngine::IsReleaseSession(const CdmSessionId& session_id) {
LOGI("CdmEngine::IsReleaseSession");
shared_ptr<CdmSession> session;
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, &session)) {
LOGE("CdmEngine::IsReleaseSession: session_id not found = %s",
session_id.c_str());
@@ -675,7 +674,7 @@ bool CdmEngine::IsReleaseSession(const CdmSessionId& session_id) {
bool CdmEngine::IsOfflineSession(const CdmSessionId& session_id) {
LOGI("CdmEngine::IsOfflineSession");
shared_ptr<CdmSession> session;
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, &session)) {
LOGE("CdmEngine::IsOfflineSession: session_id not found = %s",
session_id.c_str());
@@ -687,7 +686,7 @@ bool CdmEngine::IsOfflineSession(const CdmSessionId& session_id) {
CdmResponseType CdmEngine::QueryKeyStatus(const CdmSessionId& session_id,
CdmQueryMap* query_response) {
LOGI("CdmEngine::QueryKeyStatus");
shared_ptr<CdmSession> session;
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, &session)) {
LOGE("CdmEngine::QueryKeyStatus: session_id not found = %s",
session_id.c_str());
@@ -704,7 +703,7 @@ CdmResponseType CdmEngine::QueryKeyAllowedUsage(const CdmSessionId& session_id,
LOGE("CdmEngine::QueryKeyAllowedUsage: no response destination");
return PARAMETER_NULL;
}
shared_ptr<CdmSession> session;
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, &session)) {
LOGE("CdmEngine::QueryKeyAllowedUsage: session_id not found = %s",
session_id.c_str());
@@ -755,7 +754,7 @@ CdmResponseType CdmEngine::QueryKeyAllowedUsage(const std::string& key_id,
CdmResponseType CdmEngine::QueryOemCryptoSessionId(
const CdmSessionId& session_id, CdmQueryMap* query_response) {
LOGI("CdmEngine::QueryOemCryptoSessionId");
shared_ptr<CdmSession> session;
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, &session)) {
LOGE("CdmEngine::QueryOemCryptoSessionId: session_id not found = %s",
session_id.c_str());
@@ -1424,7 +1423,7 @@ CdmResponseType CdmEngine::LoadUsageSession(const CdmKeySetId& key_set_id,
return EMPTY_KEYSET_ID_ENG_5;
}
shared_ptr<CdmSession> session;
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(key_set_id, &session)) {
LOGE("CdmEngine::LoadUsageSession: session_id not found = %s ",
key_set_id.c_str());
@@ -1510,7 +1509,7 @@ CdmResponseType CdmEngine::Decrypt(const CdmSessionId& session_id,
}
AutoLock lock(session_map_lock_);
shared_ptr<CdmSession> session;
std::shared_ptr<CdmSession> session;
if (session_id.empty()) {
CdmSessionList sessions;
session_map_.GetSessionList(sessions);
@@ -1551,7 +1550,7 @@ CdmResponseType CdmEngine::GenericEncrypt(
LOGE("CdmEngine::GenericEncrypt: no out_buffer provided");
return PARAMETER_NULL;
}
shared_ptr<CdmSession> session;
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, &session)) {
LOGE("CdmEngine::GenericEncrypt: session_id not found = %s ",
session_id.c_str());
@@ -1569,7 +1568,7 @@ CdmResponseType CdmEngine::GenericDecrypt(
LOGE("CdmEngine::GenericDecrypt: no out_buffer provided");
return PARAMETER_NULL;
}
shared_ptr<CdmSession> session;
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, &session)) {
LOGE("CdmEngine::GenericDecrypt: session_id not found = %s ",
session_id.c_str());
@@ -1586,7 +1585,7 @@ CdmResponseType CdmEngine::GenericSign(
LOGE("CdmEngine::GenericSign: no signature buffer provided");
return PARAMETER_NULL;
}
shared_ptr<CdmSession> session;
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, &session)) {
LOGE("CdmEngine::GenericSign: session_id not found = %s ",
session_id.c_str());
@@ -1599,7 +1598,7 @@ CdmResponseType CdmEngine::GenericVerify(
const std::string& session_id, const std::string& message,
const std::string& key_id, CdmSigningAlgorithm algorithm,
const std::string& signature) {
shared_ptr<CdmSession> session;
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, &session)) {
LOGE("CdmEngine::GenericVerify: session_id not found = %s ",
session_id.c_str());
@@ -1660,7 +1659,7 @@ bool CdmEngine::FindSessionForKey(const KeyId& key_id,
bool CdmEngine::NotifyResolution(const CdmSessionId& session_id, uint32_t width,
uint32_t height) {
shared_ptr<CdmSession> session;
std::shared_ptr<CdmSession> session;
if (session_map_.FindSession(session_id, &session)) {
session->NotifyResolution(width, height);
return true;

View File

@@ -29,7 +29,7 @@ void CdmSessionMap::Add(const std::string& id, CdmSession* session) {
}
bool CdmSessionMap::CloseSession(const std::string& id) {
shared_ptr<CdmSession> session;
std::shared_ptr<CdmSession> session;
if (!FindSessionNoLock(id, &session)) {
return false;
}
@@ -43,12 +43,12 @@ bool CdmSessionMap::Exists(const std::string& id) {
}
bool CdmSessionMap::FindSession(const CdmSessionId& id,
shared_ptr<CdmSession>* session) {
std::shared_ptr<CdmSession>* session) {
return FindSessionNoLock(id, session);
}
bool CdmSessionMap::FindSessionNoLock(const CdmSessionId& session_id,
shared_ptr<CdmSession>* session) {
std::shared_ptr<CdmSession>* session) {
CdmIdToSessionMap::iterator iter = sessions_.find(session_id);
if (iter == sessions_.end()) {
return false;

View File

@@ -1,130 +0,0 @@
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine Master
// License Agreement.
#include <string>
#include <errno.h>
#include <getopt.h>
#include <gtest/gtest.h>
#include "shared_ptr.h"
#include "log.h"
namespace wvcdm {
class SharedPtrTest : public testing::Test {
public:
static void NoteDeletion() {
deletions++;
}
class Dummy {
public:
explicit Dummy(int v) : value_(v) { exists_ = true; }
~Dummy() {
NoteDeletion();
exists_ = false;
}
bool exists() { return exists_; }
int getValue() { return value_; }
void setValue(int v) { value_ = v; }
private:
bool exists_;
int value_;
};
static void ExpectedDeletions(int count) {
ASSERT_TRUE(deletions == count);
deletions = 0;
}
virtual void SetUpTest() {
deletions = 0;
}
virtual void TearDownTest() {
deletions = 0;
}
private:
static int deletions;
};
int SharedPtrTest::deletions = 0;
TEST_F(SharedPtrTest, NullSingletonCreate) {
shared_ptr<Dummy> sd1;
ASSERT_TRUE(sd1.unique());
ASSERT_TRUE(sd1.get() == NULL);
ExpectedDeletions(0);
}
TEST_F(SharedPtrTest, SingletonCreate) {
{
Dummy* d1 = new Dummy(42);
shared_ptr<Dummy> sd1(d1);
ASSERT_TRUE(sd1.unique());
ASSERT_TRUE(sd1.get() == d1);
ASSERT_TRUE(sd1->getValue() == 42);
}
ExpectedDeletions(1);
}
TEST_F(SharedPtrTest, ResetToNull) {
Dummy* d1 = new Dummy(42);
shared_ptr<Dummy> sd1(d1);
ASSERT_TRUE(sd1->getValue() == 42);
sd1.reset();
ExpectedDeletions(1);
ASSERT_TRUE(sd1.get() == NULL);
}
TEST_F(SharedPtrTest, SharedCreate) {
{
Dummy* d1 = new Dummy(42);
shared_ptr<Dummy> sd1(d1);
{
shared_ptr<Dummy> sd2(sd1);
ASSERT_FALSE(sd1.unique());
ASSERT_TRUE(sd1.get() == d1);
ASSERT_TRUE(sd2.get() == d1);
ASSERT_TRUE(sd1.use_count() == 2);
}
ExpectedDeletions(0);
ASSERT_TRUE(sd1.use_count() == 1);
}
ExpectedDeletions(1);
}
TEST_F(SharedPtrTest, SharedInstance) {
Dummy* d1 = new Dummy(42);
{
shared_ptr<Dummy> sd1(d1);
{
shared_ptr<Dummy> sd2(sd1);
ASSERT_FALSE(sd1.unique());
ASSERT_TRUE(sd1.get() == d1);
ASSERT_TRUE(sd2.get() == d1);
sd2->setValue(55);
ASSERT_TRUE(sd1.use_count() == 2);
}
ExpectedDeletions(0);
ASSERT_TRUE(sd1.use_count() == 1);
ASSERT_TRUE(sd1->getValue() == 55);
}
ExpectedDeletions(1);
}
TEST_F(SharedPtrTest, Reset) {
{
Dummy* d1 = new Dummy(42);
Dummy* d2 = new Dummy(96);
shared_ptr<Dummy> sd1(d1);
sd1.reset(d2);
ExpectedDeletions(1);
ASSERT_TRUE(sd1->getValue() == 96);
}
ExpectedDeletions(1);
}
} // namespace wvcdm

View File

@@ -17,7 +17,6 @@
#include "log.h"
#include "metrics.pb.h"
#include "pow2bucket.h"
#include "shared_ptr.h"
namespace wvcdm {
namespace metrics {

View File

@@ -107,10 +107,6 @@ test_name := service_certificate_unittest
test_src_dir := ../core/test
include $(LOCAL_PATH)/unit-test.mk
test_name := shared_ptr_test
test_src_dir := ../core/test
include $(LOCAL_PATH)/unit-test.mk
test_name := timer_unittest
test_src_dir := .
include $(LOCAL_PATH)/unit-test.mk

View File

@@ -102,7 +102,6 @@ adb_shell_run license_unittest
adb_shell_run policy_engine_constraints_unittest
adb_shell_run policy_engine_unittest
adb_shell_run service_certificate_unittest
adb_shell_run shared_ptr_test
adb_shell_run timer_unittest
adb_shell_run usage_table_header_unittest
adb_shell_run value_metric_unittest