X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;ds=sidebyside;f=folly%2FAtomicUnorderedMap.h;h=ca867fc1dfa2d0ee71f87418f1e36a655f95ae42;hb=8f4003a8d3b8d95215238d3fd52f85e87d591c0e;hp=4c0afb689aa30426aec8bf4f6d4b990ab8d27a28;hpb=6b17defc455a4b8fb0a57dd23ccdcc4edba91ac5;p=folly.git diff --git a/folly/AtomicUnorderedMap.h b/folly/AtomicUnorderedMap.h index 4c0afb68..ca867fc1 100644 --- a/folly/AtomicUnorderedMap.h +++ b/folly/AtomicUnorderedMap.h @@ -1,5 +1,5 @@ /* - * Copyright 2015 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. @@ -13,24 +13,26 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef FOLLY_ATOMICUNORDEREDMAP_H -#define FOLLY_ATOMICUNORDEREDMAP_H + +#pragma once #include +#include #include +#include #include #include #include -#include -#include -#include -#include + +#include + #include #include +#include #include #include -#include -#include +#include +#include namespace folly { @@ -127,16 +129,17 @@ namespace folly { /// which is much faster than destructing all of the keys and values. /// Feel free to override if std::is_trivial_destructor isn't recognizing /// the triviality of your destructors. -template , - typename KeyEqual = std::equal_to, - bool SkipKeyValueDeletion = - (boost::has_trivial_destructor::value && - boost::has_trivial_destructor::value), - template class Atom = std::atomic, - typename Allocator = folly::detail::MMapAlloc, - typename IndexType = uint32_t> +template < + typename Key, + typename Value, + typename Hash = std::hash, + typename KeyEqual = std::equal_to, + bool SkipKeyValueDeletion = + (boost::has_trivial_destructor::value && + boost::has_trivial_destructor::value), + template class Atom = std::atomic, + typename IndexType = uint32_t, + typename Allocator = folly::detail::MMapAlloc> struct AtomicUnorderedInsertMap { @@ -178,7 +181,7 @@ struct AtomicUnorderedInsertMap { } // post-increment - ConstIterator operator++ (int dummy) { + ConstIterator operator++(int /* dummy */) { auto prev = *this; ++*this; return prev; @@ -210,7 +213,7 @@ struct AtomicUnorderedInsertMap { const Allocator& alloc = Allocator()) : allocator_(alloc) { - size_t capacity = maxSize / std::min(1.0f, maxLoadFactor) + 128; + size_t capacity = size_t(maxSize / std::min(1.0f, maxLoadFactor) + 128); size_t avail = size_t{1} << (8 * sizeof(IndexType) - 2); if (capacity > avail && maxSize < avail) { // we'll do our best @@ -260,7 +263,7 @@ struct AtomicUnorderedInsertMap { /// auto value = memo.findOrConstruct(key, [=](void* raw) { /// new (raw) std::string(computation(key)); /// })->first; - template + template std::pair findOrConstruct(const Key& key, Func&& func) { auto const slot = keyToSlotIdx(key); auto prev = slots_[slot].headAndState_.load(std::memory_order_acquire); @@ -312,7 +315,7 @@ struct AtomicUnorderedInsertMap { /// Eventually we can duplicate all of the std::pair constructor /// forms, including a recursive tuple forwarding template /// http://functionalcpp.wordpress.com/2013/08/28/tuple-forwarding/). - template + template std::pair emplace(const K& key, V&& value) { return findOrConstruct(key, [&](void* raw) { new (raw) Value(std::forward(value)); @@ -336,8 +339,7 @@ struct AtomicUnorderedInsertMap { } private: - - enum { + enum : IndexType { kMaxAllocationTries = 1000, // after this we throw }; @@ -435,7 +437,7 @@ struct AtomicUnorderedInsertMap { /// Allocates a slot and returns its index. Tries to put it near /// slots_[start]. IndexType allocateNear(IndexType start) { - for (auto tries = 0; tries < kMaxAllocationTries; ++tries) { + for (IndexType tries = 0; tries < kMaxAllocationTries; ++tries) { auto slot = allocationAttempt(start, tries); auto prev = slots_[slot].headAndState_.load(std::memory_order_acquire); if ((prev & 3) == EMPTY && @@ -452,13 +454,13 @@ struct AtomicUnorderedInsertMap { /// can specialize it differently during deterministic testing IndexType allocationAttempt(IndexType start, IndexType tries) const { if (LIKELY(tries < 8 && start + tries < numSlots_)) { - return start + tries; + return IndexType(start + tries); } else { IndexType rv; if (sizeof(IndexType) <= 4) { - rv = folly::Random::rand32(numSlots_); + rv = IndexType(folly::Random::rand32(numSlots_)); } else { - rv = folly::Random::rand64(numSlots_); + rv = IndexType(folly::Random::rand64(numSlots_)); } assert(rv < numSlots_); return rv; @@ -477,15 +479,16 @@ struct AtomicUnorderedInsertMap { /// to select a 64 bit slot index type. Use this if you need a capacity /// bigger than 2^30 (about a billion). This increases memory overheads, /// obviously. -template , - typename KeyEqual = std::equal_to, - bool SkipKeyValueDeletion = - (boost::has_trivial_destructor::value && - boost::has_trivial_destructor::value), - template class Atom = std::atomic, - typename Allocator = folly::detail::MMapAlloc> +template < + typename Key, + typename Value, + typename Hash = std::hash, + typename KeyEqual = std::equal_to, + bool SkipKeyValueDeletion = + (boost::has_trivial_destructor::value && + boost::has_trivial_destructor::value), + template class Atom = std::atomic, + typename Allocator = folly::detail::MMapAlloc> using AtomicUnorderedInsertMap64 = AtomicUnorderedInsertMap; - + uint64_t, + Allocator>; /// MutableAtom is a tiny wrapper than gives you the option of atomically /// updating values inserted into an AtomicUnorderedInsertMap>. This relies on AtomicUnorderedInsertMap's guarantee /// that it doesn't move values. -template class Atom = std::atomic> +template class Atom = std::atomic> struct MutableAtom { mutable Atom data; @@ -518,6 +519,4 @@ struct MutableData { explicit MutableData(const T& init) : data(init) {} }; - -} -#endif +} // namespace folly