From 29bc87d102b9e36c1e15385756c9fa9a214f3503 Mon Sep 17 00:00:00 2001 From: Tom Sepez Date: Fri, 17 Apr 2015 12:55:39 -0700 Subject: Add nonstd::unique_ptr as a workaround until std::unique_ptr is allowed. This is a copy of breakpad's standalone scoped_ptr, which has been renamed to nonstd::unique_ptr, and from which more complicated classes have been removed. The reset() method has also been tweaked to more closely match c++11, and an implicit conversion to bool has been added. BUG=https://code.google.com/p/pdfium/issues/detail?id=55 R=thestig@chromium.org Review URL: https://codereview.chromium.org/1091283002 --- third_party/BUILD.gn | 1 + third_party/base/nonstd_unique_ptr.h | 180 +++++++++++++++++++++++++++++++++++ third_party/third_party.gyp | 1 + 3 files changed, 182 insertions(+) create mode 100644 third_party/base/nonstd_unique_ptr.h diff --git a/third_party/BUILD.gn b/third_party/BUILD.gn index c6de4535da..18baeb2eb5 100644 --- a/third_party/BUILD.gn +++ b/third_party/BUILD.gn @@ -78,6 +78,7 @@ source_set("pdfium_base") { sources = [ "base/logging.h", "base/macros.h", + "base/nonstd_unique_ptr.h", "base/numerics/safe_conversions.h", "base/numerics/safe_conversions_impl.h", "base/numerics/safe_math.h", diff --git a/third_party/base/nonstd_unique_ptr.h b/third_party/base/nonstd_unique_ptr.h new file mode 100644 index 0000000000..9c0b13c1bf --- /dev/null +++ b/third_party/base/nonstd_unique_ptr.h @@ -0,0 +1,180 @@ +// Copyright 2013 Google Inc. All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This is a copy of breakpad's standalone scoped_ptr, which has been +// renamed to nonstd::unique_ptr, and from which more complicated classes +// have been removed. The reset() method has also been tweaked to more +// closely match c++11, and an implicit conversion to bool has been added. + +// Scopers help you manage ownership of a pointer, helping you easily manage the +// a pointer within a scope, and automatically destroying the pointer at the +// end of a scope. +// +// Example usage (unique_ptr): +// { +// unique_ptr foo(new Foo("wee")); +// } // foo goes out of scope, releasing the pointer with it. +// +// { +// unique_ptr foo; // No pointer managed. +// foo.reset(new Foo("wee")); // Now a pointer is managed. +// foo.reset(new Foo("wee2")); // Foo("wee") was destroyed. +// foo.reset(new Foo("wee3")); // Foo("wee2") was destroyed. +// foo->Method(); // Foo::Method() called. +// foo.get()->Method(); // Foo::Method() called. +// SomeFunc(foo.release()); // SomeFunc takes ownership, foo no longer +// // manages a pointer. +// foo.reset(new Foo("wee4")); // foo manages a pointer again. +// foo.reset(); // Foo("wee4") destroyed, foo no longer +// // manages a pointer. +// } // foo wasn't managing a pointer, so nothing was destroyed. + +#ifndef NONSTD_UNIQUE_PTR_H_ +#define NONSTD_UNIQUE_PTR_H_ + +// This is an implementation designed to match the anticipated future TR2 +// implementation of the unique_ptr class. + +#include +#include +#include + +namespace nonstd { + +// A unique_ptr is like a T*, except that the destructor of unique_ptr +// automatically deletes the pointer it holds (if any). +// That is, unique_ptr owns the T object that it points to. +// Like a T*, a unique_ptr may hold either NULL or a pointer to a T object. +// Also like T*, unique_ptr is thread-compatible, and once you +// dereference it, you get the threadsafety guarantees of T. +// +// The size of a unique_ptr is small: +// sizeof(unique_ptr) == sizeof(C*) +template +class unique_ptr { + public: + + // The element type + typedef C element_type; + + // Constructor. Defaults to initializing with NULL. + // There is no way to create an uninitialized unique_ptr. + // The input parameter must be allocated with new. + explicit unique_ptr(C* p = NULL) : ptr_(p) { } + + // Destructor. If there is a C object, delete it. + // We don't need to test ptr_ == NULL because C++ does that for us. + ~unique_ptr() { + enum { type_must_be_complete = sizeof(C) }; + delete ptr_; + } + + // Reset. Deletes the current owned object, if any. + // Then takes ownership of a new object, if given. + // this->reset(this->get()) works. + void reset(C* p = NULL) { + if (p != ptr_) { + enum { type_must_be_complete = sizeof(C) }; + C* old_ptr = ptr_; + ptr_ = p; + delete old_ptr; + } + } + + // Accessors to get the owned object. + // operator* and operator-> will assert() if there is no current object. + C& operator*() const { + assert(ptr_ != NULL); + return *ptr_; + } + C* operator->() const { + assert(ptr_ != NULL); + return ptr_; + } + C* get() const { return ptr_; } + + // Comparison operators. + // These return whether two unique_ptr refer to the same object, not just to + // two different but equal objects. + bool operator==(C* p) const { return ptr_ == p; } + bool operator!=(C* p) const { return ptr_ != p; } + + // Swap two scoped pointers. + void swap(unique_ptr& p2) { + C* tmp = ptr_; + ptr_ = p2.ptr_; + p2.ptr_ = tmp; + } + + // Release a pointer. + // The return value is the current pointer held by this object. + // If this object holds a NULL pointer, the return value is NULL. + // After this operation, this object will hold a NULL pointer, + // and will not own the object any more. + C* release() { + C* retVal = ptr_; + ptr_ = NULL; + return retVal; + } + + // Allow promotion to bool for conditional statements. + operator bool() const { return ptr_ != NULL; } + + private: + C* ptr_; + + // Forbid comparison of unique_ptr types. If C2 != C, it totally doesn't + // make sense, and if C2 == C, it still doesn't make sense because you should + // never have the same object owned by two different unique_ptrs. + template bool operator==(unique_ptr const& p2) const; + template bool operator!=(unique_ptr const& p2) const; + + // Disallow evil constructors + unique_ptr(const unique_ptr&); + void operator=(const unique_ptr&); +}; + +// Free functions +template +void swap(unique_ptr& p1, unique_ptr& p2) { + p1.swap(p2); +} + +template +bool operator==(C* p1, const unique_ptr& p2) { + return p1 == p2.get(); +} + +template +bool operator!=(C* p1, const unique_ptr& p2) { + return p1 != p2.get(); +} + +} // namespace nonstd + +#endif // NONSTD_UNIQUE_PTR_H_ diff --git a/third_party/third_party.gyp b/third_party/third_party.gyp index d54905c022..c106f1e314 100644 --- a/third_party/third_party.gyp +++ b/third_party/third_party.gyp @@ -66,6 +66,7 @@ 'sources': [ 'base/logging.h', 'base/macros.h', + 'base/nonstd_unique_ptr.h' 'base/template_util.h', 'base/numerics/safe_conversions.h', 'base/numerics/safe_conversions_impl.h', -- cgit v1.2.3