diff options
Diffstat (limited to 'src/core/lib/gprpp')
-rw-r--r-- | src/core/lib/gprpp/debug_location.h | 13 | ||||
-rw-r--r-- | src/core/lib/gprpp/directory_reader.h | 48 | ||||
-rw-r--r-- | src/core/lib/gprpp/dual_ref_counted.h | 43 | ||||
-rw-r--r-- | src/core/lib/gprpp/host_port.cc | 2 | ||||
-rw-r--r-- | src/core/lib/gprpp/match.h | 2 | ||||
-rw-r--r-- | src/core/lib/gprpp/orphanable.h | 27 | ||||
-rw-r--r-- | src/core/lib/gprpp/posix/directory_reader.cc | 82 | ||||
-rw-r--r-- | src/core/lib/gprpp/posix/stat.cc | 1 | ||||
-rw-r--r-- | src/core/lib/gprpp/ref_counted.h | 85 | ||||
-rw-r--r-- | src/core/lib/gprpp/ref_counted_ptr.h | 97 | ||||
-rw-r--r-- | src/core/lib/gprpp/ref_counted_string.h | 15 | ||||
-rw-r--r-- | src/core/lib/gprpp/status_helper.cc | 4 | ||||
-rw-r--r-- | src/core/lib/gprpp/strerror.cc | 2 | ||||
-rw-r--r-- | src/core/lib/gprpp/time.cc | 1 | ||||
-rw-r--r-- | src/core/lib/gprpp/uuid_v4.cc | 2 | ||||
-rw-r--r-- | src/core/lib/gprpp/validation_errors.cc | 1 | ||||
-rw-r--r-- | src/core/lib/gprpp/windows/directory_reader.cc | 81 | ||||
-rw-r--r-- | src/core/lib/gprpp/work_serializer.cc | 3 | ||||
-rw-r--r-- | src/core/lib/gprpp/xxhash_inline.h | 29 |
19 files changed, 469 insertions, 69 deletions
diff --git a/src/core/lib/gprpp/debug_location.h b/src/core/lib/gprpp/debug_location.h index 1a29f49538..c6c9b68286 100644 --- a/src/core/lib/gprpp/debug_location.h +++ b/src/core/lib/gprpp/debug_location.h @@ -19,6 +19,10 @@ #ifndef GRPC_SRC_CORE_LIB_GPRPP_DEBUG_LOCATION_H #define GRPC_SRC_CORE_LIB_GPRPP_DEBUG_LOCATION_H +#include <grpc/support/port_platform.h> + +#include <utility> + #if defined(__has_builtin) #if __has_builtin(__builtin_FILE) #define GRPC_DEFAULT_FILE __builtin_FILE() @@ -77,6 +81,15 @@ class DebugLocation { }; #endif +template <typename T> +struct ValueWithDebugLocation { + // NOLINTNEXTLINE + ValueWithDebugLocation(T&& value, DebugLocation debug_location = {}) + : value(std::forward<T>(value)), debug_location(debug_location) {} + T value; + GPR_NO_UNIQUE_ADDRESS DebugLocation debug_location; +}; + #define DEBUG_LOCATION ::grpc_core::DebugLocation(__FILE__, __LINE__) } // namespace grpc_core diff --git a/src/core/lib/gprpp/directory_reader.h b/src/core/lib/gprpp/directory_reader.h new file mode 100644 index 0000000000..0f0bbcf0b0 --- /dev/null +++ b/src/core/lib/gprpp/directory_reader.h @@ -0,0 +1,48 @@ +// +// +// Copyright 2023 gRPC authors. +// +// 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 GRPC_SRC_CORE_LIB_GPRPP_DIRECTORY_READER_H +#define GRPC_SRC_CORE_LIB_GPRPP_DIRECTORY_READER_H + +#include <grpc/support/port_platform.h> + +#include <memory> + +#include "absl/functional/function_ref.h" +#include "absl/status/status.h" +#include "absl/strings/string_view.h" + +namespace grpc_core { + +class DirectoryReader { + public: + virtual ~DirectoryReader() = default; + // Returns the name of the directory being read. + virtual absl::string_view Name() const = 0; + // Calls callback for each name in the directory except for "." and "..". + // Returns non-OK if there was an error reading the directory. + virtual absl::Status ForEach( + absl::FunctionRef<void(absl::string_view)> callback) = 0; +}; + +std::unique_ptr<DirectoryReader> MakeDirectoryReader( + absl::string_view filename); + +} // namespace grpc_core + +#endif // GRPC_SRC_CORE_LIB_GPRPP_DIRECTORY_READER_H
\ No newline at end of file diff --git a/src/core/lib/gprpp/dual_ref_counted.h b/src/core/lib/gprpp/dual_ref_counted.h index 4fc6ea760d..547d1312e1 100644 --- a/src/core/lib/gprpp/dual_ref_counted.h +++ b/src/core/lib/gprpp/dual_ref_counted.h @@ -47,19 +47,38 @@ namespace grpc_core { template <typename Child> class DualRefCounted : public Orphanable { public: + // Not copyable nor movable. + DualRefCounted(const DualRefCounted&) = delete; + DualRefCounted& operator=(const DualRefCounted&) = delete; + ~DualRefCounted() override = default; GRPC_MUST_USE_RESULT RefCountedPtr<Child> Ref() { IncrementRefCount(); return RefCountedPtr<Child>(static_cast<Child*>(this)); } - GRPC_MUST_USE_RESULT RefCountedPtr<Child> Ref(const DebugLocation& location, const char* reason) { IncrementRefCount(location, reason); return RefCountedPtr<Child>(static_cast<Child*>(this)); } + template < + typename Subclass, + std::enable_if_t<std::is_base_of<Child, Subclass>::value, bool> = true> + RefCountedPtr<Subclass> RefAsSubclass() { + IncrementRefCount(); + return RefCountedPtr<Subclass>(static_cast<Subclass*>(this)); + } + template < + typename Subclass, + std::enable_if_t<std::is_base_of<Child, Subclass>::value, bool> = true> + RefCountedPtr<Subclass> RefAsSubclass(const DebugLocation& location, + const char* reason) { + IncrementRefCount(location, reason); + return RefCountedPtr<Subclass>(static_cast<Subclass*>(this)); + } + void Unref() { // Convert strong ref to weak ref. const uint64_t prev_ref_pair = @@ -120,7 +139,6 @@ class DualRefCounted : public Orphanable { std::memory_order_acq_rel, std::memory_order_acquire)); return RefCountedPtr<Child>(static_cast<Child*>(this)); } - GRPC_MUST_USE_RESULT RefCountedPtr<Child> RefIfNonZero( const DebugLocation& location, const char* reason) { uint64_t prev_ref_pair = refs_.load(std::memory_order_acquire); @@ -150,13 +168,28 @@ class DualRefCounted : public Orphanable { IncrementWeakRefCount(); return WeakRefCountedPtr<Child>(static_cast<Child*>(this)); } - GRPC_MUST_USE_RESULT WeakRefCountedPtr<Child> WeakRef( const DebugLocation& location, const char* reason) { IncrementWeakRefCount(location, reason); return WeakRefCountedPtr<Child>(static_cast<Child*>(this)); } + template < + typename Subclass, + std::enable_if_t<std::is_base_of<Child, Subclass>::value, bool> = true> + WeakRefCountedPtr<Subclass> WeakRefAsSubclass() { + IncrementWeakRefCount(); + return WeakRefCountedPtr<Subclass>(static_cast<Subclass*>(this)); + } + template < + typename Subclass, + std::enable_if_t<std::is_base_of<Child, Subclass>::value, bool> = true> + WeakRefCountedPtr<Subclass> WeakRefAsSubclass(const DebugLocation& location, + const char* reason) { + IncrementWeakRefCount(location, reason); + return WeakRefCountedPtr<Subclass>(static_cast<Subclass*>(this)); + } + void WeakUnref() { #ifndef NDEBUG // Grab a copy of the trace flag before the atomic change, since we @@ -207,10 +240,6 @@ class DualRefCounted : public Orphanable { } } - // Not copyable nor movable. - DualRefCounted(const DualRefCounted&) = delete; - DualRefCounted& operator=(const DualRefCounted&) = delete; - protected: // Note: Tracing is a no-op in non-debug builds. explicit DualRefCounted( diff --git a/src/core/lib/gprpp/host_port.cc b/src/core/lib/gprpp/host_port.cc index 4e19c39a8d..47404626f9 100644 --- a/src/core/lib/gprpp/host_port.cc +++ b/src/core/lib/gprpp/host_port.cc @@ -22,8 +22,6 @@ #include <stddef.h> -#include <initializer_list> - #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" diff --git a/src/core/lib/gprpp/match.h b/src/core/lib/gprpp/match.h index 5b210207f3..510e653f49 100644 --- a/src/core/lib/gprpp/match.h +++ b/src/core/lib/gprpp/match.h @@ -17,7 +17,7 @@ #include <grpc/support/port_platform.h> -#include <type_traits> +#include <utility> #include "absl/types/variant.h" diff --git a/src/core/lib/gprpp/orphanable.h b/src/core/lib/gprpp/orphanable.h index 86319429e5..f74cadfaf0 100644 --- a/src/core/lib/gprpp/orphanable.h +++ b/src/core/lib/gprpp/orphanable.h @@ -97,6 +97,33 @@ class InternallyRefCounted : public Orphanable { return RefCountedPtr<Child>(static_cast<Child*>(this)); } + template < + typename Subclass, + std::enable_if_t<std::is_base_of<Child, Subclass>::value, bool> = true> + RefCountedPtr<Subclass> RefAsSubclass() { + IncrementRefCount(); + return RefCountedPtr<Subclass>(static_cast<Subclass*>(this)); + } + template < + typename Subclass, + std::enable_if_t<std::is_base_of<Child, Subclass>::value, bool> = true> + RefCountedPtr<Subclass> RefAsSubclass(const DebugLocation& location, + const char* reason) { + IncrementRefCount(location, reason); + return RefCountedPtr<Subclass>(static_cast<Subclass*>(this)); + } + + GRPC_MUST_USE_RESULT RefCountedPtr<Child> RefIfNonZero() { + return RefCountedPtr<Child>(refs_.RefIfNonZero() ? static_cast<Child*>(this) + : nullptr); + } + GRPC_MUST_USE_RESULT RefCountedPtr<Child> RefIfNonZero( + const DebugLocation& location, const char* reason) { + return RefCountedPtr<Child>(refs_.RefIfNonZero(location, reason) + ? static_cast<Child*>(this) + : nullptr); + } + void Unref() { if (GPR_UNLIKELY(refs_.Unref())) { unref_behavior_(static_cast<Child*>(this)); diff --git a/src/core/lib/gprpp/posix/directory_reader.cc b/src/core/lib/gprpp/posix/directory_reader.cc new file mode 100644 index 0000000000..ecdf3c68c6 --- /dev/null +++ b/src/core/lib/gprpp/posix/directory_reader.cc @@ -0,0 +1,82 @@ +// +// +// Copyright 2023 gRPC authors. +// +// 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. +// +// + +#include <grpc/support/port_platform.h> + +#include <memory> + +#include "absl/functional/function_ref.h" +#include "absl/status/status.h" +#include "absl/strings/string_view.h" + +#if defined(GPR_LINUX) || defined(GPR_ANDROID) || defined(GPR_FREEBSD) || \ + defined(GPR_APPLE) + +#include <dirent.h> + +#include <string> + +#include "src/core/lib/gprpp/directory_reader.h" + +namespace grpc_core { + +namespace { +const char kSkipEntriesSelf[] = "."; +const char kSkipEntriesParent[] = ".."; +} // namespace + +class DirectoryReaderImpl : public DirectoryReader { + public: + explicit DirectoryReaderImpl(absl::string_view directory_path) + : directory_path_(directory_path) {} + absl::string_view Name() const override { return directory_path_; } + absl::Status ForEach(absl::FunctionRef<void(absl::string_view)>) override; + + private: + const std::string directory_path_; +}; + +std::unique_ptr<DirectoryReader> MakeDirectoryReader( + absl::string_view filename) { + return std::make_unique<DirectoryReaderImpl>(filename); +} + +absl::Status DirectoryReaderImpl::ForEach( + absl::FunctionRef<void(absl::string_view)> callback) { + // Open the dir for reading + DIR* directory = opendir(directory_path_.c_str()); + if (directory == nullptr) { + return absl::InternalError("Could not read crl directory."); + } + struct dirent* directory_entry; + // Iterate over everything in the directory + while ((directory_entry = readdir(directory)) != nullptr) { + const absl::string_view file_name = directory_entry->d_name; + // Skip "." and ".." + if (file_name == kSkipEntriesParent || file_name == kSkipEntriesSelf) { + continue; + } + // Call the callback with this filename + callback(file_name); + } + closedir(directory); + return absl::OkStatus(); +} +} // namespace grpc_core + +#endif // GPR_LINUX || GPR_ANDROID || GPR_FREEBSD || GPR_APPLE diff --git a/src/core/lib/gprpp/posix/stat.cc b/src/core/lib/gprpp/posix/stat.cc index 4212ea991d..d0a8ada998 100644 --- a/src/core/lib/gprpp/posix/stat.cc +++ b/src/core/lib/gprpp/posix/stat.cc @@ -21,7 +21,6 @@ // IWYU pragma: no_include <bits/struct_stat.h> #include "absl/status/status.h" -#include "absl/strings/string_view.h" #ifdef GPR_POSIX_STAT diff --git a/src/core/lib/gprpp/ref_counted.h b/src/core/lib/gprpp/ref_counted.h index cdf692c5ce..9d56397fdb 100644 --- a/src/core/lib/gprpp/ref_counted.h +++ b/src/core/lib/gprpp/ref_counted.h @@ -219,7 +219,7 @@ class NonPolymorphicRefCount { // Default behavior: Delete the object. struct UnrefDelete { template <typename T> - void operator()(T* p) { + void operator()(T* p) const { delete p; } }; @@ -231,7 +231,7 @@ struct UnrefDelete { // later by identifying entries for which RefIfNonZero() returns null. struct UnrefNoDelete { template <typename T> - void operator()(T* /*p*/) {} + void operator()(T* /*p*/) const {} }; // Call the object's dtor but do not delete it. This is useful for cases @@ -239,7 +239,7 @@ struct UnrefNoDelete { // arena). struct UnrefCallDtor { template <typename T> - void operator()(T* p) { + void operator()(T* p) const { p->~T(); } }; @@ -276,35 +276,52 @@ class RefCounted : public Impl { public: using RefCountedChildType = Child; + // Not copyable nor movable. + RefCounted(const RefCounted&) = delete; + RefCounted& operator=(const RefCounted&) = delete; + // Note: Depending on the Impl used, this dtor can be implicitly virtual. ~RefCounted() = default; + // Ref() for mutable types. GRPC_MUST_USE_RESULT RefCountedPtr<Child> Ref() { IncrementRefCount(); return RefCountedPtr<Child>(static_cast<Child*>(this)); } - GRPC_MUST_USE_RESULT RefCountedPtr<Child> Ref(const DebugLocation& location, const char* reason) { IncrementRefCount(location, reason); return RefCountedPtr<Child>(static_cast<Child*>(this)); } - // TODO(roth): Once all of our code is converted to C++ and can use - // RefCountedPtr<> instead of manual ref-counting, make this method - // private, since it will only be used by RefCountedPtr<>, which is a - // friend of this class. - void Unref() { - if (GPR_UNLIKELY(refs_.Unref())) { - unref_behavior_(static_cast<Child*>(this)); - } + // Ref() for const types. + GRPC_MUST_USE_RESULT RefCountedPtr<const Child> Ref() const { + IncrementRefCount(); + return RefCountedPtr<const Child>(static_cast<const Child*>(this)); } - void Unref(const DebugLocation& location, const char* reason) { - if (GPR_UNLIKELY(refs_.Unref(location, reason))) { - unref_behavior_(static_cast<Child*>(this)); - } + GRPC_MUST_USE_RESULT RefCountedPtr<const Child> Ref( + const DebugLocation& location, const char* reason) const { + IncrementRefCount(location, reason); + return RefCountedPtr<const Child>(static_cast<const Child*>(this)); + } + + template < + typename Subclass, + std::enable_if_t<std::is_base_of<Child, Subclass>::value, bool> = true> + RefCountedPtr<Subclass> RefAsSubclass() { + IncrementRefCount(); + return RefCountedPtr<Subclass>(static_cast<Subclass*>(this)); + } + template < + typename Subclass, + std::enable_if_t<std::is_base_of<Child, Subclass>::value, bool> = true> + RefCountedPtr<Subclass> RefAsSubclass(const DebugLocation& location, + const char* reason) { + IncrementRefCount(location, reason); + return RefCountedPtr<Subclass>(static_cast<Subclass*>(this)); } + // RefIfNonZero() for mutable types. GRPC_MUST_USE_RESULT RefCountedPtr<Child> RefIfNonZero() { return RefCountedPtr<Child>(refs_.RefIfNonZero() ? static_cast<Child*>(this) : nullptr); @@ -316,9 +333,32 @@ class RefCounted : public Impl { : nullptr); } - // Not copyable nor movable. - RefCounted(const RefCounted&) = delete; - RefCounted& operator=(const RefCounted&) = delete; + // RefIfNonZero() for const types. + GRPC_MUST_USE_RESULT RefCountedPtr<const Child> RefIfNonZero() const { + return RefCountedPtr<const Child>( + refs_.RefIfNonZero() ? static_cast<const Child*>(this) : nullptr); + } + GRPC_MUST_USE_RESULT RefCountedPtr<const Child> RefIfNonZero( + const DebugLocation& location, const char* reason) const { + return RefCountedPtr<const Child>(refs_.RefIfNonZero(location, reason) + ? static_cast<const Child*>(this) + : nullptr); + } + + // TODO(roth): Once all of our code is converted to C++ and can use + // RefCountedPtr<> instead of manual ref-counting, make this method + // private, since it will only be used by RefCountedPtr<>, which is a + // friend of this class. + void Unref() const { + if (GPR_UNLIKELY(refs_.Unref())) { + unref_behavior_(static_cast<const Child*>(this)); + } + } + void Unref(const DebugLocation& location, const char* reason) const { + if (GPR_UNLIKELY(refs_.Unref(location, reason))) { + unref_behavior_(static_cast<const Child*>(this)); + } + } protected: // Note: Tracing is a no-op on non-debug builds. @@ -336,12 +376,13 @@ class RefCounted : public Impl { template <typename T> friend class RefCountedPtr; - void IncrementRefCount() { refs_.Ref(); } - void IncrementRefCount(const DebugLocation& location, const char* reason) { + void IncrementRefCount() const { refs_.Ref(); } + void IncrementRefCount(const DebugLocation& location, + const char* reason) const { refs_.Ref(location, reason); } - RefCount refs_; + mutable RefCount refs_; GPR_NO_UNIQUE_ADDRESS UnrefBehavior unref_behavior_; }; diff --git a/src/core/lib/gprpp/ref_counted_ptr.h b/src/core/lib/gprpp/ref_counted_ptr.h index adcffe40f1..3da9b7de0f 100644 --- a/src/core/lib/gprpp/ref_counted_ptr.h +++ b/src/core/lib/gprpp/ref_counted_ptr.h @@ -43,7 +43,8 @@ class RefCountedPtr { RefCountedPtr(std::nullptr_t) {} // If value is non-null, we take ownership of a ref to it. - template <typename Y> + template <typename Y, + std::enable_if_t<std::is_convertible<Y*, T*>::value, bool> = true> explicit RefCountedPtr(Y* value) : value_(value) {} // Move ctors. @@ -51,7 +52,8 @@ class RefCountedPtr { value_ = other.value_; other.value_ = nullptr; } - template <typename Y> + template <typename Y, + std::enable_if_t<std::is_convertible<Y*, T*>::value, bool> = true> // NOLINTNEXTLINE(google-explicit-constructor) RefCountedPtr(RefCountedPtr<Y>&& other) noexcept { value_ = static_cast<T*>(other.value_); @@ -63,7 +65,8 @@ class RefCountedPtr { reset(std::exchange(other.value_, nullptr)); return *this; } - template <typename Y> + template <typename Y, + std::enable_if_t<std::is_convertible<Y*, T*>::value, bool> = true> RefCountedPtr& operator=(RefCountedPtr<Y>&& other) noexcept { reset(std::exchange(other.value_, nullptr)); return *this; @@ -74,7 +77,8 @@ class RefCountedPtr { if (other.value_ != nullptr) other.value_->IncrementRefCount(); value_ = other.value_; } - template <typename Y> + template <typename Y, + std::enable_if_t<std::is_convertible<Y*, T*>::value, bool> = true> // NOLINTNEXTLINE(google-explicit-constructor) RefCountedPtr(const RefCountedPtr<Y>& other) { static_assert(std::has_virtual_destructor<T>::value, @@ -92,7 +96,8 @@ class RefCountedPtr { reset(other.value_); return *this; } - template <typename Y> + template <typename Y, + std::enable_if_t<std::is_convertible<Y*, T*>::value, bool> = true> RefCountedPtr& operator=(const RefCountedPtr<Y>& other) { static_assert(std::has_virtual_destructor<T>::value, "T does not have a virtual dtor"); @@ -107,6 +112,12 @@ class RefCountedPtr { if (value_ != nullptr) value_->Unref(); } + // An explicit copy method that supports ref-count tracing. + RefCountedPtr<T> Ref(const DebugLocation& location, const char* reason) { + if (value_ != nullptr) value_->IncrementRefCount(location, reason); + return RefCountedPtr<T>(value_); + } + void swap(RefCountedPtr& other) { std::swap(value_, other.value_); } // If value is non-null, we take ownership of a ref to it. @@ -119,13 +130,15 @@ class RefCountedPtr { T* old_value = std::exchange(value_, value); if (old_value != nullptr) old_value->Unref(location, reason); } - template <typename Y> + template <typename Y, + std::enable_if_t<std::is_convertible<Y*, T*>::value, bool> = true> void reset(Y* value = nullptr) { static_assert(std::has_virtual_destructor<T>::value, "T does not have a virtual dtor"); reset(static_cast<T*>(value)); } - template <typename Y> + template <typename Y, + std::enable_if_t<std::is_convertible<Y*, T*>::value, bool> = true> void reset(const DebugLocation& location, const char* reason, Y* value = nullptr) { static_assert(std::has_virtual_destructor<T>::value, @@ -143,24 +156,34 @@ class RefCountedPtr { T& operator*() const { return *value_; } T* operator->() const { return value_; } - template <typename Y> + template <typename Y, + std::enable_if_t<std::is_base_of<T, Y>::value, bool> = true> + RefCountedPtr<Y> TakeAsSubclass() { + return RefCountedPtr<Y>(static_cast<Y*>(release())); + } + + template <typename Y, + std::enable_if_t<std::is_convertible<Y*, T*>::value, bool> = true> bool operator==(const RefCountedPtr<Y>& other) const { return value_ == other.value_; } - template <typename Y> + template <typename Y, + std::enable_if_t<std::is_convertible<Y*, T*>::value, bool> = true> bool operator==(const Y* other) const { return value_ == other; } bool operator==(std::nullptr_t) const { return value_ == nullptr; } - template <typename Y> + template <typename Y, + std::enable_if_t<std::is_convertible<Y*, T*>::value, bool> = true> bool operator!=(const RefCountedPtr<Y>& other) const { return value_ != other.value_; } - template <typename Y> + template <typename Y, + std::enable_if_t<std::is_convertible<Y*, T*>::value, bool> = true> bool operator!=(const Y* other) const { return value_ != other; } @@ -184,7 +207,8 @@ class WeakRefCountedPtr { WeakRefCountedPtr(std::nullptr_t) {} // If value is non-null, we take ownership of a ref to it. - template <typename Y> + template <typename Y, + std::enable_if_t<std::is_convertible<Y*, T*>::value, bool> = true> explicit WeakRefCountedPtr(Y* value) { value_ = value; } @@ -194,7 +218,8 @@ class WeakRefCountedPtr { value_ = other.value_; other.value_ = nullptr; } - template <typename Y> + template <typename Y, + std::enable_if_t<std::is_convertible<Y*, T*>::value, bool> = true> // NOLINTNEXTLINE(google-explicit-constructor) WeakRefCountedPtr(WeakRefCountedPtr<Y>&& other) noexcept { value_ = static_cast<T*>(other.value_); @@ -206,7 +231,8 @@ class WeakRefCountedPtr { reset(std::exchange(other.value_, nullptr)); return *this; } - template <typename Y> + template <typename Y, + std::enable_if_t<std::is_convertible<Y*, T*>::value, bool> = true> WeakRefCountedPtr& operator=(WeakRefCountedPtr<Y>&& other) noexcept { reset(std::exchange(other.value_, nullptr)); return *this; @@ -217,7 +243,8 @@ class WeakRefCountedPtr { if (other.value_ != nullptr) other.value_->IncrementWeakRefCount(); value_ = other.value_; } - template <typename Y> + template <typename Y, + std::enable_if_t<std::is_convertible<Y*, T*>::value, bool> = true> // NOLINTNEXTLINE(google-explicit-constructor) WeakRefCountedPtr(const WeakRefCountedPtr<Y>& other) { static_assert(std::has_virtual_destructor<T>::value, @@ -235,7 +262,8 @@ class WeakRefCountedPtr { reset(other.value_); return *this; } - template <typename Y> + template <typename Y, + std::enable_if_t<std::is_convertible<Y*, T*>::value, bool> = true> WeakRefCountedPtr& operator=(const WeakRefCountedPtr<Y>& other) { static_assert(std::has_virtual_destructor<T>::value, "T does not have a virtual dtor"); @@ -250,6 +278,13 @@ class WeakRefCountedPtr { if (value_ != nullptr) value_->WeakUnref(); } + // An explicit copy method that supports ref-count tracing. + WeakRefCountedPtr<T> WeakRef(const DebugLocation& location, + const char* reason) { + if (value_ != nullptr) value_->IncrementWeakRefCount(location, reason); + return WeakRefCountedPtr<T>(value_); + } + void swap(WeakRefCountedPtr& other) { std::swap(value_, other.value_); } // If value is non-null, we take ownership of a ref to it. @@ -262,13 +297,15 @@ class WeakRefCountedPtr { T* old_value = std::exchange(value_, value); if (old_value != nullptr) old_value->WeakUnref(location, reason); } - template <typename Y> + template <typename Y, + std::enable_if_t<std::is_convertible<Y*, T*>::value, bool> = true> void reset(Y* value = nullptr) { static_assert(std::has_virtual_destructor<T>::value, "T does not have a virtual dtor"); reset(static_cast<T*>(value)); } - template <typename Y> + template <typename Y, + std::enable_if_t<std::is_convertible<Y*, T*>::value, bool> = true> void reset(const DebugLocation& location, const char* reason, Y* value = nullptr) { static_assert(std::has_virtual_destructor<T>::value, @@ -280,35 +317,41 @@ class WeakRefCountedPtr { // us to pass a ref to idiomatic C code that does not use WeakRefCountedPtr<>. // Once all of our code has been converted to idiomatic C++, this // method should go away. - T* release() { - T* value = value_; - value_ = nullptr; - return value; - } + T* release() { return std::exchange(value_, nullptr); } T* get() const { return value_; } T& operator*() const { return *value_; } T* operator->() const { return value_; } - template <typename Y> + template <typename Y, + std::enable_if_t<std::is_base_of<T, Y>::value, bool> = true> + WeakRefCountedPtr<Y> TakeAsSubclass() { + return WeakRefCountedPtr<Y>(static_cast<Y*>(release())); + } + + template <typename Y, + std::enable_if_t<std::is_convertible<Y*, T*>::value, bool> = true> bool operator==(const WeakRefCountedPtr<Y>& other) const { return value_ == other.value_; } - template <typename Y> + template <typename Y, + std::enable_if_t<std::is_convertible<Y*, T*>::value, bool> = true> bool operator==(const Y* other) const { return value_ == other; } bool operator==(std::nullptr_t) const { return value_ == nullptr; } - template <typename Y> + template <typename Y, + std::enable_if_t<std::is_convertible<Y*, T*>::value, bool> = true> bool operator!=(const WeakRefCountedPtr<Y>& other) const { return value_ != other.value_; } - template <typename Y> + template <typename Y, + std::enable_if_t<std::is_convertible<Y*, T*>::value, bool> = true> bool operator!=(const Y* other) const { return value_ != other; } diff --git a/src/core/lib/gprpp/ref_counted_string.h b/src/core/lib/gprpp/ref_counted_string.h index 8bcdb87eea..dbe32b113d 100644 --- a/src/core/lib/gprpp/ref_counted_string.h +++ b/src/core/lib/gprpp/ref_counted_string.h @@ -21,6 +21,8 @@ #include <stddef.h> +#include <string> + #include "absl/strings/string_view.h" #include "src/core/lib/gprpp/ref_counted.h" @@ -102,6 +104,19 @@ inline bool operator==(const RefCountedStringValue& lhs, return lhs.as_string_view() == rhs.as_string_view(); } +inline bool operator!=(const RefCountedStringValue& lhs, + absl::string_view rhs) { + return lhs.as_string_view() != rhs; +} +inline bool operator!=(absl::string_view lhs, + const RefCountedStringValue& rhs) { + return lhs != rhs.as_string_view(); +} +inline bool operator!=(const RefCountedStringValue& lhs, + const RefCountedStringValue& rhs) { + return lhs.as_string_view() != rhs.as_string_view(); +} + inline bool operator<(const RefCountedStringValue& lhs, absl::string_view rhs) { return lhs.as_string_view() < rhs; } diff --git a/src/core/lib/gprpp/status_helper.cc b/src/core/lib/gprpp/status_helper.cc index bb6c84e81b..85302a985b 100644 --- a/src/core/lib/gprpp/status_helper.cc +++ b/src/core/lib/gprpp/status_helper.cc @@ -22,7 +22,6 @@ #include <string.h> -#include <algorithm> #include <utility> #include "absl/strings/cord.h" @@ -35,8 +34,7 @@ #include "google/protobuf/any.upb.h" #include "google/rpc/status.upb.h" #include "upb/base/string_view.h" -#include "upb/mem/arena.h" -#include "upb/upb.hpp" +#include "upb/mem/arena.hpp" #include <grpc/support/log.h> diff --git a/src/core/lib/gprpp/strerror.cc b/src/core/lib/gprpp/strerror.cc index d2d3e9f926..021e61ba48 100644 --- a/src/core/lib/gprpp/strerror.cc +++ b/src/core/lib/gprpp/strerror.cc @@ -18,8 +18,6 @@ #include <string.h> -#include <initializer_list> - #include "absl/strings/str_format.h" namespace grpc_core { diff --git a/src/core/lib/gprpp/time.cc b/src/core/lib/gprpp/time.cc index 40ba366c57..ba04e3347f 100644 --- a/src/core/lib/gprpp/time.cc +++ b/src/core/lib/gprpp/time.cc @@ -18,7 +18,6 @@ #include <atomic> #include <chrono> -#include <initializer_list> #include <limits> #include <string> #include <utility> diff --git a/src/core/lib/gprpp/uuid_v4.cc b/src/core/lib/gprpp/uuid_v4.cc index ee98556f94..5c3f3cd8e3 100644 --- a/src/core/lib/gprpp/uuid_v4.cc +++ b/src/core/lib/gprpp/uuid_v4.cc @@ -20,8 +20,6 @@ #include "src/core/lib/gprpp/uuid_v4.h" -#include <initializer_list> - #include "absl/strings/str_format.h" namespace grpc_core { diff --git a/src/core/lib/gprpp/validation_errors.cc b/src/core/lib/gprpp/validation_errors.cc index d6fecce934..fd6402e0f3 100644 --- a/src/core/lib/gprpp/validation_errors.cc +++ b/src/core/lib/gprpp/validation_errors.cc @@ -16,7 +16,6 @@ #include "src/core/lib/gprpp/validation_errors.h" -#include <algorithm> #include <utility> #include "absl/status/status.h" diff --git a/src/core/lib/gprpp/windows/directory_reader.cc b/src/core/lib/gprpp/windows/directory_reader.cc new file mode 100644 index 0000000000..3d45ee6532 --- /dev/null +++ b/src/core/lib/gprpp/windows/directory_reader.cc @@ -0,0 +1,81 @@ +// +// +// Copyright 2023 gRPC authors. +// +// 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. +// +// + +#include <grpc/support/port_platform.h> + +#if defined(GPR_WINDOWS) + +#include <sys/stat.h> +#include <windows.h> + +#include <string> +#include <vector> + +#include "absl/status/statusor.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/string_view.h" + +#include <grpc/support/log.h> + +#include "src/core/lib/gprpp/directory_reader.h" +namespace grpc_core { + +namespace { +const char kSkipEntriesSelf[] = "."; +const char kSkipEntriesParent[] = ".."; +} // namespace + +class DirectoryReaderImpl : public DirectoryReader { + public: + explicit DirectoryReaderImpl(absl::string_view directory_path) + : directory_path_(directory_path) {} + absl::string_view Name() const override { return directory_path_; } + absl::Status ForEach(absl::FunctionRef<void(absl::string_view)>) override; + + private: + const std::string directory_path_; +}; + +std::unique_ptr<DirectoryReader> MakeDirectoryReader( + absl::string_view filename) { + return std::make_unique<DirectoryReaderImpl>(filename); +} + +// Reference for reading directory in Windows: +// https://stackoverflow.com/questions/612097/how-can-i-get-the-list-of-files-in-a-directory-using-c-or-c +// https://learn.microsoft.com/en-us/windows/win32/fileio/listing-the-files-in-a-directory +absl::Status DirectoryReaderImpl::ForEach( + absl::FunctionRef<void(absl::string_view)> callback) { + std::string search_path = absl::StrCat(directory_path_, "/*"); + WIN32_FIND_DATAA find_data; + HANDLE hFind = ::FindFirstFileA(search_path.c_str(), &find_data); + if (hFind == INVALID_HANDLE_VALUE) { + return absl::InternalError("Could not read crl directory."); + } + do { + if (!(find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + callback(find_data.cFileName); + } + } while (::FindNextFileA(hFind, &find_data)); + ::FindClose(hFind); + return absl::OkStatus(); +} + +} // namespace grpc_core + +#endif // GPR_WINDOWS diff --git a/src/core/lib/gprpp/work_serializer.cc b/src/core/lib/gprpp/work_serializer.cc index 530238d549..1959deed98 100644 --- a/src/core/lib/gprpp/work_serializer.cc +++ b/src/core/lib/gprpp/work_serializer.cc @@ -262,6 +262,9 @@ void WorkSerializer::LegacyWorkSerializer::DrainQueueOwned() { } // There is at least one callback on the queue. Pop the callback from the // queue and execute it. + if (IsWorkSerializerClearsTimeCacheEnabled() && ExecCtx::Get() != nullptr) { + ExecCtx::Get()->InvalidateNow(); + } CallbackWrapper* cb_wrapper = nullptr; bool empty_unused; while ((cb_wrapper = reinterpret_cast<CallbackWrapper*>( diff --git a/src/core/lib/gprpp/xxhash_inline.h b/src/core/lib/gprpp/xxhash_inline.h new file mode 100644 index 0000000000..6b12c71121 --- /dev/null +++ b/src/core/lib/gprpp/xxhash_inline.h @@ -0,0 +1,29 @@ +// +// Copyright 2023 gRPC authors. +// +// 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 GRPC_SRC_CORE_LIB_GPRPP_XXHASH_INLINE_H +#define GRPC_SRC_CORE_LIB_GPRPP_XXHASH_INLINE_H + +#include <grpc/support/port_platform.h> + +// This header is a simple wrapper around the third-party xxhash +// library, so that we don't need to define XXH_INLINE_ALL in every file +// that includes xxhash.h. That definition confuses clang-format's +// ordering of includes. +#define XXH_INLINE_ALL +#include "xxhash.h" + +#endif // GRPC_SRC_CORE_LIB_GPRPP_XXHASH_INLINE_H |