wait_free_array_value_pool-inl.h 3.77 KB
Newer Older
1
/*
Marcus Winter committed
2
 * Copyright (c) 2014-2016, Siemens AG. All rights reserved.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef EMBB_CONTAINERS_INTERNAL_WAIT_FREE_ARRAY_VALUE_POOL_INL_H_
#define EMBB_CONTAINERS_INTERNAL_WAIT_FREE_ARRAY_VALUE_POOL_INL_H_

namespace embb {
namespace containers {
32 33 34
template<typename Type, Type Undefined, class Allocator >
void WaitFreeArrayValuePool<Type, Undefined, Allocator>::
Free(Type element, int index) {
35 36 37
  assert(element != Undefined);

  // Just put back the element
38
  pool_array_[index].Store(element);
39 40
}

41 42 43
template<typename Type, Type Undefined, class Allocator >
int WaitFreeArrayValuePool<Type, Undefined, Allocator>::
Allocate(Type & element) {
44
  for (int i = 0; i != size_; ++i) {
45
    Type expected;
46 47

    // If the memory cell is not available, go ahead
48
    if (Undefined == (expected = pool_array_[i].Load()))
49 50 51
      continue;

    // Try to get the memory cell
52
    if (pool_array_[i].CompareAndSwap(expected, Undefined)) {
53 54 55 56 57 58 59 60
      // When the CAS was successful, this element is ours
      element = expected;
      return i;
    }
  }
  return -1;
}

61
template<typename Type, Type Undefined, class Allocator >
62
template<typename ForwardIterator>
63
WaitFreeArrayValuePool<Type, Undefined, Allocator>::
64 65 66
WaitFreeArrayValuePool(ForwardIterator first, ForwardIterator last) {
  size_t dist = static_cast<size_t>(std::distance(first, last));

67 68 69 70
  size_ = static_cast<int>(dist);

  // conversion may result in negative number. check!
  assert(size_ >= 0);
71

72
  // Use the allocator to allocate an array of size dist
73 74 75 76 77 78
  pool_array_ = allocator_.allocate(dist);

  // invoke inplace new for each pool element
  for ( size_t i = 0; i != dist; ++i ) {
    new (&pool_array_[i]) embb::base::Atomic<Type>();
  }
79

80 81 82 83
  int i = 0;

  // Store the elements of the range
  for (ForwardIterator curIter(first); curIter != last; ++curIter) {
84
    pool_array_[i++] = *curIter;
85 86 87
  }
}

88 89
template<typename Type, Type Undefined, class Allocator >
WaitFreeArrayValuePool<Type, Undefined, Allocator>::~WaitFreeArrayValuePool() {
90 91 92 93 94 95 96
  // invoke destructor for each pool element
  for (int i = 0; i != size_; ++i) {
    pool_array_[i].~Atomic();
  }

  // free memory
  allocator_.deallocate(pool_array_, static_cast<size_t>(size_));
97
}
98 99 100 101 102 103 104 105

template<typename Type, Type Undefined, class Allocator >
size_t WaitFreeArrayValuePool<Type, Undefined, Allocator>::
GetMinimumElementCountForGuaranteedCapacity(size_t capacity) {
  // for this value pool, this is just capacity...
  return capacity;
}

106 107 108 109
} // namespace containers
} // namespace embb

#endif  // EMBB_CONTAINERS_INTERNAL_WAIT_FREE_ARRAY_VALUE_POOL_INL_H_