371 lines
15 KiB
C++
371 lines
15 KiB
C++
//----------------------------------------------------------------------------
|
|
/// @file deque_cnc.hpp
|
|
/// @brief This file contains the implementation of the several types of
|
|
/// recursive fastmutex for read and write
|
|
///
|
|
/// @author Copyright (c) 2010 2015 Francisco José Tapia (fjtapia@gmail.com )\n
|
|
/// Distributed under the Boost Software License, Version 1.0.\n
|
|
/// ( See accompanyingfile LICENSE_1_0.txt or copy at
|
|
/// http://www.boost.org/LICENSE_1_0.txt )
|
|
/// @version 0.1
|
|
///
|
|
/// @remarks
|
|
//-----------------------------------------------------------------------------
|
|
#ifndef __TOOLS_DEQUE_CNC_HPP
|
|
#define __TOOLS_DEQUE_CNC_HPP
|
|
|
|
#include <ciso646>
|
|
#include <vector>
|
|
#include <deque>
|
|
#include <boost/sort/common/spinlock.hpp>
|
|
|
|
namespace boost
|
|
{
|
|
namespace sort
|
|
{
|
|
namespace common
|
|
{
|
|
|
|
//###########################################################################
|
|
// ##
|
|
// ################################################################ ##
|
|
// # # ##
|
|
// # C L A S S # ##
|
|
// # S T A C K _ C N C # ##
|
|
// # # ##
|
|
// ################################################################ ##
|
|
// ##
|
|
//###########################################################################
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
/// @class deque_cnc
|
|
/// @brief This class is a concurrent stack controled by a spin_lock
|
|
/// @remarks
|
|
//---------------------------------------------------------------------------
|
|
template<typename T, typename Allocator = std::allocator<T> >
|
|
class deque_cnc
|
|
{
|
|
public:
|
|
//-----------------------------------------------------------------------
|
|
// D E F I N I T I O N S
|
|
//-----------------------------------------------------------------------
|
|
typedef std::deque<T, Allocator> deque_t;
|
|
typedef typename deque_t::size_type size_type;
|
|
typedef typename deque_t::difference_type difference_type;
|
|
typedef typename deque_t::value_type value_type;
|
|
typedef typename deque_t::pointer pointer;
|
|
typedef typename deque_t::const_pointer const_pointer;
|
|
typedef typename deque_t::reference reference;
|
|
typedef typename deque_t::const_reference const_reference;
|
|
typedef typename deque_t::allocator_type allocator_type;
|
|
|
|
protected:
|
|
//------------------------------------------------------------------------
|
|
// VARIABLES
|
|
//------------------------------------------------------------------------
|
|
deque_t dq;
|
|
mutable spinlock_t spl;
|
|
|
|
public:
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
// C O N S T R U C T O R S A N D D E S T R U C T O R
|
|
//-----------------------------------------------------------------------
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
// function : deque_cnc
|
|
/// @brief constructor
|
|
//----------------------------------------------------------------------
|
|
explicit inline deque_cnc(void): dq() { };
|
|
//
|
|
//----------------------------------------------------------------------
|
|
// function : deque_cnc
|
|
/// @brief constructor
|
|
/// @param [in] ALLC : Allocator
|
|
//----------------------------------------------------------------------
|
|
explicit inline deque_cnc(const Allocator &ALLC): dq(ALLC){ };
|
|
//
|
|
//----------------------------------------------------------------------
|
|
// function : ~deque_cnc
|
|
/// @brief Destructor
|
|
//----------------------------------------------------------------------
|
|
virtual ~deque_cnc(void){ dq.clear(); };
|
|
//
|
|
//----------------------------------------------------------------------
|
|
// function : clear
|
|
/// @brief Delete all the elements of the deque_cnc.
|
|
//----------------------------------------------------------------------
|
|
void clear(void)
|
|
{
|
|
std::lock_guard < spinlock_t > S(spl);
|
|
dq.clear();
|
|
};
|
|
//
|
|
//------------------------------------------------------------------------
|
|
// function : swap
|
|
/// @brief swap the data between the two deque_cnc
|
|
/// @param [in] A : deque_cnc to swap
|
|
/// @return none
|
|
//-----------------------------------------------------------------------
|
|
void swap(deque_cnc & A) noexcept
|
|
{
|
|
if (this == &A) return;
|
|
std::lock_guard < spinlock_t > S(spl);
|
|
dq.swap(A.dq);
|
|
};
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
// S I Z E , M A X _ S I Z E , R E S I Z E
|
|
// C A P A C I T Y , E M P T Y , R E S E R V E
|
|
//-----------------------------------------------------------------------
|
|
//
|
|
//------------------------------------------------------------------------
|
|
// function : size
|
|
/// @brief return the number of elements in the deque_cnc
|
|
/// @return number of elements in the deque_cnc
|
|
//------------------------------------------------------------------------
|
|
size_type size(void) const noexcept
|
|
{
|
|
std::lock_guard < spinlock_t > S(spl);
|
|
return dq.size();
|
|
};
|
|
//
|
|
//------------------------------------------------------------------------
|
|
// function :max_size
|
|
/// @brief return the maximun size of the container
|
|
/// @return maximun size of the container
|
|
//------------------------------------------------------------------------
|
|
size_type max_size(void) const noexcept
|
|
{
|
|
std::lock_guard < spinlock_t > S(spl);
|
|
return (dq.max_size());
|
|
};
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
// function : shrink_to_fit
|
|
/// @brief resize the current vector size and change to size.\n
|
|
/// If sz is smaller than the current size, delete elements to end\n
|
|
/// If sz is greater than the current size, insert elements to the
|
|
/// end with the value c
|
|
/// @param [in] sz : new size of the deque_cnc after the resize
|
|
/// @param [in] c : Value to insert if sz is greather than the current size
|
|
/// @return none
|
|
//------------------------------------------------------------------------
|
|
void shrink_to_fit()
|
|
{
|
|
std::lock_guard < spinlock_t > S(spl);
|
|
dq.shrink_to_fit();
|
|
};
|
|
//
|
|
//------------------------------------------------------------------------
|
|
// function : empty
|
|
/// @brief indicate if the map is empty
|
|
/// @return true if the map is empty, false in any other case
|
|
//------------------------------------------------------------------------
|
|
bool empty(void) const noexcept
|
|
{
|
|
std::lock_guard < spinlock_t > S(spl);
|
|
return (dq.empty());
|
|
};
|
|
//---------------------------------------------------------------------------
|
|
// function : push_back
|
|
/// @brief Insert one element in the back of the container
|
|
/// @param [in] D : value to insert. Can ve a value, a reference or an
|
|
/// rvalue
|
|
//---------------------------------------------------------------------------
|
|
void push_back(const value_type & D)
|
|
{
|
|
std::lock_guard < spinlock_t > S(spl);
|
|
dq.push_back(D);
|
|
};
|
|
|
|
//------------------------------------------------------------------------
|
|
// function : emplace_back
|
|
/// @brief Insert one element in the back of the container
|
|
/// @param [in] args :group of arguments for to build the object to insert
|
|
//-------------------------------------------------------------------------
|
|
template<class ... Args>
|
|
void emplace_back(Args && ... args)
|
|
{
|
|
std::lock_guard < spinlock_t > S(spl);
|
|
dq.emplace_back(std::forward <Args>(args) ...);
|
|
};
|
|
//------------------------------------------------------------------------
|
|
// function : push_back
|
|
/// @brief Insert one element in the back of the container
|
|
/// @param [in] D : deque to insert in the actual deque, inserting a copy
|
|
/// of the elements
|
|
/// @return reference to the deque after the insertion
|
|
//------------------------------------------------------------------------
|
|
template<class Allocator2>
|
|
deque_cnc & push_back(const std::deque<value_type, Allocator2> & D)
|
|
{
|
|
std::lock_guard < spinlock_t > S(spl);
|
|
for (size_type i = 0; i < D.size(); ++i)
|
|
dq.push_back(D[i]);
|
|
return *this;
|
|
};
|
|
//------------------------------------------------------------------------
|
|
// function : push_back
|
|
/// @brief Insert one element in the back of the container
|
|
/// @param [in] D : deque to insert in the actual deque, inserting a move
|
|
/// of the elements
|
|
/// @return reference to the deque after the insertion
|
|
//------------------------------------------------------------------------
|
|
deque_cnc & push_back(std::deque<value_type, Allocator> && D)
|
|
{
|
|
std::lock_guard < spinlock_t > S(spl);
|
|
for (size_type i = 0; i < D.size(); ++i)
|
|
dq.emplace_back(std::move(D[i]));
|
|
return *this;
|
|
};
|
|
//
|
|
//------------------------------------------------------------------------
|
|
// function :pop_back
|
|
/// @brief erase the last element of the container
|
|
//-----------------------------------------------------------------------
|
|
void pop_back(void)
|
|
{
|
|
std::lock_guard < spinlock_t > S(spl);
|
|
dq.pop_back();
|
|
};
|
|
//
|
|
//------------------------------------------------------------------------
|
|
// function :pop_copy_back
|
|
/// @brief erase the last element and return a copy over P
|
|
/// @param [out] P : reference to a variable where copy the element
|
|
/// @return code of the operation
|
|
/// true - Element erased
|
|
/// false - Empty tree
|
|
//------------------------------------------------------------------------
|
|
bool pop_copy_back(value_type & P)
|
|
{ //-------------------------- begin -----------------------------
|
|
std::lock_guard < spinlock_t > S(spl);
|
|
if (dq.size() == 0) return false;
|
|
P = dq.back();
|
|
dq.pop_back();
|
|
return true;
|
|
};
|
|
//
|
|
//------------------------------------------------------------------------
|
|
// function :pop_move_back
|
|
/// @brief erase the last element and move over P
|
|
/// @param [out] P : reference to a variable where move the element
|
|
/// @return code of the operation
|
|
/// true - Element erased
|
|
/// false - Empty tree
|
|
//------------------------------------------------------------------------
|
|
bool pop_move_back(value_type & P)
|
|
{ //-------------------------- begin -----------------------------
|
|
std::lock_guard < spinlock_t > S(spl);
|
|
if (dq.size() == 0) return false;
|
|
P = std::move(dq.back());
|
|
dq.pop_back();
|
|
return true;
|
|
};
|
|
|
|
//------------------------------------------------------------------------
|
|
// function : push_front
|
|
/// @brief Insert one copy of the element in the front of the container
|
|
/// @param [in] D : value to insert
|
|
//------------------------------------------------------------------------
|
|
void push_front(const value_type & D)
|
|
{
|
|
std::lock_guard < spinlock_t > S(spl);
|
|
dq.push_front(D);
|
|
};
|
|
|
|
//------------------------------------------------------------------------
|
|
// function : emplace_front
|
|
/// @brief Insert one element in the front of the container
|
|
/// @param [in] args :group of arguments for to build the object to insert
|
|
//-------------------------------------------------------------------------
|
|
template<class ... Args>
|
|
void emplace_front(Args && ... args)
|
|
{
|
|
std::lock_guard < spinlock_t > S(spl);
|
|
dq.emplace_front(std::forward <Args>(args) ...);
|
|
};
|
|
//------------------------------------------------------------------------
|
|
// function : push_front
|
|
/// @brief Insert a copy of the elements of the deque V1 in the front
|
|
/// of the container
|
|
/// @param [in] V1 : deque with the elements to insert
|
|
/// @return reference to the deque after the insertion
|
|
//------------------------------------------------------------------------
|
|
template<class Allocator2>
|
|
deque_cnc & push_front(const std::deque<value_type, Allocator2> & V1)
|
|
{
|
|
std::lock_guard < spinlock_t > S(spl);
|
|
for (size_type i = 0; i < V1.size(); ++i)
|
|
dq.push_front(V1[i]);
|
|
return *this;
|
|
};
|
|
//-----------------------------------------------------------------------
|
|
// function : push_front
|
|
/// @brief Insert a move of the elements of the deque V1 in the front
|
|
/// of the container
|
|
/// @param [in] V1 : deque with the elements to insert
|
|
/// @return reference to the deque after the insertion
|
|
//-----------------------------------------------------------------------
|
|
deque_cnc & push_front(std::deque<value_type, Allocator> && V1)
|
|
{
|
|
std::lock_guard < spinlock_t > S(spl);
|
|
for (size_type i = 0; i < V1.size(); ++i)
|
|
dq.emplace_front(std::move(V1[i]));
|
|
return *this;
|
|
};
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
// function :pop_front
|
|
/// @brief erase the first element of the container
|
|
//-----------------------------------------------------------------------
|
|
void pop_front(void)
|
|
{
|
|
std::lock_guard < spinlock_t > S(spl);
|
|
dq.pop_front();
|
|
};
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
// function :pop_copy_front
|
|
/// @brief erase the first element of the tree and return a copy over P
|
|
/// @param [out] P : reference to a variable where copy the element
|
|
/// @return code of the operation
|
|
/// true- Element erased
|
|
/// false - Empty tree
|
|
//-----------------------------------------------------------------------
|
|
bool pop_copy_front(value_type & P)
|
|
{ //-------------------------- begin -----------------------------
|
|
std::lock_guard < spinlock_t > S(spl);
|
|
if (dq.size() == 0) return false;
|
|
P = dq.front();
|
|
dq.pop_front();
|
|
return true;
|
|
};
|
|
//
|
|
//------------------------------------------------------------------------
|
|
// function :pop_move_front
|
|
/// @brief erase the first element of the tree and return a move over P
|
|
/// @param [out] P : reference to a variable where move the element
|
|
/// @return code of the operation
|
|
/// true- Element erased
|
|
/// false - Empty tree
|
|
//------------------------------------------------------------------------
|
|
bool pop_move_front(value_type & P)
|
|
{ //-------------------------- begin -----------------------------
|
|
std::lock_guard < spinlock_t > S(spl);
|
|
if (dq.size() == 0) return false;
|
|
P = std::move(dq.front());
|
|
dq.pop_front();
|
|
return true;
|
|
};
|
|
};
|
|
// end class deque_cnc
|
|
|
|
//***************************************************************************
|
|
};// end namespace common
|
|
};// end namespace sort
|
|
};// end namespace boost
|
|
//***************************************************************************
|
|
#endif
|