/*
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2015 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <type_traits>
#include <utility>
+#include <folly/FormatTraits.h>
#include <folly/Likely.h>
#include <folly/Malloc.h>
#include <folly/Traits.h>
#include <boost/operators.hpp>
-// some files expected these from FBVector
-#include <limits>
-#include <folly/Foreach.h>
-#include <boost/type_traits.hpp>
-#include <boost/utility/enable_if.hpp>
-
//=============================================================================
// forward declaration
// constructors
Impl() : Allocator(), b_(nullptr), e_(nullptr), z_(nullptr) {}
- Impl(const Allocator& a)
+ /* implicit */ Impl(const Allocator& a)
: Allocator(a), b_(nullptr), e_(nullptr), z_(nullptr) {}
- Impl(Allocator&& a)
+ /* implicit */ Impl(Allocator&& a)
: Allocator(std::move(a)), b_(nullptr), e_(nullptr), z_(nullptr) {}
- Impl(size_type n, const Allocator& a = Allocator())
+ /* implicit */ Impl(size_type n, const Allocator& a = Allocator())
: Allocator(a)
{ init(n); }
- Impl(Impl&& other)
+ Impl(Impl&& other) noexcept
: Allocator(std::move(other)),
b_(other.b_), e_(other.e_), z_(other.z_)
{ other.b_ = other.e_ = other.z_ = nullptr; }
static void
S_uninitialized_copy_bits(T* dest, const T* first, const T* last) {
- std::memcpy(dest, first, (last - first) * sizeof(T));
+ std::memcpy((void*)dest, (void*)first, (last - first) * sizeof(T));
}
static void
std::move_iterator<T*> last) {
T* bFirst = first.base();
T* bLast = last.base();
- std::memcpy(dest, bFirst, (bLast - bFirst) * sizeof(T));
+ std::memcpy((void*)dest, (void*)bFirst, (bLast - bFirst) * sizeof(T));
}
template <typename It>
static const T* S_copy_n(T* dest, const T* first, size_type n) {
if (folly::IsTriviallyCopyable<T>::value) {
- std::memcpy(dest, first, n * sizeof(T));
+ std::memcpy((void*)dest, (void*)first, n * sizeof(T));
return first + n;
} else {
return S_copy_n<const T*>(dest, first, n);
S_copy_n(T* dest, std::move_iterator<T*> mIt, size_type n) {
if (folly::IsTriviallyCopyable<T>::value) {
T* first = mIt.base();
- std::memcpy(dest, first, n * sizeof(T));
+ std::memcpy((void*)dest, (void*)first, n * sizeof(T));
return std::make_move_iterator(first + n);
} else {
return S_copy_n<std::move_iterator<T*>>(dest, mIt, n);
}
void relocate_move_or_memcpy(T* dest, T* first, T* last, std::true_type) {
- std::memcpy(dest, first, (last - first) * sizeof(T));
+ std::memcpy((void*)dest, (void*)first, (last - first) * sizeof(T));
}
void relocate_move_or_memcpy(T* dest, T* first, T* last, std::false_type) {
}
// done
- void relocate_done(T* dest, T* first, T* last) noexcept {
+ void relocate_done(T* /*dest*/, T* first, T* last) noexcept {
if (folly::IsRelocatable<T>::value && usingStdAllocator::value) {
// used memcpy; data has been relocated, do not call destructor
} else {
fbvector(const fbvector& other, const Allocator& a)
: fbvector(other.begin(), other.end(), a) {}
- fbvector(fbvector&& other, const Allocator& a) : impl_(a) {
+ /* may throw */ fbvector(fbvector&& other, const Allocator& a) : impl_(a) {
if (impl_ == other.impl_) {
impl_.swapData(other.impl_);
} else {
template <class ForwardIterator>
void assign(ForwardIterator first, ForwardIterator last,
std::forward_iterator_tag) {
- auto const newSize = std::distance(first, last);
+ const size_t newSize = std::distance(first, last);
if (newSize > capacity()) {
impl_.reset(newSize);
M_uninitialized_copy_e(first, last);
}
void shrink_to_fit() noexcept {
+ if (empty()) {
+ // Just skip reallocation.
+ *this = fbvector();
+ return;
+ }
+
auto const newCapacityBytes = folly::goodMallocSize(size() * sizeof(T));
auto const newCap = newCapacityBytes / sizeof(T);
auto const oldCap = capacity();
if (newCap >= oldCap) return;
void* p = impl_.b_;
- if ((rallocm && usingStdAllocator::value) &&
+ // xallocx() will shrink to precisely newCapacityBytes (which was generated
+ // by goodMallocSize()) if it successfully shrinks in place.
+ if ((usingJEMalloc() && usingStdAllocator::value) &&
newCapacityBytes >= folly::jemallocMinInPlaceExpandable &&
- rallocm(&p, nullptr, newCapacityBytes, 0, ALLOCM_NO_MOVE)
- == ALLOCM_SUCCESS) {
+ xallocx(p, newCapacityBytes, 0, 0) == newCapacityBytes) {
impl_.z_ += newCap - oldCap;
} else {
T* newB; // intentionally uninitialized
private:
bool reserve_in_place(size_type n) {
- if (!usingStdAllocator::value || !rallocm) return false;
+ if (!usingStdAllocator::value || !usingJEMalloc()) return false;
// jemalloc can never grow in place blocks smaller than 4096 bytes.
if ((impl_.z_ - impl_.b_) * sizeof(T) <
auto const newCapacityBytes = folly::goodMallocSize(n * sizeof(T));
void* p = impl_.b_;
- if (rallocm(&p, nullptr, newCapacityBytes, 0, ALLOCM_NO_MOVE)
- == ALLOCM_SUCCESS) {
+ if (xallocx(p, newCapacityBytes, 0, 0) == newCapacityBytes) {
impl_.z_ = impl_.b_ + newCapacityBytes / sizeof(T);
return true;
}
//
size_type computePushBackCapacity() const {
- return empty() ? std::max(64 / sizeof(T), size_type(1))
- : capacity() < folly::jemallocMinInPlaceExpandable / sizeof(T)
- ? capacity() * 2
- : sizeof(T) > folly::jemallocMinInPlaceExpandable / 2 && capacity() == 1
- ? 2
- : capacity() > 4096 * 32 / sizeof(T)
- ? capacity() * 2
- : (capacity() * 3 + 1) / 2;
+ if (capacity() == 0) {
+ return std::max(64 / sizeof(T), size_type(1));
+ }
+ if (capacity() < folly::jemallocMinInPlaceExpandable / sizeof(T)) {
+ return capacity() * 2;
+ }
+ if (capacity() > 4096 * 32 / sizeof(T)) {
+ return capacity() * 2;
+ }
+ return (capacity() * 3 + 1) / 2;
}
template <class... Args>
if (folly::IsRelocatable<T>::value && usingStdAllocator::value) {
D_destroy_range_a((iterator)first, (iterator)last);
if (last - first >= cend() - last) {
- std::memcpy((iterator)first, last, (cend() - last) * sizeof(T));
+ std::memcpy((void*)first, (void*)last, (cend() - last) * sizeof(T));
} else {
std::memmove((iterator)first, last, (cend() - last) * sizeof(T));
}
assert(size() + n <= capacity());
assert(n != 0);
- auto tail = std::distance(position, impl_.e_);
+ // The result is guaranteed to be non-negative, so use an unsigned type:
+ size_type tail = std::distance(position, impl_.e_);
if (tail <= n) {
relocate_move(position + n, position, impl_.e_);
size_type byte_sz = folly::goodMallocSize(
computePushBackCapacity() * sizeof(T));
if (usingStdAllocator::value
- && rallocm
+ && usingJEMalloc()
&& ((impl_.z_ - impl_.b_) * sizeof(T) >=
folly::jemallocMinInPlaceExpandable)) {
// Try to reserve in place.
- // Ask rallocm to allocate in place at least size()+1 and at most sz space.
- // rallocm will allocate as much as possible within that range, which
+ // Ask xallocx to allocate in place at least size()+1 and at most sz space.
+ // xallocx will allocate as much as possible within that range, which
// is the best possible outcome: if sz space is available, take it all,
// otherwise take as much as possible. If nothing is available, then fail.
// In this fashion, we never relocate if there is a possibility of
- // expanding in place, and we never relocate by less than the desired
- // amount unless we cannot expand further. Hence we will not relocate
+ // expanding in place, and we never reallocate by less than the desired
+ // amount unless we cannot expand further. Hence we will not reallocate
// sub-optimally twice in a row (modulo the blocking memory being freed).
size_type lower = folly::goodMallocSize(sizeof(T) + size() * sizeof(T));
size_type upper = byte_sz;
void* p = impl_.b_;
size_t actual;
- if (rallocm(&p, &actual, lower, extra, ALLOCM_NO_MOVE)
- == ALLOCM_SUCCESS) {
+ if ((actual = xallocx(p, lower, extra, 0)) >= lower) {
impl_.z_ = impl_.b_ + actual / sizeof(T);
M_construct(impl_.e_, std::forward<Args>(args)...);
++impl_.e_;
//-----------------------------------------------------------------------------
// other
+namespace detail {
+
+// Format support.
+template <class T, class A>
+struct IndexableTraits<fbvector<T, A>>
+ : public IndexableTraitsSeq<fbvector<T, A>> {
+};
+
+} // namespace detail
+
template <class T, class A>
void compactResize(fbvector<T, A>* v, size_t sz) {
v->resize(sz);