Commit 8b6b7369 by Marcus Winter

containers_cpp: revised template argument names

parent 8af3d2c0
......@@ -62,19 +62,19 @@ T LockFreeMPMCQueueNode<T>::GetElement() {
}
} // namespace internal
template< typename T, typename ValuePool >
void LockFreeMPMCQueue<T, ValuePool>::
DeletePointerCallback(internal::LockFreeMPMCQueueNode<T>* to_delete) {
template< typename Type, typename ValuePool >
void LockFreeMPMCQueue<Type, ValuePool>::
DeletePointerCallback(internal::LockFreeMPMCQueueNode<Type>* to_delete) {
objectPool.Free(to_delete);
}
template< typename T, typename ValuePool >
LockFreeMPMCQueue<T, ValuePool>::~LockFreeMPMCQueue() {
template< typename Type, typename ValuePool >
LockFreeMPMCQueue<Type, ValuePool>::~LockFreeMPMCQueue() {
// Nothing to do here, did not allocate anything.
}
template< typename T, typename ValuePool >
LockFreeMPMCQueue<T, ValuePool>::LockFreeMPMCQueue(size_t capacity) :
template< typename Type, typename ValuePool >
LockFreeMPMCQueue<Type, ValuePool>::LockFreeMPMCQueue(size_t capacity) :
capacity(capacity),
// Disable "this is used in base member initializer" warning.
// We explicitly want this.
......@@ -82,7 +82,8 @@ capacity(capacity),
#pragma warning(push)
#pragma warning(disable:4355)
#endif
delete_pointer_callback(*this, &LockFreeMPMCQueue<T>::DeletePointerCallback),
delete_pointer_callback(*this,
&LockFreeMPMCQueue<Type>::DeletePointerCallback),
#ifdef _MSC_VER
#pragma warning(pop)
#endif
......@@ -94,26 +95,26 @@ capacity(capacity),
embb::base::Thread::GetThreadsMaxCount() +
capacity + 1) {
// Allocate dummy node to reduce the number of special cases to consider.
internal::LockFreeMPMCQueueNode<T>* dummyNode = objectPool.Allocate();
internal::LockFreeMPMCQueueNode<Type>* dummyNode = objectPool.Allocate();
// Initially, head and tail point to the dummy node.
head = dummyNode;
tail = dummyNode;
}
template< typename T, typename ValuePool >
size_t LockFreeMPMCQueue<T, ValuePool>::GetCapacity() {
template< typename Type, typename ValuePool >
size_t LockFreeMPMCQueue<Type, ValuePool>::GetCapacity() {
return capacity;
}
template< typename T, typename ValuePool >
bool LockFreeMPMCQueue<T, ValuePool>::TryEnqueue(T const& element) {
template< typename Type, typename ValuePool >
bool LockFreeMPMCQueue<Type, ValuePool>::TryEnqueue(Type const& element) {
// Get node from the pool containing element to enqueue.
internal::LockFreeMPMCQueueNode<T>* node = objectPool.Allocate(element);
internal::LockFreeMPMCQueueNode<Type>* node = objectPool.Allocate(element);
// Queue full, cannot enqueue
if (node == NULL)
return false;
internal::LockFreeMPMCQueueNode<T>* my_tail;
internal::LockFreeMPMCQueueNode<Type>* my_tail;
for (;;) {
my_tail = tail;
......@@ -124,14 +125,14 @@ bool LockFreeMPMCQueue<T, ValuePool>::TryEnqueue(T const& element) {
continue; // Hazard pointer outdated, retry
}
internal::LockFreeMPMCQueueNode<T>* my_tail_next = my_tail->GetNext();
internal::LockFreeMPMCQueueNode<Type>* my_tail_next = my_tail->GetNext();
if (my_tail == tail) {
// If the next pointer of the tail node is null, the tail pointer
// points to the last object. We try to set the next pointer of the
// tail node to our new node.
if (my_tail_next == NULL) {
internal::LockFreeMPMCQueueNode<T>* expected = NULL;
internal::LockFreeMPMCQueueNode<Type>* expected = NULL;
// This fails if the next pointer of the "cached" tail is not null
// anymore, i.e., another thread added a node before we could complete.
if (my_tail->GetNext().CompareAndSwap(expected, node))
......@@ -151,13 +152,13 @@ bool LockFreeMPMCQueue<T, ValuePool>::TryEnqueue(T const& element) {
return true;
}
template< typename T, typename ValuePool >
bool LockFreeMPMCQueue<T, ValuePool>::TryDequeue(T & element) {
internal::LockFreeMPMCQueueNode<T>* my_head;
internal::LockFreeMPMCQueueNode<T>* my_tail;
internal::LockFreeMPMCQueueNode<T>* my_next;
internal::LockFreeMPMCQueueNode<T>* expected;
T data;
template< typename Type, typename ValuePool >
bool LockFreeMPMCQueue<Type, ValuePool>::TryDequeue(Type & element) {
internal::LockFreeMPMCQueueNode<Type>* my_head;
internal::LockFreeMPMCQueueNode<Type>* my_tail;
internal::LockFreeMPMCQueueNode<Type>* my_next;
internal::LockFreeMPMCQueueNode<Type>* expected;
Type data;
for (;;) {
my_head = head;
hazardPointer.GuardPointer(0, my_head);
......
......@@ -59,14 +59,14 @@ namespace internal {
}
} // namespace internal
template< typename T, typename ValuePool >
void LockFreeStack< T, ValuePool >::
DeletePointerCallback(internal::LockFreeStackNode<T>* to_delete) {
template< typename Type, typename ValuePool >
void LockFreeStack< Type, ValuePool >::
DeletePointerCallback(internal::LockFreeStackNode<Type>* to_delete) {
objectPool.Free(to_delete);
}
template< typename T, typename ValuePool >
LockFreeStack< T, ValuePool >::LockFreeStack(size_t capacity) :
template< typename Type, typename ValuePool >
LockFreeStack< Type, ValuePool >::LockFreeStack(size_t capacity) :
capacity(capacity),
// Disable "this is used in base member initializer" warning.
// We explicitly want this.
......@@ -75,7 +75,7 @@ capacity(capacity),
#pragma warning(disable:4355)
#endif
delete_pointer_callback(*this,
&LockFreeStack<T>::DeletePointerCallback),
&LockFreeStack<Type>::DeletePointerCallback),
#ifdef _MSC_VER
#pragma warning(pop)
#endif
......@@ -88,19 +88,19 @@ capacity(capacity),
capacity) {
}
template< typename T, typename ValuePool >
size_t LockFreeStack< T, ValuePool >::GetCapacity() {
template< typename Type, typename ValuePool >
size_t LockFreeStack< Type, ValuePool >::GetCapacity() {
return capacity;
}
template< typename T, typename ValuePool >
LockFreeStack< T, ValuePool >::~LockFreeStack() {
template< typename Type, typename ValuePool >
LockFreeStack< Type, ValuePool >::~LockFreeStack() {
// Nothing to do here, did not allocate anything.
}
template< typename T, typename ValuePool >
bool LockFreeStack< T, ValuePool >::TryPush(T const& element) {
internal::LockFreeStackNode<T>* newNode =
template< typename Type, typename ValuePool >
bool LockFreeStack< Type, ValuePool >::TryPush(Type const& element) {
internal::LockFreeStackNode<Type>* newNode =
objectPool.Allocate(element);
// Stack full, cannot push
......@@ -108,16 +108,16 @@ bool LockFreeStack< T, ValuePool >::TryPush(T const& element) {
return false;
for (;;) {
internal::LockFreeStackNode<T>* top_cached = top;
internal::LockFreeStackNode<Type>* top_cached = top;
newNode->SetNext(top_cached);
if (top.CompareAndSwap(top_cached, newNode))
return true;
}
}
template< typename T, typename ValuePool >
bool LockFreeStack< T, ValuePool >::TryPop(T & element) {
internal::LockFreeStackNode<T>* top_cached = top;
template< typename Type, typename ValuePool >
bool LockFreeStack< Type, ValuePool >::TryPop(Type & element) {
internal::LockFreeStackNode<Type>* top_cached = top;
for (;;) {
top_cached = top;
......@@ -146,7 +146,7 @@ bool LockFreeStack< T, ValuePool >::TryPop(T & element) {
}
}
T data = top_cached->GetElement();
Type data = top_cached->GetElement();
// We don't need to read from this reference anymore, unguard it
hazardPointer.GuardPointer(0, NULL);
......
......@@ -29,39 +29,44 @@
namespace embb {
namespace containers {
template<typename T, T Undefined, class PoolAllocator, class TreeAllocator >
int LockFreeTreeValuePool<T, Undefined, PoolAllocator, TreeAllocator>::
template<typename Type, Type Undefined, class PoolAllocator,
class TreeAllocator >
int LockFreeTreeValuePool<Type, Undefined, PoolAllocator, TreeAllocator>::
GetSmallestPowerByTwoValue(int value) {
int result = 1;
while (result < value) result <<= 1;
return result;
}
template<typename T, T Undefined, class PoolAllocator, class TreeAllocator >
bool LockFreeTreeValuePool<T, Undefined, PoolAllocator, TreeAllocator>::IsLeaf(
int node ) {
template<typename Type, Type Undefined, class PoolAllocator,
class TreeAllocator >
bool LockFreeTreeValuePool<Type, Undefined, PoolAllocator, TreeAllocator>::
IsLeaf(int node) {
if (node >= size - 1 && node <= 2 * size - 1) {
return true;
}
return false;
}
template<typename T, T Undefined, class PoolAllocator, class TreeAllocator >
bool LockFreeTreeValuePool<T, Undefined, PoolAllocator, TreeAllocator>::
template<typename Type, Type Undefined, class PoolAllocator,
class TreeAllocator >
bool LockFreeTreeValuePool<Type, Undefined, PoolAllocator, TreeAllocator>::
IsValid(int node) {
return (node >= 0 && node <= 2 * size - 1);
}
template<typename T, T Undefined, class PoolAllocator, class TreeAllocator >
int LockFreeTreeValuePool<T, Undefined, PoolAllocator, TreeAllocator>::
template<typename Type, Type Undefined, class PoolAllocator,
class TreeAllocator >
int LockFreeTreeValuePool<Type, Undefined, PoolAllocator, TreeAllocator>::
GetLeftChildIndex(int node) {
int index = 2 * node + 1;
assert(IsValid(index));
return index;
}
template<typename T, T Undefined, class PoolAllocator, class TreeAllocator >
int LockFreeTreeValuePool<T, Undefined, PoolAllocator, TreeAllocator>::
template<typename Type, Type Undefined, class PoolAllocator,
class TreeAllocator >
int LockFreeTreeValuePool<Type, Undefined, PoolAllocator, TreeAllocator>::
GetRightChildIndex(int node) {
int index = 2 * node + 2;
assert(IsValid(index));
......@@ -75,16 +80,18 @@ NodeIndexToPoolIndex(int node) {
return(node - (size - 1));
}
template<typename T, T Undefined, class PoolAllocator, class TreeAllocator >
int LockFreeTreeValuePool<T, Undefined, PoolAllocator, TreeAllocator>::
template<typename Type, Type Undefined, class PoolAllocator,
class TreeAllocator >
int LockFreeTreeValuePool<Type, Undefined, PoolAllocator, TreeAllocator>::
PoolIndexToNodeIndex(int index) {
int node = index + (size - 1);
assert(IsLeaf(node));
return node;
}
template<typename T, T Undefined, class PoolAllocator, class TreeAllocator >
bool LockFreeTreeValuePool<T, Undefined, PoolAllocator, TreeAllocator>::
template<typename Type, Type Undefined, class PoolAllocator,
class TreeAllocator >
bool LockFreeTreeValuePool<Type, Undefined, PoolAllocator, TreeAllocator>::
IsRoot(int node) {
return(0 == node);
}
......@@ -97,14 +104,15 @@ GetParentNode(int node) {
return parent;
}
template<typename T, T Undefined, class PoolAllocator, class TreeAllocator >
int LockFreeTreeValuePool<T, Undefined, PoolAllocator, TreeAllocator>::
allocate_rec(int node, T& element) {
template<typename Type, Type Undefined, class PoolAllocator,
class TreeAllocator >
int LockFreeTreeValuePool<Type, Undefined, PoolAllocator, TreeAllocator>::
allocate_rec(int node, Type& element) {
// If we are a leaf, we try to allocate a cell using CAS.
if (IsLeaf(node)) {
int pool_index = NodeIndexToPoolIndex(node);
T expected = pool[pool_index];
Type expected = pool[pool_index];
if (expected == Undefined)
return -1;
......@@ -120,7 +128,7 @@ allocate_rec(int node, T& element) {
int desired;
// Try to decrement node value.
// This is the point, where the algorithm becomes not wait-free. We have to
// atomically decrement the value in the node iff 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.
do {
current = tree[node];
......@@ -141,8 +149,9 @@ allocate_rec(int node, T& element) {
return rightResult;
}
template<typename T, T Undefined, class PoolAllocator, class TreeAllocator >
void LockFreeTreeValuePool<T, Undefined, PoolAllocator, TreeAllocator>::
template<typename Type, Type Undefined, class PoolAllocator,
class TreeAllocator >
void LockFreeTreeValuePool<Type, Undefined, PoolAllocator, TreeAllocator>::
Fill(int node, int elementsToStore, int power2Value) {
if (IsLeaf(node))
return;
......@@ -165,15 +174,17 @@ Fill(int node, int elementsToStore, int power2Value) {
}
}
template<typename T, T Undefined, class PoolAllocator, class TreeAllocator >
int LockFreeTreeValuePool<T, Undefined, PoolAllocator, TreeAllocator>::
Allocate(T & element) {
template<typename Type, Type Undefined, class PoolAllocator,
class TreeAllocator >
int LockFreeTreeValuePool<Type, Undefined, PoolAllocator, TreeAllocator>::
Allocate(Type & element) {
return allocate_rec(0, element);
}
template<typename T, T Undefined, class PoolAllocator, class TreeAllocator >
void LockFreeTreeValuePool<T, Undefined, PoolAllocator, TreeAllocator>::
Free(T element, int index) {
template<typename Type, Type Undefined, class PoolAllocator,
class TreeAllocator >
void LockFreeTreeValuePool<Type, Undefined, PoolAllocator, TreeAllocator>::
Free(Type element, int index) {
assert(element != Undefined);
// Put the element back
......@@ -188,9 +199,10 @@ Free(T element, int index) {
}
}
template< typename T, T Undefined, class PoolAllocator, class TreeAllocator >
template< typename Type, Type Undefined, class PoolAllocator,
class TreeAllocator >
template< typename ForwardIterator >
LockFreeTreeValuePool<T, Undefined, PoolAllocator, TreeAllocator>::
LockFreeTreeValuePool<Type, Undefined, PoolAllocator, TreeAllocator>::
LockFreeTreeValuePool(ForwardIterator first, ForwardIterator last) {
// Number of elements to store
real_size = static_cast<int>(::std::distance(first, last));
......@@ -218,12 +230,14 @@ LockFreeTreeValuePool(ForwardIterator first, ForwardIterator last) {
Fill(0, static_cast<int>(::std::distance(first, last)), size);
}
template<typename T, T Undefined, class PoolAllocator, class TreeAllocator >
LockFreeTreeValuePool<T, Undefined, PoolAllocator, TreeAllocator>::
template<typename Type, Type Undefined, class PoolAllocator,
class TreeAllocator >
LockFreeTreeValuePool<Type, Undefined, PoolAllocator, TreeAllocator>::
~LockFreeTreeValuePool() {
poolAllocator.deallocate(pool, static_cast<size_t>(real_size));
treeAllocator.deallocate(tree, static_cast<size_t>(tree_size));
}
} // namespace containers
} // namespace embb
......
......@@ -29,60 +29,60 @@
namespace embb {
namespace containers {
template<class T, typename ValuePool, class ObjectAllocator>
ObjectPool<T, ValuePool, ObjectAllocator>::
template<class Type, typename ValuePool, class ObjectAllocator>
ObjectPool<Type, ValuePool, ObjectAllocator>::
ReturningTrueIterator::ReturningTrueIterator(size_t count_value) :
count_value(count_value),
ret_value(true)
{}
template<class T, typename ValuePool, class ObjectAllocator>
typename ObjectPool<T, ValuePool, ObjectAllocator>::
template<class Type, typename ValuePool, class ObjectAllocator>
typename ObjectPool<Type, ValuePool, ObjectAllocator>::
ReturningTrueIterator::self_type
ObjectPool<T, ValuePool, ObjectAllocator>::
ObjectPool<Type, ValuePool, ObjectAllocator>::
ReturningTrueIterator::operator++() {
self_type i = *this;
count_value++;
return i;
}
template<class T, typename ValuePool, class ObjectAllocator>
typename ObjectPool<T, ValuePool, ObjectAllocator>::
ReturningTrueIterator::self_type ObjectPool<T, ValuePool, ObjectAllocator>::
template<class Type, typename ValuePool, class ObjectAllocator>
typename ObjectPool<Type, ValuePool, ObjectAllocator>::
ReturningTrueIterator::self_type ObjectPool<Type, ValuePool, ObjectAllocator>::
ReturningTrueIterator::operator++(int) {
count_value++;
return *this;
}
template<class T, typename ValuePool, class ObjectAllocator>
typename ObjectPool<T, ValuePool, ObjectAllocator>::
ReturningTrueIterator::reference ObjectPool<T, ValuePool, ObjectAllocator>::
template<class Type, typename ValuePool, class ObjectAllocator>
typename ObjectPool<Type, ValuePool, ObjectAllocator>::
ReturningTrueIterator::reference ObjectPool<Type, ValuePool, ObjectAllocator>::
ReturningTrueIterator::operator*() {
return ret_value;
}
template<class T, typename ValuePool, class ObjectAllocator>
typename ObjectPool<T, ValuePool, ObjectAllocator>::
ReturningTrueIterator::pointer ObjectPool<T, ValuePool, ObjectAllocator>::
template<class Type, typename ValuePool, class ObjectAllocator>
typename ObjectPool<Type, ValuePool, ObjectAllocator>::
ReturningTrueIterator::pointer ObjectPool<Type, ValuePool, ObjectAllocator>::
ReturningTrueIterator::operator->() {
return &ret_value;
}
template<class T, typename ValuePool, class ObjectAllocator>
bool ObjectPool<T, ValuePool, ObjectAllocator>::
template<class Type, typename ValuePool, class ObjectAllocator>
bool ObjectPool<Type, ValuePool, ObjectAllocator>::
ReturningTrueIterator::operator==(const self_type& rhs) {
return count_value == rhs.count_value;
}
template<class T, typename ValuePool, class ObjectAllocator>
bool ObjectPool<T, ValuePool, ObjectAllocator>::
template<class Type, typename ValuePool, class ObjectAllocator>
bool ObjectPool<Type, ValuePool, ObjectAllocator>::
ReturningTrueIterator::operator!=(const self_type& rhs) {
return count_value != rhs.count_value;
}
template<class T, typename ValuePool, class ObjectAllocator>
bool ObjectPool<T, ValuePool, ObjectAllocator>::
IsContained(const T &obj) const {
template<class Type, typename ValuePool, class ObjectAllocator>
bool ObjectPool<Type, ValuePool, ObjectAllocator>::
IsContained(const Type &obj) const {
if ((&obj < &objects[0]) || (&obj > &objects[capacity - 1])) {
return false;
} else {
......@@ -90,104 +90,104 @@ IsContained(const T &obj) const {
}
}
template<class T, typename ValuePool, class ObjectAllocator>
int ObjectPool<T, ValuePool, ObjectAllocator>::
GetIndexOfObject(const T &obj) const {
template<class Type, typename ValuePool, class ObjectAllocator>
int ObjectPool<Type, ValuePool, ObjectAllocator>::
GetIndexOfObject(const Type &obj) const {
assert(IsContained(obj));
return(static_cast<int>(&obj - &objects[0]));
}
template<class T, typename ValuePool, class ObjectAllocator>
T* ObjectPool<T, ValuePool, ObjectAllocator>::AllocateRaw() {
template<class Type, typename ValuePool, class ObjectAllocator>
Type* ObjectPool<Type, ValuePool, ObjectAllocator>::AllocateRaw() {
bool val;
int allocated_index = p.Allocate(val);
if (allocated_index == -1) {
return NULL;
} else {
T* ret_pointer = &(objects[allocated_index]);
Type* ret_pointer = &(objects[allocated_index]);
return ret_pointer;
}
}
template<class T, typename ValuePool, class ObjectAllocator>
size_t ObjectPool<T, ValuePool, ObjectAllocator>::GetCapacity() {
template<class Type, typename ValuePool, class ObjectAllocator>
size_t ObjectPool<Type, ValuePool, ObjectAllocator>::GetCapacity() {
return capacity;
}
template<class T, typename ValuePool, class ObjectAllocator>
ObjectPool<T, ValuePool, ObjectAllocator>::ObjectPool(size_t capacity) :
template<class Type, typename ValuePool, class ObjectAllocator>
ObjectPool<Type, ValuePool, ObjectAllocator>::ObjectPool(size_t capacity) :
capacity(capacity),
p(ReturningTrueIterator(0), ReturningTrueIterator(capacity)) {
// Allocate the objects (without construction, just get the memory)
objects = objectAllocator.allocate(capacity);
}
template<class T, typename ValuePool, class ObjectAllocator>
void ObjectPool<T, ValuePool, ObjectAllocator>::Free(T* obj) {
template<class Type, typename ValuePool, class ObjectAllocator>
void ObjectPool<Type, ValuePool, ObjectAllocator>::Free(Type* obj) {
int index = GetIndexOfObject(*obj);
obj->~T();
obj->~Type();
p.Free(true, index);
}
template<class T, typename ValuePool, class ObjectAllocator>
T* ObjectPool<T, ValuePool, ObjectAllocator>::Allocate() {
T* rawObject = AllocateRaw();
template<class Type, typename ValuePool, class ObjectAllocator>
Type* ObjectPool<Type, ValuePool, ObjectAllocator>::Allocate() {
Type* rawObject = AllocateRaw();
if (rawObject != NULL)
new (rawObject)T();
new (rawObject)Type();
return rawObject;
}
template<class T, typename ValuePool, class ObjectAllocator>
template<class Type, typename ValuePool, class ObjectAllocator>
template<typename Param1>
T* ObjectPool<T, ValuePool, ObjectAllocator>::Allocate(
Type* ObjectPool<Type, ValuePool, ObjectAllocator>::Allocate(
Param1 const& param1) {
T* rawObject = AllocateRaw();
Type* rawObject = AllocateRaw();
if (rawObject != NULL)
new (rawObject)T(param1);
new (rawObject)Type(param1);
return rawObject;
}
template<class T, typename ValuePool, class ObjectAllocator>
template<class Type, typename ValuePool, class ObjectAllocator>
template<typename Param1, typename Param2>
T* ObjectPool<T, ValuePool, ObjectAllocator>::Allocate(
Type* ObjectPool<Type, ValuePool, ObjectAllocator>::Allocate(
Param1 const& param1, Param2 const& param2) {
T* rawObject = AllocateRaw();
Type* rawObject = AllocateRaw();
if (rawObject != NULL)
new (rawObject)T(param1, param2);
new (rawObject)Type(param1, param2);
return rawObject;
}
template<class T, typename ValuePool, class ObjectAllocator>
template<class Type, typename ValuePool, class ObjectAllocator>
template<typename Param1, typename Param2, typename Param3>
T* ObjectPool<T, ValuePool, ObjectAllocator>::Allocate(
Type* ObjectPool<Type, ValuePool, ObjectAllocator>::Allocate(
Param1 const& param1, Param2 const& param2,
Param3 const& param3) {
T* rawObject = AllocateRaw();
Type* rawObject = AllocateRaw();
if (rawObject != NULL)
new (rawObject)T(param1, param2, param3);
new (rawObject)Type(param1, param2, param3);
return rawObject;
}
template<class T, typename ValuePool, class ObjectAllocator>
template<class Type, typename ValuePool, class ObjectAllocator>
template<typename Param1, typename Param2, typename Param3, typename Param4>
T* ObjectPool<T, ValuePool, ObjectAllocator>::Allocate(
Type* ObjectPool<Type, ValuePool, ObjectAllocator>::Allocate(
Param1 const& param1, Param2 const& param2,
Param3 const& param3, Param4 const& param4) {
T* rawObject = AllocateRaw();
Type* rawObject = AllocateRaw();
if (rawObject != NULL)
new (rawObject)T(param1, param2, param3, param4);
new (rawObject)Type(param1, param2, param3, param4);
return rawObject;
}
template<class T, typename ValuePool, class ObjectAllocator>
ObjectPool<T, ValuePool, ObjectAllocator>::~ObjectPool() {
template<class Type, typename ValuePool, class ObjectAllocator>
ObjectPool<Type, ValuePool, ObjectAllocator>::~ObjectPool() {
// Deallocate the objects
objectAllocator.deallocate(objects, capacity);
}
......
......@@ -29,20 +29,20 @@
namespace embb {
namespace containers {
template<typename T, T Undefined, class Allocator >
void WaitFreeArrayValuePool<T, Undefined, Allocator>::
Free(T element, int index) {
template<typename Type, Type Undefined, class Allocator >
void WaitFreeArrayValuePool<Type, Undefined, Allocator>::
Free(Type element, int index) {
assert(element != Undefined);
// Just put back the element
pool[index].Store(element);
}
template<typename T, T Undefined, class Allocator >
int WaitFreeArrayValuePool<T, Undefined, Allocator>::
Allocate(T & element) {
template<typename Type, Type Undefined, class Allocator >
int WaitFreeArrayValuePool<Type, Undefined, Allocator>::
Allocate(Type & element) {
for (int i = 0; i != size; ++i) {
T expected;
Type expected;
// If the memory cell is not available, go ahead
if (Undefined == (expected = pool[i].Load()))
......@@ -58,9 +58,9 @@ Allocate(T & element) {
return -1;
}
template<typename T, T Undefined, class Allocator >
template<typename Type, Type Undefined, class Allocator >
template<typename ForwardIterator>
WaitFreeArrayValuePool<T, Undefined, Allocator>::
WaitFreeArrayValuePool<Type, Undefined, Allocator>::
WaitFreeArrayValuePool(ForwardIterator first, ForwardIterator last) {
size_t dist = static_cast<size_t>(std::distance(first, last));
......@@ -77,8 +77,8 @@ WaitFreeArrayValuePool(ForwardIterator first, ForwardIterator last) {
}
}
template<typename T, T Undefined, class Allocator >
WaitFreeArrayValuePool<T, Undefined, Allocator>::~WaitFreeArrayValuePool() {
template<typename Type, Type Undefined, class Allocator >
WaitFreeArrayValuePool<Type, Undefined, Allocator>::~WaitFreeArrayValuePool() {
allocator.deallocate(pool, (size_t)size);
}
} // namespace containers
......
......@@ -36,21 +36,21 @@
namespace embb {
namespace containers {
template<typename T, class Allocator>
WaitFreeSPSCQueue<T, Allocator>::WaitFreeSPSCQueue(size_t capacity) :
template<typename Type, class Allocator>
WaitFreeSPSCQueue<Type, Allocator>::WaitFreeSPSCQueue(size_t capacity) :
capacity(capacity),
head_index(0),
tail_index(0) {
queue_array = allocator.allocate(capacity);
}
template<typename T, class Allocator>
size_t WaitFreeSPSCQueue<T, Allocator>::GetCapacity() {
template<typename Type, class Allocator>
size_t WaitFreeSPSCQueue<Type, Allocator>::GetCapacity() {
return capacity;
}
template<typename T, class Allocator>
bool WaitFreeSPSCQueue<T, Allocator>::TryEnqueue(T const & element) {
template<typename Type, class Allocator>
bool WaitFreeSPSCQueue<Type, Allocator>::TryEnqueue(Type const & element) {
if (head_index - tail_index == capacity)
return false;
......@@ -59,19 +59,19 @@ bool WaitFreeSPSCQueue<T, Allocator>::TryEnqueue(T const & element) {
return true;
}
template<typename T, class Allocator>
bool WaitFreeSPSCQueue<T, Allocator>::TryDequeue(T & element) {
template<typename Type, class Allocator>
bool WaitFreeSPSCQueue<Type, Allocator>::TryDequeue(Type & element) {
if (tail_index - head_index == 0)
return false;
T x = queue_array[head_index % capacity];
Type x = queue_array[head_index % capacity];
this->head_index++;
element = x;
return true;
}
template<typename T, class Allocator>
WaitFreeSPSCQueue<T, Allocator>::~WaitFreeSPSCQueue() {
template<typename Type, class Allocator>
WaitFreeSPSCQueue<Type, Allocator>::~WaitFreeSPSCQueue() {
allocator.deallocate(queue_array, capacity);
}
} // namespace containers
......
......@@ -46,20 +46,20 @@ namespace internal {
* Single linked lists, contains the element (\c element) and a pointer to the
* next node (\c next).
*
* \tparam T Element type
* \tparam Type Element type
*/
template< typename T >
template< typename Type >
class LockFreeMPMCQueueNode {
private:
/**
* Pointer to the next node
*/
embb::base::Atomic< LockFreeMPMCQueueNode< T >* > next;
embb::base::Atomic< LockFreeMPMCQueueNode< Type >* > next;
/**
* The stored element
*/
T element;
Type element;
public:
/**
......@@ -73,7 +73,7 @@ class LockFreeMPMCQueueNode {
* Creates a queue node
*/
LockFreeMPMCQueueNode(
T const& element
Type const& element
/**< [IN] The element of this queue node */);
/**
......@@ -81,12 +81,12 @@ class LockFreeMPMCQueueNode {
*
* \return The next pointer
*/
embb::base::Atomic< LockFreeMPMCQueueNode< T >* > & GetNext();
embb::base::Atomic< LockFreeMPMCQueueNode< Type >* > & GetNext();
/**
* Returns the element held by this node
*/
T GetElement();
Type GetElement();
};
} // namespace internal
......@@ -99,11 +99,11 @@ class LockFreeMPMCQueueNode {
*
* \see WaitFreeSPSCQueue
*
* \tparam T Type of the queue elements
* \tparam Type Type of the queue elements
* \tparam ValuePool Type of the value pool used as basis for the ObjectPool
* which stores the elements.
*/
template< typename T,
template< typename Type,
typename ValuePool = embb::containers::LockFreeTreeValuePool < bool, false >
>
class LockFreeMPMCQueue {
......@@ -120,35 +120,35 @@ class LockFreeMPMCQueue {
* Callback to the method that is called by hazard pointers if a pointer is
* not hazardous anymore, i.e., can safely be reused.
*/
embb::base::Function < void, internal::LockFreeMPMCQueueNode<T>* >
embb::base::Function < void, internal::LockFreeMPMCQueueNode<Type>* >
delete_pointer_callback;
/**
* The hazard pointer object, used for memory management.
*/
embb::containers::internal::HazardPointer
< internal::LockFreeMPMCQueueNode<T>* > hazardPointer;
< internal::LockFreeMPMCQueueNode<Type>* > hazardPointer;
/**
* The object pool, used for lock-free memory allocation.
*/
ObjectPool< internal::LockFreeMPMCQueueNode<T>, ValuePool > objectPool;
ObjectPool< internal::LockFreeMPMCQueueNode<Type>, ValuePool > objectPool;
/**
* Atomic pointer to the head node of the queue
*/
embb::base::Atomic< internal::LockFreeMPMCQueueNode<T>* > head;
embb::base::Atomic< internal::LockFreeMPMCQueueNode<Type>* > head;
/**
* Atomic pointer to the tail node of the queue
*/
embb::base::Atomic< internal::LockFreeMPMCQueueNode<T>* > tail;
embb::base::Atomic< internal::LockFreeMPMCQueueNode<Type>* > tail;
/**
* The callback function, used to cleanup non-hazardous pointers.
* \see delete_pointer_callback
*/
void DeletePointerCallback(internal::LockFreeMPMCQueueNode<T>* to_delete);
void DeletePointerCallback(internal::LockFreeMPMCQueueNode<Type>* to_delete);
public:
/**
......@@ -157,8 +157,8 @@ class LockFreeMPMCQueue {
* \memory
* Let \c t be the maximum number of threads and \c x be <tt>2.5*t+1</tt>.
* Then, <tt>x*(3*t+1)</tt> elements of size <tt>sizeof(void*)</tt>, \c x
* elements of size <tt>sizeof(T)</tt>, and \c capacity+1 elements of size
* <tt>sizeof(T)</tt> are allocated.
* elements of size <tt>sizeof(Type)</tt>, and \c capacity+1 elements of size
* <tt>sizeof(Type)</tt> are allocated.
*
* \notthreadsafe
*
......@@ -198,7 +198,7 @@ class LockFreeMPMCQueue {
* \see CPP_CONCEPTS_QUEUE
*/
bool TryEnqueue(
T const& element
Type const& element
/**< [IN] Const reference to the element that shall be enqueued */);
/**
......@@ -212,7 +212,7 @@ class LockFreeMPMCQueue {
* \see CPP_CONCEPTS_QUEUE
*/
bool TryDequeue(
T & element
Type & element
/**< [IN, OUT] Reference to the dequeued element.
Unchanged, if the operation
was not successful. */);
......
......@@ -53,9 +53,9 @@
*
* \par Requirements
* - Let \c Stack be the stack class
* - Let \c T be the element type of the stack
* - Let \c Type be the element type of the stack
* - Let \c capacity be a value of type \c size_t
* - Let \c element be a reference to an element of type \c T
* - Let \c element be a reference to an element of type \c Type
*
* \par Valid Expressions
* <table>
......@@ -65,11 +65,11 @@
* <th>Description</th>
* </tr>
* <tr>
* <td>\code{.cpp} Stack<T>(capacity) \endcode</td>
* <td>\code{.cpp} Stack<Type>(capacity) \endcode</td>
* <td>Nothing</td>
* <td>
* Constructs a stack with capacity \c capacity that holds elements of
* type \c T.
* type \c Type.
* </td>
* </tr>
* <tr>
......@@ -165,11 +165,11 @@ class LockFreeStackNode {
*
* \ingroup CPP_CONTAINERS_STACKS
*
* \tparam T Type of the stack elements
* \tparam Type Type of the stack elements
* \tparam ValuePool Type of the value pool used as basis for the ObjectPool
* which stores the elements.
*/
template< typename T,
template< typename Type,
typename ValuePool = embb::containers::LockFreeTreeValuePool < bool, false > >
class LockFreeStack {
private:
......@@ -183,29 +183,29 @@ class LockFreeStack {
* Callback to the method that is called by hazard pointers if a pointer is
* not hazardous anymore, i.e., can safely be reused.
*/
embb::base::Function<void, internal::LockFreeStackNode<T>*>
embb::base::Function<void, internal::LockFreeStackNode<Type>*>
delete_pointer_callback;
/**
* The hazard pointer object, used for memory management.
*/
internal::HazardPointer<internal::LockFreeStackNode<T>*> hazardPointer;
internal::HazardPointer<internal::LockFreeStackNode<Type>*> hazardPointer;
/**
* The callback function, used to cleanup non-hazardous pointers.
* \see delete_pointer_callback
*/
void DeletePointerCallback(internal::LockFreeStackNode<T>* to_delete);
void DeletePointerCallback(internal::LockFreeStackNode<Type>* to_delete);
/**
* The object pool, used for lock-free memory allocation.
*/
ObjectPool< internal::LockFreeStackNode<T>, ValuePool > objectPool;
ObjectPool< internal::LockFreeStackNode<Type>, ValuePool > objectPool;
/**
* Atomic pointer to the top node of the stack (element that is popped next)
*/
embb::base::Atomic<internal::LockFreeStackNode<T>*> top;
embb::base::Atomic<internal::LockFreeStackNode<Type>*> top;
public:
/**
......@@ -214,8 +214,8 @@ class LockFreeStack {
* \memory
* Let \c t be the maximum number of threads and \c x be <tt>1.25*t+1</tt>.
* Then, <tt>x*(3*t+1)</tt> elements of size <tt>sizeof(void*)</tt>, \c x
* elements of size <tt>sizeof(T)</tt>, and \c capacity elements of size
* <tt>sizeof(T)</tt> are allocated.
* elements of size <tt>sizeof(Type)</tt>, and \c capacity elements of size
* <tt>sizeof(Type)</tt> are allocated.
*
* \notthreadsafe
*
......@@ -256,7 +256,7 @@ class LockFreeStack {
* \see CPP_CONCEPTS_STACK
*/
bool TryPush(
T const& element
Type const& element
/**< [IN] Const reference to the element that shall be pushed */
);
......@@ -271,7 +271,7 @@ class LockFreeStack {
* \see CPP_CONCEPTS_STACK
*/
bool TryPop(
T & element
Type & element
/**< [IN,OUT] Reference to the popped element. Unchanged, if the operation
was not successful. */
);
......
......@@ -41,15 +41,15 @@ namespace containers {
*
* \see WaitFreeArrayValuePool
*
* \tparam T Element type (must support atomic operations such as \c int).
* \tparam Type Element type (must support atomic operations such as \c int).
* \tparam Undefined Bottom element (cannot be stored in the pool)
* \tparam PoolAllocator Allocator used to allocate the pool array
* \tparam TreeAllocator Allocator used to allocate the array representing the
* binary tree.
*/
template<typename T,
T Undefined,
class PoolAllocator = embb::base::Allocator< embb::base::Atomic<T> >,
template<typename Type,
Type Undefined,
class PoolAllocator = embb::base::Allocator< embb::base::Atomic<Type> >,
class TreeAllocator = embb::base::Allocator < embb::base::Atomic<int> >
>
class LockFreeTreeValuePool {
......@@ -95,7 +95,7 @@ class LockFreeTreeValuePool {
*
* The algorithm for allocating an element starts at the root node and
* recursively traverses the tree. It tries to decrement a node (a decrement
* is actually a conditional decrement, i.e., a node is decremented iff the
* is actually a conditional decrement, i.e., a node is decremented if the
* result is not less than 0. This is the place, where the algorithm is not
* wait-free anymore, as this cannot be implemented atomically.) and if
* successful, calls itself on the left child, if not successful, on the right
......@@ -135,7 +135,7 @@ class LockFreeTreeValuePool {
embb::base::Atomic<int>* tree;
// The actual pool
embb::base::Atomic<T>* pool;
embb::base::Atomic<Type>* pool;
PoolAllocator poolAllocator;
TreeAllocator treeAllocator;
......@@ -235,7 +235,7 @@ class LockFreeTreeValuePool {
int allocate_rec(
int node,
/**< [IN] Node index */
T& element
Type& element
/**< [IN,OUT] Allocated element, if there is any */
);
......@@ -260,8 +260,8 @@ class LockFreeTreeValuePool {
*
* \memory Let <tt>n = \c std::distance(first, last))</tt> and \c k be the
* minimum number such that <tt>n <= 2^k holds</tt>. Then,
* <tt>((2^k)-1) * sizeof(embb::Atomic<int>) + n*sizeof(embb::Atomic<T>)</tt>
* bytes of memory are allocated.
* <tt>((2^k)-1) * sizeof(embb::Atomic<int>) +
* n*sizeof(embb::Atomic<Type>)</tt> bytes of memory are allocated.
*
* \notthreadsafe
*
......@@ -294,7 +294,7 @@ class LockFreeTreeValuePool {
* \see CPP_CONCEPTS_VALUE_POOL
*/
int Allocate(
T & element
Type & element
/**< [IN,OUT] Reference to the allocated element. Unchanged, if the
operation was not successful. */
);
......@@ -309,7 +309,7 @@ class LockFreeTreeValuePool {
* \see CPP_CONCEPTS_VALUE_POOL
*/
void Free(
T element,
Type element,
/**< [IN] Element to be returned to the pool */
int index
/**< [IN] Index of the element as obtained by Allocate() */
......
......@@ -48,15 +48,15 @@ namespace containers {
*
* \ingroup CPP_CONTAINERS_POOLS
*
* \tparam T Element type
* \tparam Type Element type
* \tparam ValuePool Type of the underlying value pool, determines whether
* the object pool is wait-free or lock-free
* \tparam ObjectAllocator Type of allocator used to allocate objects
*/
template<class T,
template<class Type,
typename ValuePool =
embb::containers::WaitFreeArrayValuePool< bool, false >,
class ObjectAllocator = embb::base::Allocator<T> >
class ObjectAllocator = embb::base::Allocator<Type> >
class ObjectPool {
private:
/**
......@@ -67,7 +67,7 @@ class ObjectPool {
/**
* Array holding the allocated object
*/
T* objects;
Type* objects;
/**
* Capacity of the object pool
......@@ -105,15 +105,15 @@ class ObjectPool {
bool ret_value;
};
bool IsContained(const T &obj) const;
int GetIndexOfObject(const T &obj) const;
T* AllocateRaw();
bool IsContained(const Type &obj) const;
int GetIndexOfObject(const Type &obj) const;
Type* AllocateRaw();
public:
/**
* Constructs an object pool with capacity \c capacity.
*
* \memory Allocates \c capacity elements of type \c T.
* \memory Allocates \c capacity elements of type \c Type.
*
* \notthreadsafe
*/
......@@ -147,7 +147,7 @@ class ObjectPool {
* \note The element must have been allocated with Allocate().
*/
void Free(
T* obj
Type* obj
/**< [IN] Pointer to the object to be freed */
);
......@@ -162,22 +162,22 @@ class ObjectPool {
*
* \param ... Arguments of arbitrary type, passed to the object's constructor
*/
T* Allocate(...);
Type* Allocate(...);
#else
T* Allocate();
Type* Allocate();
template<typename Param1>
T* Allocate(Param1 const& param1);
Type* Allocate(Param1 const& param1);
template<typename Param1, typename Param2>
T* Allocate(Param1 const& param1, Param2 const& param2);
Type* Allocate(Param1 const& param1, Param2 const& param2);
template<typename Param1, typename Param2, typename Param3>
T* Allocate(Param1 const& param1, Param2 const& param2,
Type* Allocate(Param1 const& param1, Param2 const& param2,
Param3 const& param3);
template<typename Param1, typename Param2, typename Param3, typename Param4>
T* Allocate(Param1 const& param1, Param2 const& param2,
Type* Allocate(Param1 const& param1, Param2 const& param2,
Param3 const& param3, Param4 const& param4);
#endif
......
......@@ -48,11 +48,11 @@ namespace containers {
*
* \par Requirements
* - Let \c Pool be the pool class
* - Let \c T be the element type of the pool. Atomic operations must be
* possible on \c T.
* - Let \c b, d be objects of type \c T
* - Let \c Type be the element type of the pool. Atomic operations must be
* possible on \c Type.
* - Let \c b, d be objects of type \c Type
* - Let \c i, j be forward iterators supporting \c std::distance.
* - Let \c c be an object of type \c T&
* - Let \c c be an object of type \c Type&
* - Let \c e be a value of type \c int
*
* \par Valid Expressions
......@@ -64,13 +64,13 @@ namespace containers {
* <th>Description</th>
* </tr>
* <tr>
* <td>\code{.cpp} Pool<T, b>(i, j) \endcode
* <td>\code{.cpp} Pool<Type, b>(i, j) \endcode
* </td>
* <td>Nothing</td>
* <td>
* Constructs a value pool holding elements of type \c T, where \c b is the
* bottom element. The bottom element cannot be stored in the pool, it is
* exclusively used to mark empty cells. The pool initially contains
* Constructs a value pool holding elements of type \c Type, where \c b is
* the bottom element. The bottom element cannot be stored in the pool, it
* is exclusively used to mark empty cells. The pool initially contains
* \c std::distance(i, j) elements which are copied during construction from
* the range \c [i, j). A concrete class satisfying the value pool concept
* might provide additional template parameters for specifying allocators.
......@@ -107,17 +107,17 @@ namespace containers {
*
* \see LockFreeTreeValuePool
*
* \tparam T Element type (must support atomic operations such as \c int).
* \tparam Type Element type (must support atomic operations such as \c int).
* \tparam Undefined Bottom element (cannot be stored in the pool)
* \tparam Allocator Allocator used to allocate the pool array
*/
template<typename T,
T Undefined,
class Allocator = embb::base::Allocator< embb::base::Atomic<T> > >
template<typename Type,
Type Undefined,
class Allocator = embb::base::Allocator< embb::base::Atomic<Type> > >
class WaitFreeArrayValuePool {
private:
int size;
embb::base::Atomic<T>* pool;
embb::base::Atomic<Type>* pool;
WaitFreeArrayValuePool();
Allocator allocator;
......@@ -131,7 +131,7 @@ class WaitFreeArrayValuePool {
/**
* Constructs a pool and fills it with the elements in the specified range.
*
* \memory Dynamically allocates <tt>n*sizeof(embb::base::Atomic<T>)</tt>
* \memory Dynamically allocates <tt>n*sizeof(embb::base::Atomic<Type>)</tt>
* bytes, where <tt>n = std::distance(first, last)</tt> is the number
* of pool elements.
*
......@@ -166,7 +166,7 @@ class WaitFreeArrayValuePool {
* \see CPP_CONCEPTS_VALUE_POOL
*/
int Allocate(
T & element
Type & element
/**< [IN,OUT] Reference to the allocated element. Unchanged, if the
operation was not successful. */
);
......@@ -181,7 +181,7 @@ class WaitFreeArrayValuePool {
* \see CPP_CONCEPTS_VALUE_POOL
*/
void Free(
T element,
Type element,
/**< [IN] Element to be returned to the pool */
int index
/**< [IN] Index of the element as obtained by Allocate() */
......
......@@ -53,9 +53,9 @@
*
* \par Requirements
* - Let \c Queue be the queue class
* - Let \c T be the element type of the queue
* - Let \c Type be the element type of the queue
* - Let \c capacity be a value of type \c size_t
* - Let \c element be a reference to an element of type \c T
* - Let \c element be a reference to an element of type \c Type
*
* \par Valid Expressions
* <table>
......@@ -65,7 +65,7 @@
* <th>Description</th>
* </tr>
* <tr>
* <td>\code{.cpp} Queue<T>(capacity) \endcode</td>
* <td>\code{.cpp} Queue<Type>(capacity) \endcode</td>
* <td>Nothing</td>
* <td>
* Constructs a queue with capacity \c capacity that holds elements of
......@@ -114,10 +114,10 @@ namespace containers {
*
* \see LockFreeMPMCQueue
*
* \tparam T Type of the queue elements
* \tparam Type Type of the queue elements
* \tparam Allocator Allocator type for allocating queue elements.
*/
template<typename T, class Allocator = embb::base::Allocator< T > >
template<typename Type, class Allocator = embb::base::Allocator< Type > >
class WaitFreeSPSCQueue {
private:
/**
......@@ -133,7 +133,7 @@ class WaitFreeSPSCQueue {
/**
* Array holding the queue elements
*/
T* queue_array;
Type* queue_array;
/**
* Index of the head in the \c queue_array
......@@ -149,7 +149,7 @@ class WaitFreeSPSCQueue {
/**
* Creates a queue with the specified capacity.
*
* \memory Allocates \c capacity elements of type \c T.
* \memory Allocates \c capacity elements of type \c Type.
*
* \notthreadsafe
*
......@@ -190,7 +190,7 @@ class WaitFreeSPSCQueue {
* \see CPP_CONCEPTS_QUEUE
*/
bool TryEnqueue(
T const & element
Type const & element
/**< [IN] Const reference to the element that shall be enqueued */
);
......@@ -208,9 +208,9 @@ class WaitFreeSPSCQueue {
* \see CPP_CONCEPTS_QUEUE
*/
bool TryDequeue(
T & element
/**< [IN,OUT] Reference to the dequeued element. Unchanged, if the operation
was not successful. */
Type & element
/**< [IN,OUT] Reference to the dequeued element. Unchanged, if the
operation was not successful. */
);
};
} // namespace containers
......
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