Commit a21f0ac6 authored by neverlord's avatar neverlord

benchmarking

parent 1c1b11a6
#ifndef INTRUSIVE_SUTTER_LIST_HPP
#define INTRUSIVE_SUTTER_LIST_HPP
#include <atomic>
#include <boost/thread.hpp>
#include "defines.hpp"
// This implementation is a single-consumer version
// of an example implementation of Herb Sutter:
// http://drdobbs.com/cpp/211601363.
// T is any type
template<typename T>
class intrusive_sutter_list
{
public:
struct node
{
node(T val = T()) : value(val), next(0) { }
T value;
std::atomic<node*> next;
char pad[CACHE_LINE_SIZE - sizeof(T)- sizeof(std::atomic<node*>)];
};
private:
// one consumer at a time
node* m_first;
char m_pad1[CACHE_LINE_SIZE - sizeof(node*)];
// for one producers at a time
node* m_last;
char m_pad2[CACHE_LINE_SIZE - sizeof(node*)];
// shared among producers
std::atomic<bool> m_producer_lock;
public:
intrusive_sutter_list()
{
m_first = m_last = new node;
m_producer_lock = false;
}
~intrusive_sutter_list()
{
while (m_first)
{
node* tmp = m_first;
m_first = tmp->next;
delete tmp;
}
}
// takes ownership of what
void push(node* tmp)
{
// acquire exclusivity
while (m_producer_lock.exchange(true))
{
boost::this_thread::yield();
}
// publish & swing last forward
m_last->next = tmp;
m_last = tmp;
// release exclusivity
m_producer_lock = false;
}
// returns nullptr on failure
bool try_pop(T& result)
{
// no critical section; only one consumer allowed
node* first = m_first;
node* next = m_first->next;
if (next)
{
// queue is not empty
result = next->value; // take it out of the node
// swing first forward
m_first = next;
// delete old dummy
delete first;
// done
return true;
}
return false;
}
// polls the queue until an element was dequeued
T pop()
{
T result;
while (!try_pop(result))
{
boost::this_thread::yield();
}
return result;
}
};
#endif // INTRUSIVE_SUTTER_LIST_HPP
#ifndef LOCKFREE_LIST_HPP
#define LOCKFREE_LIST_HPP
#include <atomic>
#include <boost/thread.hpp>
#include "defines.hpp"
// This implementation is a single-consumer version
// of an example implementation of Herb Sutter:
// http://drdobbs.com/cpp/211601363.
// T is any type
template<typename T>
class lockfree_list
{
public:
struct node
{
node(T val = T()) : value(val), next(0) { }
T value;
std::atomic<node*> next;
char pad[CACHE_LINE_SIZE - sizeof(T)- sizeof(std::atomic<node*>)];
};
private:
// one consumer at a time
node* m_first;
char m_pad1[CACHE_LINE_SIZE - sizeof(node*)];
// shared among producers
std::atomic<node*> m_last;
public:
lockfree_list()
{
m_first = m_last = new node;
}
~lockfree_list()
{
while (m_first)
{
node* tmp = m_first;
m_first = tmp->next;
delete tmp;
}
}
// takes ownership of what
void push(node* tmp)
{
// m_last becomes our predecessor
node* predecessor = m_last.load();
// swing last forward
while (!m_last.compare_exchange_weak(predecessor, tmp)) { }
// link pieces together
predecessor->next = tmp;
}
// returns nullptr on failure
bool try_pop(T& result)
{
// no critical section; only one consumer allowed
node* first = m_first;
node* next = m_first->next;
if (next)
{
// queue is not empty
result = next->value; // take it out
next->value = 0; // of the node
// swing first forward
m_first = next;
// delete old dummy
delete first;
// done
return true;
}
// queue was empty
return false;
}
// polls the queue until an element was dequeued
T pop()
{
T result;
while (!try_pop(result))
{
boost::this_thread::yield();
}
return result;
}
};
#endif // LOCKFREE_LIST_HPP
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 to comment