summaryrefslogtreecommitdiff
path: root/absl/strings/internal
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2020-07-30 13:58:50 -0700
committerGravatar Mark Barolak <mbar@google.com>2020-07-31 11:30:59 -0400
commit184cf2524101310a0ba315c743e82cf45fccccf8 (patch)
tree61f5cb2de5da31efd024ce2a49f2d304352b33ba /absl/strings/internal
parent82302f1e05d6daed93bdd77e8951b529b0ebfcf6 (diff)
Export of internal Abseil changes
-- 587e6db882749fa7faa12815e614afab04d218b9 by Derek Mauro <dmauro@google.com>: Use attribute detection for other sanitizer related attributes PiperOrigin-RevId: 324077073 -- 3ee55e4935b4235516b1fcac3c55945e510f7afc by Evan Brown <ezb@google.com>: Simplify CordRepExternal allocation/deallocation. I think this can save some memory when `Releaser` is empty and when on platforms where alignof(CordRepExternal) < (default `::operator new` alignment). We no longer need the API requirement that alignof(Releaser) <= (default `::operator new` alignment). Also remove another static_assert from a TODO in cord_internal.h and fix some warnings about calling std::move on a forwarding reference. PiperOrigin-RevId: 324053720 -- 9fc78436565eb3b204d4aa425ee3773354392f45 by Derek Mauro <dmauro@google.com>: Use auto-detected sanitizer attributes for ASAN, MSAN, and TSAN builds PiperOrigin-RevId: 323831461 GitOrigin-RevId: 587e6db882749fa7faa12815e614afab04d218b9 Change-Id: Ie0e4a2846d7f66988a2d81a5e50721b62fdb3d6d
Diffstat (limited to 'absl/strings/internal')
-rw-r--r--absl/strings/internal/cord_internal.h65
1 files changed, 44 insertions, 21 deletions
diff --git a/absl/strings/internal/cord_internal.h b/absl/strings/internal/cord_internal.h
index 830ceaf4..d456eef8 100644
--- a/absl/strings/internal/cord_internal.h
+++ b/absl/strings/internal/cord_internal.h
@@ -21,6 +21,8 @@
#include <cstdint>
#include <type_traits>
+#include "absl/base/internal/invoke.h"
+#include "absl/container/internal/compressed_tuple.h"
#include "absl/meta/type_traits.h"
#include "absl/strings/string_view.h"
@@ -114,35 +116,56 @@ struct CordRepSubstring : public CordRep {
CordRep* child;
};
-// TODO(strel): replace the following logic (and related functions in cord.cc)
-// with container_internal::Layout.
-
-// Alignment requirement for CordRepExternal so that the type erased releaser
-// will be stored at a suitably aligned address.
-constexpr size_t ExternalRepAlignment() {
-#if defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__)
- return __STDCPP_DEFAULT_NEW_ALIGNMENT__;
-#else
- return alignof(max_align_t);
-#endif
-}
-
-// Type for function pointer that will invoke and destroy the type-erased
-// releaser function object. Accepts a pointer to the releaser and the
-// `string_view` that were passed in to `NewExternalRep` below. The return value
-// is the size of the `Releaser` type.
-using ExternalReleaserInvoker = size_t (*)(void*, absl::string_view);
+// Type for function pointer that will invoke the releaser function and also
+// delete the `CordRepExternalImpl` corresponding to the passed in
+// `CordRepExternal`.
+using ExternalReleaserInvoker = void (*)(CordRepExternal*);
// External CordReps are allocated together with a type erased releaser. The
// releaser is stored in the memory directly following the CordRepExternal.
-struct alignas(ExternalRepAlignment()) CordRepExternal : public CordRep {
+struct CordRepExternal : public CordRep {
const char* base;
// Pointer to function that knows how to call and destroy the releaser.
ExternalReleaserInvoker releaser_invoker;
};
-// TODO(strel): look into removing, it doesn't seem like anything relies on this
-static_assert(sizeof(CordRepConcat) == sizeof(CordRepSubstring), "");
+struct Rank1 {};
+struct Rank0 : Rank1 {};
+
+template <typename Releaser, typename = ::absl::base_internal::invoke_result_t<
+ Releaser, absl::string_view>>
+void InvokeReleaser(Rank0, Releaser&& releaser, absl::string_view data) {
+ ::absl::base_internal::invoke(std::forward<Releaser>(releaser), data);
+}
+
+template <typename Releaser,
+ typename = ::absl::base_internal::invoke_result_t<Releaser>>
+void InvokeReleaser(Rank1, Releaser&& releaser, absl::string_view) {
+ ::absl::base_internal::invoke(std::forward<Releaser>(releaser));
+}
+
+// We use CompressedTuple so that we can benefit from EBCO.
+template <typename Releaser>
+struct CordRepExternalImpl
+ : public CordRepExternal,
+ public ::absl::container_internal::CompressedTuple<Releaser> {
+ // The extra int arg is so that we can avoid interfering with copy/move
+ // constructors while still benefitting from perfect forwarding.
+ template <typename T>
+ CordRepExternalImpl(T&& releaser, int)
+ : CordRepExternalImpl::CompressedTuple(std::forward<T>(releaser)) {
+ this->releaser_invoker = &Release;
+ }
+
+ ~CordRepExternalImpl() {
+ InvokeReleaser(Rank0{}, std::move(this->template get<0>()),
+ absl::string_view(base, length));
+ }
+
+ static void Release(CordRepExternal* rep) {
+ delete static_cast<CordRepExternalImpl*>(rep);
+ }
+};
} // namespace cord_internal
ABSL_NAMESPACE_END