From e3490ede24844d5b2b79fff1cb84154be1b634a5 Mon Sep 17 00:00:00 2001 From: Nicolas Capens Date: Mon, 9 Apr 2018 15:12:15 -0400 Subject: [PATCH] Add work-arounds for missing C++11 features. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Android versions before M did not have: std::shared_ptr std::unique_ptr std::to_string This is fixed by extending stlport with custom implementations for these features. This works by using 'string' and 'memory' header files in a path searched before stlport itself, in which the new features are implemented, and including stport's original headers for all other functionality. Bug b/75229322 Change-Id: Icd05c072c366381155e086c3f14f805bc4f104d6 Reviewed-on: https://swiftshader-review.googlesource.com/18408 Tested-by: Nicolas Capens Reviewed-by: Alexis Hétu Reviewed-by: Nicolas Capens --- src/OpenGL/compiler/Android.mk | 5 +- third_party/stlport-cpp11-extension/memory | 352 +++++++++++++++++++++++++++++ third_party/stlport-cpp11-extension/string | 44 ++++ 3 files changed, 400 insertions(+), 1 deletion(-) create mode 100644 third_party/stlport-cpp11-extension/memory create mode 100644 third_party/stlport-cpp11-extension/string diff --git a/src/OpenGL/compiler/Android.mk b/src/OpenGL/compiler/Android.mk index d29b549eb..07d9b6cc0 100644 --- a/src/OpenGL/compiler/Android.mk +++ b/src/OpenGL/compiler/Android.mk @@ -12,7 +12,10 @@ COMMON_C_INCLUDES := \ # Marshmallow does not have stlport, but comes with libc++ by default ifeq ($(shell test $(PLATFORM_SDK_VERSION) -lt 23 && echo PreMarshmallow),PreMarshmallow) -COMMON_C_INCLUDES += external/stlport/stlport +COMMON_C_INCLUDES += \ + $(LOCAL_PATH)/../../../third_party/stlport-cpp11-extension/ \ + external/stlport/stlport/ \ + external/stlport/ endif COMMON_CFLAGS := \ diff --git a/third_party/stlport-cpp11-extension/memory b/third_party/stlport-cpp11-extension/memory new file mode 100644 index 000000000..2ff5435dd --- /dev/null +++ b/third_party/stlport-cpp11-extension/memory @@ -0,0 +1,352 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _STLPORT_CPP11_EXTENSION_MEMORY_ +#define _STLPORT_CPP11_EXTENSION_MEMORY_ + +// This file extends stlport's implementation to provide support for: +// - std::shared_ptr (C++11) +// - std::unique_ptr (C++11) + +// Cloned from master branch vendor/google/native/cmds/sysproxy/shared_ptr.h +// Upstream commit ff64c352c35c46a14f15503778781889a816eea4 +// Upstream Change-Id: I481ec53b08beecde2bf6dc38e5933342235da3d9 + +#include + +namespace std { + +template +class shared_ptr { + public: + shared_ptr(); + explicit shared_ptr(T *value); + shared_ptr(const shared_ptr &rhs); + shared_ptr &operator=(const shared_ptr &rhs); + template + shared_ptr(const shared_ptr &rhs); + template + shared_ptr &operator=(const shared_ptr &rhs); + ~shared_ptr(); + + T *get() const; + T *operator->() const; + T &operator*() const; + + template + bool operator==(const shared_ptr &rhs) const; + template + bool operator!=(const shared_ptr &rhs) const; + template + bool operator<(const shared_ptr &rhs) const; + template + bool operator<=(const shared_ptr &rhs) const; + template + bool operator>(const shared_ptr &rhs) const; + template + bool operator>=(const shared_ptr &rhs) const; + + void reset(T *value = NULL); + + // TODO(haining) Work with Deleter + + private: + template + friend class shared_ptr; + + struct Node { + T *value; + int *count; + }; + // Thread safe decrement, deletes node_ if holding last remaining reference. + // Any use of node_ after calling this function is unsafe unless node_ is + // reassigned. + void DecNode(); + + // Thread safe increment. + void IncNode(); + + // Creates a Node referring to NULL. + static Node NewNullNode(); + + // Creates a Node referring to value. + static Node NewNodeFor(T *value); + + Node node_; +}; + +template +typename shared_ptr::Node shared_ptr::NewNodeFor(T *value) { + Node n = {value, new int(1)}; + return n; +} + +template +typename shared_ptr::Node shared_ptr::NewNullNode() { + return NewNodeFor(NULL); +} + +template +void shared_ptr::reset(T *value) { + DecNode(); + node_ = NewNodeFor(value); +} + +template +shared_ptr::shared_ptr() : node_(NewNullNode()) {} + +template +void shared_ptr::DecNode() { + bool should_delete = __atomic_fetch_sub(node_.count, 1, __ATOMIC_SEQ_CST) == 0; + // The only accesses to node_ that should be made after this line is the + // deletion conditional on should_delete. Anything else is unsafe since + // because another thread could have deleted node_ + if (should_delete) { + delete node_.value; + delete node_.count; + node_.value = NULL; + node_.count = NULL; + } +} + +template +void shared_ptr::IncNode() { + __atomic_fetch_add(node_.count, 1, __ATOMIC_SEQ_CST); +} + +template +shared_ptr::shared_ptr(T *value) { + node_ = NewNodeFor(value); +} + +template +shared_ptr::shared_ptr(const shared_ptr &rhs) : node_(rhs.node_) { + IncNode(); +} + +template +template +shared_ptr::shared_ptr(const shared_ptr &rhs) { + node_.value = rhs.node_.value; + node_.count = rhs.node_.count; + node_.m = rhs.node_.m; + IncNode(); +} + +template +shared_ptr &shared_ptr::operator=(const shared_ptr &rhs) { + if (node_.value == rhs.node_.value) { + return *this; + } + + DecNode(); + node_ = rhs.node_; + IncNode(); + return *this; +} + +template +template +shared_ptr &shared_ptr::operator=(const shared_ptr &rhs) { + if (node_.value == rhs.node_.value) { + return *this; + } + + DecNode(); + node_.value = rhs.node_.value; + node_.count = rhs.node_.count; + node_.m = rhs.node_.m; + IncNode(); + return *this; +} + +template +shared_ptr::~shared_ptr() { + DecNode(); +} + +template +T *shared_ptr::get() const { + return node_.value; +} + +template +T *shared_ptr::operator->() const { + return get(); +} + +template +T &shared_ptr::operator*() const { + return *node_.value; +} + +template +template +bool shared_ptr::operator==(const shared_ptr &rhs) const { + return node_.value == rhs.node_.value; +} + +template +template +bool shared_ptr::operator!=(const shared_ptr &rhs) const { + return node_.value != rhs.node_.value; +} + +template +template +bool shared_ptr::operator<(const shared_ptr &rhs) const { + return node_.value < rhs.node_.value; +} + +template +template +bool shared_ptr::operator<=(const shared_ptr &rhs) const { + return node_.value <= rhs.node_.value; +} + +template +template +bool shared_ptr::operator>(const shared_ptr &rhs) const { + return node_.value > rhs.node_.value; +} + +template +template +bool shared_ptr::operator>=(const shared_ptr &rhs) const { + return node_.value >= rhs.node_.value; +} + +#if !defined(DISALLOW_COPY_AND_ASSIGN) +#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&); \ + void operator=(const TypeName&); +#endif + +#include + +// Default deleter for pointer types. +template +struct DefaultDelete { + void operator()(T* p) const { delete p; } +}; + +// Default deleter for array types. +template +struct DefaultDelete { + void operator()(T* p) const { delete[] p; } +}; + +// A smart pointer that deletes the given pointer on destruction. +// Equivalent to C++11's std::unique_ptr +// Named to be in keeping with Android style but also to avoid +// collision with any other implementation, until we can switch over +// to unique_ptr. +// Use thus: +// unique_ptr c(new C); + +namespace workaround_internal { +template +class UniquePtrBase { + public: + // Construct a new UniquePtrBase, taking ownership of the given raw pointer. + explicit UniquePtrBase(T* ptr = 0) : mPtr(ptr), mDeleter() {} + explicit UniquePtrBase(T* ptr, Deleter d) : mPtr(ptr), mDeleter(d) {} + + ~UniquePtrBase() { reset(); } + + // Accessors. + T* get() const { return mPtr; } + + // Returns the raw pointer and hands over ownership to the caller. + // The pointer will not be deleted by UniquePtrBase. + T* release() { + T* result = mPtr; + mPtr = 0; + return result; + } + + // Takes ownership of the given raw pointer. + // If this smart pointer previously owned a different raw pointer, that + // raw pointer will be freed. + void reset(T* ptr = 0) { + T* old_ptr = mPtr; + mPtr = ptr; + if (old_ptr != NULL && mPtr != old_ptr) { + get_deleter()(old_ptr); + } + } + + Deleter& get_deleter() { return mDeleter; } + const Deleter& get_deleter() const { return mDeleter; } + + private: + // This is so users can compare against null. Callers should be able + // to invoke operator== and operator!= above with NULL pointers but not + // with any other pointer. + struct RawDummy {}; + + public: + bool operator==(const RawDummy*) const { return get() == NULL; } + friend bool operator==(const RawDummy*, const UniquePtrBase& self) { + return self == NULL; + } + + bool operator!=(const RawDummy*) const { return !(*this == NULL); } + friend bool operator!=(const RawDummy*, const UniquePtrBase& self) { + return self != NULL; + } + + private: + // The raw pointer. + T* mPtr; + Deleter mDeleter; + + DISALLOW_COPY_AND_ASSIGN(UniquePtrBase); +}; +} // namespace workaround_internal + +template > +class unique_ptr : public workaround_internal::UniquePtrBase { + typedef workaround_internal::UniquePtrBase Base; + public: + // Construct a new unique_ptr, taking ownership of the given raw pointer. + explicit unique_ptr(T* ptr = 0) : Base(ptr) { } + explicit unique_ptr(T* ptr, Deleter d) : Base(ptr, d) { } + + T& operator*() const { return *this->get(); } + T* operator->() const { return this->get(); } +}; + +// Partial specialization for array types. Like std::unique_ptr, this removes +// operator* and operator-> but adds operator[]. +template +class unique_ptr : public workaround_internal::UniquePtrBase { + typedef workaround_internal::UniquePtrBase Base; + public: + explicit unique_ptr(T* ptr = 0) : Base(ptr) { } + explicit unique_ptr(T* ptr, Deleter d) : Base(ptr, d) { } + + T& operator[](std::ptrdiff_t i) const { return this->get()[i]; } +}; + +template +shared_ptr make_shared() { + return shared_ptr(new T); +} + +} // namespace std + +#endif // _STLPORT_CPP11_EXTENSION_MEMORY_ diff --git a/third_party/stlport-cpp11-extension/string b/third_party/stlport-cpp11-extension/string new file mode 100644 index 000000000..53f612530 --- /dev/null +++ b/third_party/stlport-cpp11-extension/string @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _STLPORT_CPP11_EXTENSION_STRING_ +#define _STLPORT_CPP11_EXTENSION_STRING_ + +// This file extends stlport's implementation to provide support for: +// - std::to_string (C++11) + +// Cloned from master branch vendor/google/native/cmds/sysproxy/shared_ptr.h +// Upstream commit ff64c352c35c46a14f15503778781889a816eea4 +// Upstream Change-Id: I481ec53b08beecde2bf6dc38e5933342235da3d9 + +// Include the original stlport header. +#include + +#include + +namespace std { + +template +std::string to_string(const T& val) { + std::ostringstream temp; + temp << val; + return temp.str(); +} + +} // namespace std + +#endif // _STLPORT_CPP11_EXTENSION_STRING_ + -- 2.11.0