vendredi 13 mars 2015

Thread Safe C++ Container


After looking for an implementation of a basic Thread Safe C++ Container and not finding one, I rolled my own out:



#pragma once
#include <vector>
#include "boost/thread.hpp"

#define LOCK_OUT boost::unique_lock<boost::mutex> lock(_mutex);

template <class ItemType, class ContainerType = std::deque<ItemType>>
class SuperContainer
{
public:
SuperContainer()
{
}

void push_back(const ItemType & item)
{
LOCK_OUT;
_container.push_back(item);
}

void push_front(const ItemType & item)
{
LOCK_OUT;
_container.push_front(item);
}

void pop_back()
{
LOCK_OUT;
if (!_container.empty())
{
_container.pop_back();
}
}

void pop_front()
{
LOCK_OUT;
if (!_container.empty())
{
_container.pop_front();
}
}

template <class Func>
void for_each(Func func)
{
LOCK_OUT;
for (auto & item : _container)
{
func(item);
}
}

ItemType front()
{
LOCK_OUT;
_container.front();
}

ItemType back()
{
LOCK_OUT;
_container.back();
}

void append(const ContainerType & container)
{
LOCK_OUT;
_container.insert(_container.end(), container.begin(), container.end());
}

bool empty()
{
LOCK_OUT;
return _container.empty();
}

void clear()
{
LOCK_OUT;
_container.clear();
}

bool contains(const ItemType & item)
{
LOCK_OUT;
return std::find(_container.begin(), _container.end(), item);
}

int size()
{
LOCK_OUT;
return _container.size();
}

ItemType at(int index)
{
LOCK_OUT;
return _container.at(index);
}

ItemType operator[](int index)
{
LOCK_OUT;
return _container.at(index);
}

void remove_value(const ItemType & item)
{
LOCK_OUT;
_container.erase(std::remove(_container.begin(), _container.end(), item), _container.end());
}

template <class P>
void erase_if(P func)
{
LOCK_OUT;
_container.erase(std::remove_if(_container.begin(), _container.end(), func), _container.end());
}

void sort()
{
LOCK_OUT;
std::sort(_container.begin(), _container.end());
}

void print_one_on_each_line()
{
LOCK_OUT;
for (auto & item : _container)
{
std::cout << item << std::endl;
}
}

std::string print_to_string()
{
LOCK_OUT;
std::stringstream stream;
for (auto & item : _container)
{
stream << item << std::endl;
}

return stream.str();
}

protected:
ContainerType<ItemType> _container;
boost::mutex _mutex;
};


In order to maintain thread-safety with a container it is not possible to use iterators as they're stored externally to the class and therefore cannot be locked out. So algorithms either need to be passed in functionally or used implemented in the class.


I understand that this breaks algorithm / container separation but that is a necessary evil in order to ensure safety.


Anyway, I thought I'd share it in case anyone else needs one.


Does anyone have any suggestions for improvements?




Aucun commentaire:

Enregistrer un commentaire