X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2Fsmall_vector.h;h=db36acc072b5c9ddd0de5cf83a235a683435447c;hb=a857f83b2b25f42eeba1524ebca1bd2e74abc71a;hp=b03eec05f3a3281ba3b73b05dba18d86300dab2b;hpb=67a4edadf17fc386d11fc26c5c47d0da12c0be48;p=folly.git diff --git a/folly/small_vector.h b/folly/small_vector.h index b03eec05..db36acc0 100644 --- a/folly/small_vector.h +++ b/folly/small_vector.h @@ -1,5 +1,5 @@ /* - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,10 +20,8 @@ * * @author Jordan DeLong */ -#ifndef FOLLY_SMALL_VECTOR_H_ -#define FOLLY_SMALL_VECTOR_H_ -#include +#pragma once #include #include @@ -44,30 +42,15 @@ #include #include #include -#include +#include #include - -#if defined(__GNUC__) && FOLLY_X64 -# include -# define FB_PACK_ATTR FOLLY_PACK_ATTR -# define FB_PACK_PUSH FOLLY_PACK_PUSH -# define FB_PACK_POP FOLLY_PACK_POP -#else -# define FB_PACK_ATTR -# define FB_PACK_PUSH -# define FB_PACK_POP -#endif - -#if FOLLY_HAVE_MALLOC_SIZE - extern "C" std::size_t malloc_size(const void*); -# if !FOLLY_HAVE_MALLOC_USABLE_SIZE -# define malloc_usable_size malloc_size -# endif -# ifndef malloc_usable_size -# define malloc_usable_size malloc_size -# endif -#endif +#include +#include +#include +#include +#include +#include // Ignore shadowing warnings within this file, so includers can use -Wshadow. #pragma GCC diagnostic push @@ -342,7 +325,7 @@ namespace detail { } ////////////////////////////////////////////////////////////////////// -FB_PACK_PUSH +FOLLY_PACK_PUSH template, - boost::mpl::int_ - >::type::value - }; + static constexpr std::size_t MaxInline{ + constexpr_max(sizeof(Value*) / sizeof(Value), RequestedMaxInline)}; -public: + public: typedef std::size_t size_type; typedef Value value_type; typedef value_type& reference; @@ -382,7 +361,7 @@ public: typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; - explicit small_vector() {} + explicit small_vector() = default; small_vector(small_vector const& o) { auto n = o.size(); @@ -458,7 +437,7 @@ public: } static constexpr size_type max_size() { - return !BaseType::kShouldUseHeap ? MaxInline + return !BaseType::kShouldUseHeap ? static_cast(MaxInline) : BaseType::policyMaxSize(); } @@ -658,6 +637,17 @@ public: emplaceBack(std::forward(args)...); } + void emplace_back(const value_type& t) { + push_back(t); + } + void emplace_back(value_type& t) { + push_back(t); + } + + void emplace_back(value_type&& t) { + push_back(std::move(t)); + } + void push_back(value_type&& t) { if (capacity() == size()) { makeSize(std::max(size_type(2), 3 * size() / 2), &t, size()); @@ -668,9 +658,17 @@ public: } void push_back(value_type const& t) { - // Make a copy and forward to the rvalue value_type&& overload - // above. - push_back(value_type(t)); + // TODO: we'd like to make use of makeSize (it can be optimized better, + // because it manipulates the internals) + // unfortunately the current implementation only supports moving from + // a supplied rvalue, and doing an extra move just to reuse it is a perf + // net loss + if (size() == capacity()) {// && isInside(&t)) { + value_type tmp(t); + emplaceBack(std::move(tmp)); + } else { + emplaceBack(t); + } } void pop_back() { @@ -784,14 +782,14 @@ public: reference at(size_type i) { if (i >= size()) { - throw std::out_of_range("index out of range"); + std::__throw_out_of_range("index out of range"); } return (*this)[i]; } const_reference at(size_type i) const { if (i >= size()) { - throw std::out_of_range("index out of range"); + std::__throw_out_of_range("index out of range"); } return (*this)[i]; } @@ -809,13 +807,6 @@ private: this->setSize(size() + 1); } - /* - * Special case of emplaceBack for rvalue - */ - void emplaceBack(value_type&& t) { - push_back(std::move(t)); - } - static iterator unconst(const_iterator it) { return const_cast(it); } @@ -871,7 +862,7 @@ private: // With iterators that only allow a single pass, we can't really // do anything sane here. while (first != last) { - push_back(*first++); + emplace_back(*first++); } return; } @@ -1032,7 +1023,7 @@ private: InternalSizeType* getCapacity() { return &capacity_; } - } FB_PACK_ATTR; + } FOLLY_PACK_ATTR; struct HeapPtr { // Lower order bit of heap_ is used as flag to indicate whether capacity is @@ -1044,17 +1035,23 @@ private: return static_cast( detail::pointerFlagClear(heap_)); } - } FB_PACK_ATTR; + } FOLLY_PACK_ATTR; -#if FOLLY_X64 - typedef unsigned char InlineStorageType[sizeof(value_type) * MaxInline]; +#if (FOLLY_X64 || FOLLY_PPC64) + typedef unsigned char InlineStorageDataType[sizeof(value_type) * MaxInline]; #else typedef typename std::aligned_storage< sizeof(value_type) * MaxInline, alignof(value_type) - >::type InlineStorageType; + >::type InlineStorageDataType; #endif + typedef typename std::conditional< + sizeof(value_type) * MaxInline != 0, + InlineStorageDataType, + void* + >::type InlineStorageType; + static bool const kHasInlineCapacity = sizeof(HeapPtrWithCapacity) < sizeof(InlineStorageType); @@ -1113,9 +1110,9 @@ private: auto vp = detail::pointerFlagClear(pdata_.heap_); free(vp); } - } FB_PACK_ATTR u; -} FB_PACK_ATTR; -FB_PACK_POP + } FOLLY_PACK_ATTR u; +} FOLLY_PACK_ATTR; +FOLLY_PACK_POP ////////////////////////////////////////////////////////////////////// @@ -1129,14 +1126,16 @@ void swap(small_vector& a, ////////////////////////////////////////////////////////////////////// -} +namespace detail { -#pragma GCC diagnostic pop +// Format support. +template +struct IndexableTraits> + : public IndexableTraitsSeq> { +}; -#ifdef FB_PACK_ATTR -# undef FB_PACK_ATTR -# undef FB_PACK_PUSH -# undef FB_PACK_POP -#endif +} // namespace detail -#endif +} // namespace folly + +#pragma GCC diagnostic pop