diff options
author | Nicolas Capens <capn@google.com> | 2018-04-09 15:12:15 -0400 |
---|---|---|
committer | Nicolas Capens <nicolascapens@google.com> | 2018-04-10 13:20:58 +0000 |
commit | e3490ede24844d5b2b79fff1cb84154be1b634a5 (patch) | |
tree | ceef2748b103bcd1fc721d4796bee64d141eb926 | |
parent | 7e45f6d1b239819ad107ea66d23e656d47856ec3 (diff) | |
download | swiftshader-e3490ede24844d5b2b79fff1cb84154be1b634a5.tar.gz |
Add work-arounds for missing C++11 features.
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 <nicolascapens@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
-rw-r--r-- | src/OpenGL/compiler/Android.mk | 5 | ||||
-rw-r--r-- | third_party/stlport-cpp11-extension/memory | 352 | ||||
-rw-r--r-- | third_party/stlport-cpp11-extension/string | 44 |
3 files changed, 400 insertions, 1 deletions
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 <memory> 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 <stlport/memory> + +namespace std { + +template <typename T> +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 <typename U> + shared_ptr(const shared_ptr<U> &rhs); + template <typename U> + shared_ptr &operator=(const shared_ptr<U> &rhs); + ~shared_ptr(); + + T *get() const; + T *operator->() const; + T &operator*() const; + + template <typename U> + bool operator==(const shared_ptr<U> &rhs) const; + template <typename U> + bool operator!=(const shared_ptr<U> &rhs) const; + template <typename U> + bool operator<(const shared_ptr<U> &rhs) const; + template <typename U> + bool operator<=(const shared_ptr<U> &rhs) const; + template <typename U> + bool operator>(const shared_ptr<U> &rhs) const; + template <typename U> + bool operator>=(const shared_ptr<U> &rhs) const; + + void reset(T *value = NULL); + + // TODO(haining) Work with Deleter + + private: + template <typename U> + 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 T> +typename shared_ptr<T>::Node shared_ptr<T>::NewNodeFor(T *value) { + Node n = {value, new int(1)}; + return n; +} + +template <typename T> +typename shared_ptr<T>::Node shared_ptr<T>::NewNullNode() { + return NewNodeFor(NULL); +} + +template <typename T> +void shared_ptr<T>::reset(T *value) { + DecNode(); + node_ = NewNodeFor(value); +} + +template <typename T> +shared_ptr<T>::shared_ptr() : node_(NewNullNode()) {} + +template <typename T> +void shared_ptr<T>::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 <typename T> +void shared_ptr<T>::IncNode() { + __atomic_fetch_add(node_.count, 1, __ATOMIC_SEQ_CST); +} + +template <typename T> +shared_ptr<T>::shared_ptr(T *value) { + node_ = NewNodeFor(value); +} + +template <typename T> +shared_ptr<T>::shared_ptr(const shared_ptr &rhs) : node_(rhs.node_) { + IncNode(); +} + +template <typename T> +template <typename U> +shared_ptr<T>::shared_ptr(const shared_ptr<U> &rhs) { + node_.value = rhs.node_.value; + node_.count = rhs.node_.count; + node_.m = rhs.node_.m; + IncNode(); +} + +template <typename T> +shared_ptr<T> &shared_ptr<T>::operator=(const shared_ptr &rhs) { + if (node_.value == rhs.node_.value) { + return *this; + } + + DecNode(); + node_ = rhs.node_; + IncNode(); + return *this; +} + +template <typename T> +template <typename U> +shared_ptr<T> &shared_ptr<T>::operator=(const shared_ptr<U> &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 <typename T> +shared_ptr<T>::~shared_ptr() { + DecNode(); +} + +template <typename T> +T *shared_ptr<T>::get() const { + return node_.value; +} + +template <typename T> +T *shared_ptr<T>::operator->() const { + return get(); +} + +template <typename T> +T &shared_ptr<T>::operator*() const { + return *node_.value; +} + +template <typename T> +template <typename U> +bool shared_ptr<T>::operator==(const shared_ptr<U> &rhs) const { + return node_.value == rhs.node_.value; +} + +template <typename T> +template <typename U> +bool shared_ptr<T>::operator!=(const shared_ptr<U> &rhs) const { + return node_.value != rhs.node_.value; +} + +template <typename T> +template <typename U> +bool shared_ptr<T>::operator<(const shared_ptr<U> &rhs) const { + return node_.value < rhs.node_.value; +} + +template <typename T> +template <typename U> +bool shared_ptr<T>::operator<=(const shared_ptr<U> &rhs) const { + return node_.value <= rhs.node_.value; +} + +template <typename T> +template <typename U> +bool shared_ptr<T>::operator>(const shared_ptr<U> &rhs) const { + return node_.value > rhs.node_.value; +} + +template <typename T> +template <typename U> +bool shared_ptr<T>::operator>=(const shared_ptr<U> &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 <cstddef> + +// Default deleter for pointer types. +template <typename T> +struct DefaultDelete { + void operator()(T* p) const { delete p; } +}; + +// Default deleter for array types. +template <typename T> +struct DefaultDelete<T[]> { + 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> c(new C); + +namespace workaround_internal { +template <typename T, typename Deleter> +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 <typename T, typename Deleter = DefaultDelete<T> > +class unique_ptr : public workaround_internal::UniquePtrBase<T, Deleter> { + typedef workaround_internal::UniquePtrBase<T, Deleter> 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 <typename T, typename Deleter> +class unique_ptr<T[], Deleter> : public workaround_internal::UniquePtrBase<T, Deleter> { + typedef workaround_internal::UniquePtrBase<T, Deleter> 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 <typename T> +shared_ptr<T> make_shared() { + return shared_ptr<T>(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 <string> 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 <string> header. +#include <stlport/string> + +#include <sstream> + +namespace std { + +template <typename T> +std::string to_string(const T& val) { + std::ostringstream temp; + temp << val; + return temp.str(); +} + +} // namespace std + +#endif // _STLPORT_CPP11_EXTENSION_STRING_ + |