-- d85f04af95a6fdafb102f7dc393d78d4431b47e5 by Abseil Team <absl-team@google.com>: Internal change for cord ring PiperOrigin-RevId: 344541196 -- 1ff57908e31a09ec0c98d8316da1263092cc3a1c by Abseil Team <absl-team@google.com>: Fix typo in comment. PiperOrigin-RevId: 344214280 GitOrigin-RevId: d85f04af95a6fdafb102f7dc393d78d4431b47e5 Change-Id: I58b3c28f62a5d10dd665b17d58a121f371e1260apull/861/head
parent
5d8fc91922
commit
e80c0b3536
7 changed files with 180 additions and 109 deletions
@ -0,0 +1,129 @@ |
||||
// Copyright 2020 The Abseil 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
|
||||
//
|
||||
// https://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 ABSL_STRINGS_INTERNAL_CORD_REP_FLAT_H_ |
||||
#define ABSL_STRINGS_INTERNAL_CORD_REP_FLAT_H_ |
||||
|
||||
#include <cassert> |
||||
#include <cstddef> |
||||
#include <cstdint> |
||||
#include <memory> |
||||
|
||||
#include "absl/strings/internal/cord_internal.h" |
||||
|
||||
namespace absl { |
||||
ABSL_NAMESPACE_BEGIN |
||||
namespace cord_internal { |
||||
|
||||
// Note: all constants below are never ODR used and internal to cord, we define
|
||||
// these as static constexpr to avoid 'in struct' definition and usage clutter.
|
||||
|
||||
// Largest and smallest flat node lengths we are willing to allocate
|
||||
// Flat allocation size is stored in tag, which currently can encode sizes up
|
||||
// to 4K, encoded as multiple of either 8 or 32 bytes.
|
||||
// If we allow for larger sizes, we need to change this to 8/64, 16/128, etc.
|
||||
// kMinFlatSize is bounded by tag needing to be at least FLAT * 8 bytes, and
|
||||
// ideally a 'nice' size aligning with allocation and cacheline sizes like 32.
|
||||
// kMaxFlatSize is bounded by the size resulting in a computed tag no greater
|
||||
// than MAX_FLAT_TAG. MAX_FLAT_TAG provides for additional 'high' tag values.
|
||||
static constexpr size_t kFlatOverhead = offsetof(CordRep, data); |
||||
static constexpr size_t kMinFlatSize = 32; |
||||
static constexpr size_t kMaxFlatSize = 4096; |
||||
static constexpr size_t kMaxFlatLength = kMaxFlatSize - kFlatOverhead; |
||||
static constexpr size_t kMinFlatLength = kMinFlatSize - kFlatOverhead; |
||||
|
||||
static constexpr size_t AllocatedSizeToTagUnchecked(size_t size) { |
||||
return (size <= 1024) ? size / 8 : 128 + size / 32 - 1024 / 32; |
||||
} |
||||
|
||||
static_assert(kMinFlatSize / 8 >= FLAT, ""); |
||||
static_assert(AllocatedSizeToTagUnchecked(kMaxFlatSize) <= MAX_FLAT_TAG, ""); |
||||
|
||||
// Helper functions for rounded div, and rounding to exact sizes.
|
||||
static size_t DivUp(size_t n, size_t m) { return (n + m - 1) / m; } |
||||
static size_t RoundUp(size_t n, size_t m) { return DivUp(n, m) * m; } |
||||
|
||||
// Returns the size to the nearest equal or larger value that can be
|
||||
// expressed exactly as a tag value.
|
||||
static size_t RoundUpForTag(size_t size) { |
||||
return RoundUp(size, (size <= 1024) ? 8 : 32); |
||||
} |
||||
|
||||
// Converts the allocated size to a tag, rounding down if the size
|
||||
// does not exactly match a 'tag expressible' size value. The result is
|
||||
// undefined if the size exceeds the maximum size that can be encoded in
|
||||
// a tag, i.e., if size is larger than TagToAllocatedSize(<max tag>).
|
||||
static uint8_t AllocatedSizeToTag(size_t size) { |
||||
const size_t tag = AllocatedSizeToTagUnchecked(size); |
||||
assert(tag <= MAX_FLAT_TAG); |
||||
return tag; |
||||
} |
||||
|
||||
// Converts the provided tag to the corresponding allocated size
|
||||
static constexpr size_t TagToAllocatedSize(uint8_t tag) { |
||||
return (tag <= 128) ? (tag * 8) : (1024 + (tag - 128) * 32); |
||||
} |
||||
|
||||
// Converts the provided tag to the corresponding available data length
|
||||
static constexpr size_t TagToLength(uint8_t tag) { |
||||
return TagToAllocatedSize(tag) - kFlatOverhead; |
||||
} |
||||
|
||||
// Enforce that kMaxFlatSize maps to a well-known exact tag value.
|
||||
static_assert(TagToAllocatedSize(224) == kMaxFlatSize, "Bad tag logic"); |
||||
|
||||
struct CordRepFlat : public CordRep { |
||||
// Creates a new flat node.
|
||||
static CordRepFlat* New(size_t len) { |
||||
if (len <= kMinFlatLength) { |
||||
len = kMinFlatLength; |
||||
} else if (len > kMaxFlatLength) { |
||||
len = kMaxFlatLength; |
||||
} |
||||
|
||||
// Round size up so it matches a size we can exactly express in a tag.
|
||||
const size_t size = RoundUpForTag(len + kFlatOverhead); |
||||
void* const raw_rep = ::operator new(size); |
||||
CordRepFlat* rep = new (raw_rep) CordRepFlat(); |
||||
rep->tag = AllocatedSizeToTag(size); |
||||
return rep; |
||||
} |
||||
|
||||
// Deletes a CordRepFlat instance created previously through a call to New().
|
||||
// Flat CordReps are allocated and constructed with raw ::operator new and
|
||||
// placement new, and must be destructed and deallocated accordingly.
|
||||
static void Delete(CordRep*rep) { |
||||
assert(rep->tag >= FLAT); |
||||
#if defined(__cpp_sized_deallocation) |
||||
size_t size = TagToAllocatedSize(rep->tag); |
||||
rep->~CordRep(); |
||||
::operator delete(rep, size); |
||||
#else |
||||
rep->~CordRep(); |
||||
::operator delete(rep); |
||||
#endif |
||||
} |
||||
|
||||
// Returns the maximum capacity (payload size) of this instance.
|
||||
size_t Capacity() const { return TagToLength(tag); } |
||||
|
||||
// Returns the allocated size (payload + overhead) of this instance.
|
||||
size_t AllocatedSize() const { return TagToAllocatedSize(tag); } |
||||
}; |
||||
|
||||
} // namespace cord_internal
|
||||
ABSL_NAMESPACE_END |
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_STRINGS_INTERNAL_CORD_REP_FLAT_H_
|
Loading…
Reference in new issue