Parametrize allocator in AtomicHash{Array,Map}
[folly.git] / folly / AtomicHashArray-inl.h
index 236c7c223142a2846427bee85bcf08f944d5607b..81fa1c88a57422279306fc4057f6abaecb39f68d 100644 (file)
@@ -24,8 +24,9 @@
 namespace folly {
 
 // AtomicHashArray private constructor --
-template <class KeyT, class ValueT, class HashFcn, class EqualFcn>
-AtomicHashArray<KeyT, ValueT, HashFcn, EqualFcn>::
+template <class KeyT, class ValueT,
+          class HashFcn, class EqualFcn, class Allocator>
+AtomicHashArray<KeyT, ValueT, HashFcn, EqualFcn, Allocator>::
 AtomicHashArray(size_t capacity, KeyT emptyKey, KeyT lockedKey,
                 KeyT erasedKey, double maxLoadFactor, size_t cacheSize)
     : capacity_(capacity), maxEntries_(size_t(maxLoadFactor * capacity_ + 0.5)),
@@ -41,9 +42,11 @@ AtomicHashArray(size_t capacity, KeyT emptyKey, KeyT lockedKey,
  *   of key and returns true, or if key does not exist returns false and
  *   ret.index is set to capacity_.
  */
-template <class KeyT, class ValueT, class HashFcn, class EqualFcn>
-typename AtomicHashArray<KeyT, ValueT, HashFcn, EqualFcn>::SimpleRetT
-AtomicHashArray<KeyT, ValueT, HashFcn, EqualFcn>::
+template <class KeyT, class ValueT,
+          class HashFcn, class EqualFcn, class Allocator>
+typename AtomicHashArray<KeyT, ValueT,
+         HashFcn, EqualFcn, Allocator>::SimpleRetT
+AtomicHashArray<KeyT, ValueT, HashFcn, EqualFcn, Allocator>::
 findInternal(const KeyT key_in) {
   DCHECK_NE(key_in, kEmptyKey_);
   DCHECK_NE(key_in, kLockedKey_);
@@ -77,10 +80,12 @@ findInternal(const KeyT key_in) {
  *   this will be the previously inserted value, and if the map is full it is
  *   default.
  */
-template <class KeyT, class ValueT, class HashFcn, class EqualFcn>
+template <class KeyT, class ValueT,
+          class HashFcn, class EqualFcn, class Allocator>
 template <class T>
-typename AtomicHashArray<KeyT, ValueT, HashFcn, EqualFcn>::SimpleRetT
-AtomicHashArray<KeyT, ValueT, HashFcn, EqualFcn>::
+typename AtomicHashArray<KeyT, ValueT,
+         HashFcn, EqualFcn, Allocator>::SimpleRetT
+AtomicHashArray<KeyT, ValueT, HashFcn, EqualFcn, Allocator>::
 insertInternal(KeyT key_in, T&& value) {
   const short NO_NEW_INSERTS = 1;
   const short NO_PENDING_INSERTS = 2;
@@ -193,8 +198,9 @@ insertInternal(KeyT key_in, T&& value) {
  *   erased key will never be reused. If there's an associated value, we won't
  *   touch it either.
  */
-template <class KeyT, class ValueT, class HashFcn, class EqualFcn>
-size_t AtomicHashArray<KeyT, ValueT, HashFcn, EqualFcn>::
+template <class KeyT, class ValueT,
+          class HashFcn, class EqualFcn, class Allocator>
+size_t AtomicHashArray<KeyT, ValueT, HashFcn, EqualFcn, Allocator>::
 erase(KeyT key_in) {
   CHECK_NE(key_in, kEmptyKey_);
   CHECK_NE(key_in, kLockedKey_);
@@ -236,13 +242,17 @@ erase(KeyT key_in) {
   }
 }
 
-template <class KeyT, class ValueT, class HashFcn, class EqualFcn>
-const typename AtomicHashArray<KeyT, ValueT, HashFcn, EqualFcn>::Config
-AtomicHashArray<KeyT, ValueT, HashFcn, EqualFcn>::defaultConfig;
-
-template <class KeyT, class ValueT, class HashFcn, class EqualFcn>
-typename AtomicHashArray<KeyT, ValueT, HashFcn, EqualFcn>::SmartPtr
-AtomicHashArray<KeyT, ValueT, HashFcn, EqualFcn>::
+template <class KeyT, class ValueT,
+          class HashFcn, class EqualFcn, class Allocator>
+const typename AtomicHashArray<KeyT, ValueT,
+      HashFcn, EqualFcn, Allocator>::Config
+AtomicHashArray<KeyT, ValueT, HashFcn, EqualFcn, Allocator>::defaultConfig;
+
+template <class KeyT, class ValueT,
+         class HashFcn, class EqualFcn, class Allocator>
+typename AtomicHashArray<KeyT, ValueT,
+         HashFcn, EqualFcn, Allocator>::SmartPtr
+AtomicHashArray<KeyT, ValueT, HashFcn, EqualFcn, Allocator>::
 create(size_t maxSize, const Config& c) {
   CHECK_LE(c.maxLoadFactor, 1.0);
   CHECK_GT(c.maxLoadFactor, 0.0);
@@ -250,10 +260,16 @@ create(size_t maxSize, const Config& c) {
   size_t capacity = size_t(maxSize / c.maxLoadFactor);
   size_t sz = sizeof(AtomicHashArray) + sizeof(value_type) * capacity;
 
-  std::unique_ptr<void, void(*)(void*)> mem(malloc(sz), free);
-  new(mem.get()) AtomicHashArray(capacity, c.emptyKey, c.lockedKey, c.erasedKey,
-                                 c.maxLoadFactor, c.entryCountThreadCacheSize);
-  SmartPtr map(static_cast<AtomicHashArray*>(mem.release()));
+  auto const mem = Allocator().allocate(sz);
+  try {
+    new (mem) AtomicHashArray(capacity, c.emptyKey, c.lockedKey, c.erasedKey,
+                              c.maxLoadFactor, c.entryCountThreadCacheSize);
+  } catch (...) {
+    Allocator().deallocate(mem, sz);
+    throw;
+  }
+
+  SmartPtr map(static_cast<AtomicHashArray*>((void *)mem));
 
   /*
    * Mark all cells as empty.
@@ -274,22 +290,28 @@ create(size_t maxSize, const Config& c) {
   return map;
 }
 
-template <class KeyT, class ValueT, class HashFcn, class EqualFcn>
-void AtomicHashArray<KeyT, ValueT, HashFcn, EqualFcn>::
+template <class KeyT, class ValueT,
+          class HashFcn, class EqualFcn, class Allocator>
+void AtomicHashArray<KeyT, ValueT, HashFcn, EqualFcn, Allocator>::
 destroy(AtomicHashArray* p) {
   assert(p);
+
+  size_t sz = sizeof(AtomicHashArray) + sizeof(value_type) * p->capacity_;
+
   FOR_EACH_RANGE(i, 0, p->capacity_) {
     if (p->cells_[i].first != p->kEmptyKey_) {
       p->cells_[i].~value_type();
     }
   }
   p->~AtomicHashArray();
-  free(p);
+
+  Allocator().deallocate((char *)p, sz);
 }
 
 // clear -- clears all keys and values in the map and resets all counters
-template <class KeyT, class ValueT, class HashFcn, class EqualFcn>
-void AtomicHashArray<KeyT, ValueT, HashFcn, EqualFcn>::
+template <class KeyT, class ValueT,
+          class HashFcn, class EqualFcn, class Allocator>
+void AtomicHashArray<KeyT, ValueT, HashFcn, EqualFcn, Allocator>::
 clear() {
   FOR_EACH_RANGE(i, 0, capacity_) {
     if (cells_[i].first != kEmptyKey_) {
@@ -307,9 +329,10 @@ clear() {
 
 // Iterator implementation
 
-template <class KeyT, class ValueT, class HashFcn, class EqualFcn>
+template <class KeyT, class ValueT,
+          class HashFcn, class EqualFcn, class Allocator>
 template <class ContT, class IterVal>
-struct AtomicHashArray<KeyT, ValueT, HashFcn, EqualFcn>::aha_iterator
+struct AtomicHashArray<KeyT, ValueT, HashFcn, EqualFcn, Allocator>::aha_iterator
     : boost::iterator_facade<aha_iterator<ContT,IterVal>,
                              IterVal,
                              boost::forward_traversal_tag>