Commit 2b554f74 by Christian Kern

Continue implementation for ticket #520, fix some code style issues

parent db969583
...@@ -42,7 +42,7 @@ template<typename Type, Type Undefined, class PoolAllocator, ...@@ -42,7 +42,7 @@ template<typename Type, Type Undefined, class PoolAllocator,
class TreeAllocator > class TreeAllocator >
bool LockFreeTreeValuePool<Type, Undefined, PoolAllocator, TreeAllocator>:: bool LockFreeTreeValuePool<Type, Undefined, PoolAllocator, TreeAllocator>::
IsLeaf(int node) { IsLeaf(int node) {
if (node >= size - 1 && node <= 2 * size - 1) { if (node >= size_ - 1 && node <= 2 * size_ - 1) {
return true; return true;
} }
return false; return false;
...@@ -52,7 +52,7 @@ template<typename Type, Type Undefined, class PoolAllocator, ...@@ -52,7 +52,7 @@ template<typename Type, Type Undefined, class PoolAllocator,
class TreeAllocator > class TreeAllocator >
bool LockFreeTreeValuePool<Type, Undefined, PoolAllocator, TreeAllocator>:: bool LockFreeTreeValuePool<Type, Undefined, PoolAllocator, TreeAllocator>::
IsValid(int node) { IsValid(int node) {
return (node >= 0 && node <= 2 * size - 1); return (node >= 0 && node <= 2 * size_ - 1);
} }
template<typename Type, Type Undefined, class PoolAllocator, template<typename Type, Type Undefined, class PoolAllocator,
...@@ -77,14 +77,14 @@ template<typename T, T Undefined, class PoolAllocator, class TreeAllocator > ...@@ -77,14 +77,14 @@ template<typename T, T Undefined, class PoolAllocator, class TreeAllocator >
int LockFreeTreeValuePool<T, Undefined, PoolAllocator, TreeAllocator>:: int LockFreeTreeValuePool<T, Undefined, PoolAllocator, TreeAllocator>::
NodeIndexToPoolIndex(int node) { NodeIndexToPoolIndex(int node) {
assert(IsLeaf(node)); assert(IsLeaf(node));
return(node - (size - 1)); return(node - (size_ - 1));
} }
template<typename Type, Type Undefined, class PoolAllocator, template<typename Type, Type Undefined, class PoolAllocator,
class TreeAllocator > class TreeAllocator >
int LockFreeTreeValuePool<Type, Undefined, PoolAllocator, TreeAllocator>:: int LockFreeTreeValuePool<Type, Undefined, PoolAllocator, TreeAllocator>::
PoolIndexToNodeIndex(int index) { PoolIndexToNodeIndex(int index) {
int node = index + (size - 1); int node = index + (size_ - 1);
assert(IsLeaf(node)); assert(IsLeaf(node));
return node; return node;
} }
...@@ -100,7 +100,7 @@ template<typename T, T Undefined, class PoolAllocator, class TreeAllocator > ...@@ -100,7 +100,7 @@ template<typename T, T Undefined, class PoolAllocator, class TreeAllocator >
int LockFreeTreeValuePool<T, Undefined, PoolAllocator, TreeAllocator>:: int LockFreeTreeValuePool<T, Undefined, PoolAllocator, TreeAllocator>::
GetParentNode(int node) { GetParentNode(int node) {
int parent = (node - 1) / 2; int parent = (node - 1) / 2;
assert(parent >= 0 && parent < size - 1); assert(parent >= 0 && parent < size_ - 1);
return parent; return parent;
} }
...@@ -112,11 +112,11 @@ allocate_rec(int node, Type& element) { ...@@ -112,11 +112,11 @@ allocate_rec(int node, Type& element) {
if (IsLeaf(node)) { if (IsLeaf(node)) {
int pool_index = NodeIndexToPoolIndex(node); int pool_index = NodeIndexToPoolIndex(node);
Type expected = pool[pool_index]; Type expected = pool_[pool_index];
if (expected == Undefined) if (expected == Undefined)
return -1; return -1;
if (pool[pool_index].CompareAndSwap(expected, Undefined)) { if (pool_[pool_index].CompareAndSwap(expected, Undefined)) {
element = expected; element = expected;
return pool_index; return pool_index;
} }
...@@ -131,11 +131,11 @@ allocate_rec(int node, Type& element) { ...@@ -131,11 +131,11 @@ allocate_rec(int node, Type& element) {
// atomically decrement the value in the node if the result is greater than // atomically decrement the value in the node if the result is greater than
// or equal to zero. This cannot be done atomically. // or equal to zero. This cannot be done atomically.
do { do {
current = tree[node]; current = tree_[node];
desired = current - 1; desired = current - 1;
if (desired < 0) if (desired < 0)
return -1; return -1;
} while (!tree[node].CompareAndSwap(current, desired)); } while (!tree_[node].CompareAndSwap(current, desired));
int leftResult = allocate_rec(GetLeftChildIndex(node), element); int leftResult = allocate_rec(GetLeftChildIndex(node), element);
if (leftResult != -1) { if (leftResult != -1) {
...@@ -156,7 +156,7 @@ Fill(int node, int elementsToStore, int power2Value) { ...@@ -156,7 +156,7 @@ Fill(int node, int elementsToStore, int power2Value) {
if (IsLeaf(node)) if (IsLeaf(node))
return; return;
tree[node] = elementsToStore; tree_[node] = elementsToStore;
int postPower2Value = power2Value >> 1; int postPower2Value = power2Value >> 1;
...@@ -188,14 +188,14 @@ Free(Type element, int index) { ...@@ -188,14 +188,14 @@ Free(Type element, int index) {
assert(element != Undefined); assert(element != Undefined);
// Put the element back // Put the element back
pool[index].Store(element); pool_[index].Store(element);
assert(index >= 0 && index < size); assert(index >= 0 && index < size_);
int node = PoolIndexToNodeIndex(index); int node = PoolIndexToNodeIndex(index);
while (!IsRoot(node)) { while (!IsRoot(node)) {
node = GetParentNode(node); node = GetParentNode(node);
tree[node].FetchAndAdd(1); tree_[node].FetchAndAdd(1);
} }
} }
...@@ -205,67 +205,67 @@ template< typename ForwardIterator > ...@@ -205,67 +205,67 @@ template< typename ForwardIterator >
LockFreeTreeValuePool<Type, Undefined, PoolAllocator, TreeAllocator>:: LockFreeTreeValuePool<Type, Undefined, PoolAllocator, TreeAllocator>::
LockFreeTreeValuePool(ForwardIterator first, ForwardIterator last) { LockFreeTreeValuePool(ForwardIterator first, ForwardIterator last) {
// Number of elements to store // Number of elements to store
real_size = static_cast<int>(::std::distance(first, last)); real_size_ = static_cast<int>(::std::distance(first, last));
// Let k be smallest number so that real_size <= 2^k, size = 2^k // Let k be smallest number so that real_size <= 2^k, size = 2^k
size = GetSmallestPowerByTwoValue(real_size); size_ = GetSmallestPowerByTwoValue(real_size_);
// Size of binary tree without the leaves // Size of binary tree without the leaves
tree_size = size - 1; tree_size_ = size_ - 1;
// make sure, signed values are not negative // make sure, signed values are not negative
assert(tree_size >= 0); assert(tree_size_ >= 0);
assert(real_size >= 0); assert(real_size_ >= 0);
size_t tree_size_unsigned = static_cast<size_t>(tree_size); size_t tree_size_unsigned = static_cast<size_t>(tree_size_);
size_t real_size_unsigned = static_cast<size_t>(real_size); size_t real_size_unsigned = static_cast<size_t>(real_size_);
// Pool stores elements of type T // Pool stores elements of type T
pool = poolAllocator.allocate(real_size_unsigned); pool_ = pool_allocator_.allocate(real_size_unsigned);
// invoke inplace new for each pool element // invoke inplace new for each pool element
for (size_t i = 0; i != real_size_unsigned; ++i) { for (size_t i = 0; i != real_size_unsigned; ++i) {
new (&pool[i]) embb::base::Atomic<Type>(); new (&pool_[i]) embb::base::Atomic<Type>();
} }
// Tree holds the counter of not allocated elements // Tree holds the counter of not allocated elements
tree = treeAllocator.allocate(tree_size_unsigned); tree_ = tree_allocator_.allocate(tree_size_unsigned);
// invoke inplace new for each tree element // invoke inplace new for each tree element
for (size_t i = 0; i != tree_size_unsigned; ++i) { for (size_t i = 0; i != tree_size_unsigned; ++i) {
new (&tree[i]) embb::base::Atomic<int>(); new (&tree_[i]) embb::base::Atomic<int>();
} }
int i = 0; int i = 0;
// Store the elements from the range // Store the elements from the range
for (ForwardIterator curIter(first); curIter != last; ++curIter) { for (ForwardIterator curIter(first); curIter != last; ++curIter) {
pool[i++] = *curIter; pool_[i++] = *curIter;
} }
// Initialize the binary tree without leaves (counters) // Initialize the binary tree without leaves (counters)
Fill(0, static_cast<int>(::std::distance(first, last)), size); Fill(0, static_cast<int>(::std::distance(first, last)), size_);
} }
template<typename Type, Type Undefined, class PoolAllocator, template<typename Type, Type Undefined, class PoolAllocator,
class TreeAllocator > class TreeAllocator >
LockFreeTreeValuePool<Type, Undefined, PoolAllocator, TreeAllocator>:: LockFreeTreeValuePool<Type, Undefined, PoolAllocator, TreeAllocator>::
~LockFreeTreeValuePool() { ~LockFreeTreeValuePool() {
size_t tree_size_unsigned = static_cast<size_t>(tree_size); size_t tree_size_unsigned = static_cast<size_t>(tree_size_);
size_t real_size_unsigned = static_cast<size_t>(real_size); size_t real_size_unsigned = static_cast<size_t>(real_size_);
poolAllocator.deallocate(pool, real_size_unsigned); pool_allocator_.deallocate(pool_, real_size_unsigned);
// invoke destructor for each pool element // invoke destructor for each pool element
for (size_t i = 0; i != real_size_unsigned; ++i) { for (size_t i = 0; i != real_size_unsigned; ++i) {
pool[i].~Atomic(); pool_[i].~Atomic();
} }
treeAllocator.deallocate(tree, tree_size_unsigned); tree_allocator_.deallocate(tree_, tree_size_unsigned);
// invoke destructor for each tree element // invoke destructor for each tree element
for (size_t i = 0; i != tree_size_unsigned; ++i) { for (size_t i = 0; i != tree_size_unsigned; ++i) {
tree[i].~Atomic(); tree_[i].~Atomic();
} }
} }
......
...@@ -83,7 +83,8 @@ ReturningTrueIterator::operator!=(const self_type& rhs) { ...@@ -83,7 +83,8 @@ ReturningTrueIterator::operator!=(const self_type& rhs) {
template<class Type, typename ValuePool, class ObjectAllocator> template<class Type, typename ValuePool, class ObjectAllocator>
bool ObjectPool<Type, ValuePool, ObjectAllocator>:: bool ObjectPool<Type, ValuePool, ObjectAllocator>::
IsContained(const Type &obj) const { IsContained(const Type &obj) const {
if ((&obj < &objects[0]) || (&obj > &objects[capacity - 1])) { if ((&obj < &objects_array_[0]) ||
(&obj > &objects_array_[value_pool_size_ - 1])) {
return false; return false;
} else { } else {
return true; return true;
...@@ -94,17 +95,17 @@ template<class Type, typename ValuePool, class ObjectAllocator> ...@@ -94,17 +95,17 @@ template<class Type, typename ValuePool, class ObjectAllocator>
int ObjectPool<Type, ValuePool, ObjectAllocator>:: int ObjectPool<Type, ValuePool, ObjectAllocator>::
GetIndexOfObject(const Type &obj) const { GetIndexOfObject(const Type &obj) const {
assert(IsContained(obj)); assert(IsContained(obj));
return(static_cast<int>(&obj - &objects[0])); return(static_cast<int>(&obj - &objects_array_[0]));
} }
template<class Type, typename ValuePool, class ObjectAllocator> template<class Type, typename ValuePool, class ObjectAllocator>
Type* ObjectPool<Type, ValuePool, ObjectAllocator>::AllocateRaw() { Type* ObjectPool<Type, ValuePool, ObjectAllocator>::AllocateRaw() {
bool val; bool val;
int allocated_index = p.Allocate(val); int allocated_index = value_pool_.Allocate(val);
if (allocated_index == -1) { if (allocated_index == -1) {
return NULL; return NULL;
} else { } else {
Type* ret_pointer = &(objects[allocated_index]); Type* ret_pointer = &(objects_array_[allocated_index]);
return ret_pointer; return ret_pointer;
} }
...@@ -112,16 +113,17 @@ Type* ObjectPool<Type, ValuePool, ObjectAllocator>::AllocateRaw() { ...@@ -112,16 +113,17 @@ Type* ObjectPool<Type, ValuePool, ObjectAllocator>::AllocateRaw() {
template<class Type, typename ValuePool, class ObjectAllocator> template<class Type, typename ValuePool, class ObjectAllocator>
size_t ObjectPool<Type, ValuePool, ObjectAllocator>::GetCapacity() { size_t ObjectPool<Type, ValuePool, ObjectAllocator>::GetCapacity() {
return capacity; return capacity_;
} }
template<class Type, typename ValuePool, class ObjectAllocator> template<class Type, typename ValuePool, class ObjectAllocator>
ObjectPool<Type, ValuePool, ObjectAllocator>::ObjectPool(size_t capacity) : ObjectPool<Type, ValuePool, ObjectAllocator>::ObjectPool(size_t capacity) :
capacity(capacity), capacity_(capacity),
p(ReturningTrueIterator(0), ReturningTrueIterator( value_pool_size_(
ValuePool::GetMinimumElementCountForGuaranteedCapacity(capacity))) { ValuePool::GetMinimumElementCountForGuaranteedCapacity(capacity)),
// Allocate the objects (without construction, just get the memory) value_pool_(ReturningTrueIterator(0), ReturningTrueIterator(
objects = objectAllocator.allocate(capacity); value_pool_size_)),
objects_array_(object_allocator_.allocate(value_pool_size_)) {
} }
template<class Type, typename ValuePool, class ObjectAllocator> template<class Type, typename ValuePool, class ObjectAllocator>
...@@ -129,7 +131,7 @@ void ObjectPool<Type, ValuePool, ObjectAllocator>::Free(Type* obj) { ...@@ -129,7 +131,7 @@ void ObjectPool<Type, ValuePool, ObjectAllocator>::Free(Type* obj) {
int index = GetIndexOfObject(*obj); int index = GetIndexOfObject(*obj);
obj->~Type(); obj->~Type();
p.Free(true, index); value_pool_.Free(true, index);
} }
template<class Type, typename ValuePool, class ObjectAllocator> template<class Type, typename ValuePool, class ObjectAllocator>
...@@ -190,7 +192,7 @@ Type* ObjectPool<Type, ValuePool, ObjectAllocator>::Allocate( ...@@ -190,7 +192,7 @@ Type* ObjectPool<Type, ValuePool, ObjectAllocator>::Allocate(
template<class Type, typename ValuePool, class ObjectAllocator> template<class Type, typename ValuePool, class ObjectAllocator>
ObjectPool<Type, ValuePool, ObjectAllocator>::~ObjectPool() { ObjectPool<Type, ValuePool, ObjectAllocator>::~ObjectPool() {
// Deallocate the objects // Deallocate the objects
objectAllocator.deallocate(objects, capacity); object_allocator_.deallocate(objects_array_, value_pool_size_);
} }
} // namespace containers } // namespace containers
} // namespace embb } // namespace embb
......
...@@ -35,21 +35,21 @@ Free(Type element, int index) { ...@@ -35,21 +35,21 @@ Free(Type element, int index) {
assert(element != Undefined); assert(element != Undefined);
// Just put back the element // Just put back the element
pool[index].Store(element); pool_array_[index].Store(element);
} }
template<typename Type, Type Undefined, class Allocator > template<typename Type, Type Undefined, class Allocator >
int WaitFreeArrayValuePool<Type, Undefined, Allocator>:: int WaitFreeArrayValuePool<Type, Undefined, Allocator>::
Allocate(Type & element) { Allocate(Type & element) {
for (int i = 0; i != size; ++i) { for (int i = 0; i != size_; ++i) {
Type expected; Type expected;
// If the memory cell is not available, go ahead // If the memory cell is not available, go ahead
if (Undefined == (expected = pool[i].Load())) if (Undefined == (expected = pool_array_[i].Load()))
continue; continue;
// Try to get the memory cell // Try to get the memory cell
if (pool[i].CompareAndSwap(expected, Undefined)) { if (pool_array_[i].CompareAndSwap(expected, Undefined)) {
// When the CAS was successful, this element is ours // When the CAS was successful, this element is ours
element = expected; element = expected;
return i; return i;
...@@ -64,36 +64,36 @@ WaitFreeArrayValuePool<Type, Undefined, Allocator>:: ...@@ -64,36 +64,36 @@ WaitFreeArrayValuePool<Type, Undefined, Allocator>::
WaitFreeArrayValuePool(ForwardIterator first, ForwardIterator last) { WaitFreeArrayValuePool(ForwardIterator first, ForwardIterator last) {
size_t dist = static_cast<size_t>(std::distance(first, last)); size_t dist = static_cast<size_t>(std::distance(first, last));
size = static_cast<int>(dist); size_ = static_cast<int>(dist);
// conversion may result in negative number. check! // conversion may result in negative number. check!
assert(size >= 0); assert(size_ >= 0);
// Use the allocator to allocate an array of size dist // Use the allocator to allocate an array of size dist
pool = allocator.allocate(dist); pool_array_ = allocator_.allocate(dist);
// invoke inplace new for each pool element // invoke inplace new for each pool element
for ( size_t i = 0; i != dist; ++i ) { for ( size_t i = 0; i != dist; ++i ) {
new (&pool[i]) embb::base::Atomic<Type>(); new (&pool_array_[i]) embb::base::Atomic<Type>();
} }
int i = 0; int i = 0;
// Store the elements of the range // Store the elements of the range
for (ForwardIterator curIter(first); curIter != last; ++curIter) { for (ForwardIterator curIter(first); curIter != last; ++curIter) {
pool[i++] = *curIter; pool_array_[i++] = *curIter;
} }
} }
template<typename Type, Type Undefined, class Allocator > template<typename Type, Type Undefined, class Allocator >
WaitFreeArrayValuePool<Type, Undefined, Allocator>::~WaitFreeArrayValuePool() { WaitFreeArrayValuePool<Type, Undefined, Allocator>::~WaitFreeArrayValuePool() {
// invoke destructor for each pool element // invoke destructor for each pool element
for (int i = 0; i != size; ++i) { for (int i = 0; i != size_; ++i) {
pool[i].~Atomic(); pool_array_[i].~Atomic();
} }
// free memory // free memory
allocator.deallocate(pool, static_cast<size_t>(size)); allocator_.deallocate(pool_array_, static_cast<size_t>(size_));
} }
template<typename Type, Type Undefined, class Allocator > template<typename Type, Type Undefined, class Allocator >
......
...@@ -123,22 +123,25 @@ class LockFreeTreeValuePool { ...@@ -123,22 +123,25 @@ class LockFreeTreeValuePool {
LockFreeTreeValuePool& operator=(const LockFreeTreeValuePool&); LockFreeTreeValuePool& operator=(const LockFreeTreeValuePool&);
// See algorithm description above // See algorithm description above
int size; int size_;
// See algorithm description above // See algorithm description above
int tree_size; int tree_size_;
// See algorithm description above // See algorithm description above
int real_size; int real_size_;
// The tree above the pool // The tree above the pool
embb::base::Atomic<int>* tree; embb::base::Atomic<int>* tree_;
// The actual pool // The actual pool
embb::base::Atomic<Type>* pool; embb::base::Atomic<Type>* pool_;
PoolAllocator poolAllocator; // respective allocator
TreeAllocator treeAllocator; PoolAllocator pool_allocator_;
// respective allocator
TreeAllocator tree_allocator_;
/** /**
* Computes smallest power of two fitting the specified value * Computes smallest power of two fitting the specified value
......
...@@ -35,7 +35,6 @@ ...@@ -35,7 +35,6 @@
namespace embb { namespace embb {
namespace containers { namespace containers {
/** /**
* \defgroup CPP_CONTAINERS_POOLS Pools * \defgroup CPP_CONTAINERS_POOLS Pools
* Concurrent pools * Concurrent pools
...@@ -62,22 +61,29 @@ class ObjectPool { ...@@ -62,22 +61,29 @@ class ObjectPool {
/** /**
* Allocator used to allocate elements of the object pool * Allocator used to allocate elements of the object pool
*/ */
ObjectAllocator objectAllocator; ObjectAllocator object_allocator_;
/** /**
* Array holding the allocated object * Capacity of the object pool
*/ */
Type* objects; size_t capacity_;
/** /**
* Capacity of the object pool * The size of the underlying value pool. This is also the size of the object
* array in this class. It is assumed, that the valuepool manages indices in
* range [0;value_pool_size_-1].
*/ */
size_t capacity; size_t value_pool_size_;
/** /**
* Underlying value pool * Underlying value pool
*/ */
ValuePool p; ValuePool value_pool_;
/**
* Array holding the allocated object
*/
Type* objects_array_;
/** /**
* Helper providing a virtual iterator that just returns true in each * Helper providing a virtual iterator that just returns true in each
...@@ -108,7 +114,6 @@ class ObjectPool { ...@@ -108,7 +114,6 @@ class ObjectPool {
bool IsContained(const Type &obj) const; bool IsContained(const Type &obj) const;
int GetIndexOfObject(const Type &obj) const; int GetIndexOfObject(const Type &obj) const;
Type* AllocateRaw(); Type* AllocateRaw();
public: public:
/** /**
* Constructs an object pool with capacity \c capacity. * Constructs an object pool with capacity \c capacity.
......
...@@ -116,10 +116,10 @@ template<typename Type, ...@@ -116,10 +116,10 @@ template<typename Type,
class Allocator = embb::base::Allocator< embb::base::Atomic<Type> > > class Allocator = embb::base::Allocator< embb::base::Atomic<Type> > >
class WaitFreeArrayValuePool { class WaitFreeArrayValuePool {
private: private:
int size; int size_;
embb::base::Atomic<Type>* pool; embb::base::Atomic<Type>* pool_array_;
WaitFreeArrayValuePool(); WaitFreeArrayValuePool();
Allocator allocator; Allocator allocator_;
// Prevent copy-construction // Prevent copy-construction
WaitFreeArrayValuePool(const WaitFreeArrayValuePool&); WaitFreeArrayValuePool(const WaitFreeArrayValuePool&);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment