%PDF- %PDF-
| Direktori : /usr/include/boost/sort/parallel_stable_sort/ |
| Current File : //usr/include/boost/sort/parallel_stable_sort/parallel_stable_sort.hpp |
//----------------------------------------------------------------------------
/// @file parallel_stable_sort.hpp
/// @brief This file contains the class parallel_stable_sort
///
/// @author Copyright (c) 2016 Francisco Jose Tapia (fjtapia@gmail.com )\n
/// Distributed under the Boost Software License, Version 1.0.\n
/// ( See accompanying file LICENSE_1_0.txt or copy at
/// http://www.boost.org/LICENSE_1_0.txt )
/// @version 0.1
///
/// @remarks
//-----------------------------------------------------------------------------
#ifndef __BOOST_SORT_PARALLEL_DETAIL_PARALLEL_STABLE_SORT_HPP
#define __BOOST_SORT_PARALLEL_DETAIL_PARALLEL_STABLE_SORT_HPP
#include <boost/sort/sample_sort/sample_sort.hpp>
#include <boost/sort/common/util/traits.hpp>
#include <functional>
#include <future>
#include <iterator>
#include <memory>
#include <type_traits>
#include <vector>
namespace boost
{
namespace sort
{
namespace stable_detail
{
//---------------------------------------------------------------------------
// USING SENTENCES
//---------------------------------------------------------------------------
namespace bsc = boost::sort::common;
namespace bss = boost::sort::spin_detail;
using bsc::range;
using bsc::merge_half;
using boost::sort::sample_detail::sample_sort;
//
///---------------------------------------------------------------------------
/// @struct parallel_stable_sort
/// @brief This a structure for to implement a parallel stable sort, exception
/// safe
//----------------------------------------------------------------------------
template <class Iter_t, class Compare = compare_iter <Iter_t> >
struct parallel_stable_sort
{
//-------------------------------------------------------------------------
// DEFINITIONS
//-------------------------------------------------------------------------
typedef value_iter<Iter_t> value_t;
//-------------------------------------------------------------------------
// VARIABLES
//-------------------------------------------------------------------------
// Number of elements to sort
size_t nelem;
// Pointer to the auxiliary memory needed for the algorithm
value_t *ptr;
// Minimal number of elements for to be sorted in parallel mode
const size_t nelem_min = 1 << 16;
//------------------------------------------------------------------------
// F U N C T I O N S
//------------------------------------------------------------------------
parallel_stable_sort (Iter_t first, Iter_t last)
: parallel_stable_sort (first, last, Compare(),
std::thread::hardware_concurrency()) { };
parallel_stable_sort (Iter_t first, Iter_t last, Compare cmp)
: parallel_stable_sort (first, last, cmp,
std::thread::hardware_concurrency()) { };
parallel_stable_sort (Iter_t first, Iter_t last, uint32_t num_thread)
: parallel_stable_sort (first, last, Compare(), num_thread) { };
parallel_stable_sort (Iter_t first, Iter_t last, Compare cmp,
uint32_t num_thread);
//
//-----------------------------------------------------------------------------
// function : destroy_all
/// @brief The utility is to destroy the temporary buffer used in the
/// sorting process
//-----------------------------------------------------------------------------
void destroy_all()
{
if (ptr != nullptr) std::return_temporary_buffer(ptr);
};
//
//-----------------------------------------------------------------------------
// function :~parallel_stable_sort
/// @brief destructor of the class. The utility is to destroy the temporary
/// buffer used in the sorting process
//-----------------------------------------------------------------------------
~parallel_stable_sort() {destroy_all(); } ;
};
// end struct parallel_stable_sort
//
//############################################################################
// ##
// ##
// N O N I N L I N E F U N C T I O N S ##
// ##
// ##
//############################################################################
//
//-----------------------------------------------------------------------------
// function : parallel_stable_sort
/// @brief constructor of the class
///
/// @param first : iterator to the first element of the range to sort
/// @param last : iterator after the last element to the range to sort
/// @param comp : object for to compare two elements pointed by Iter_t
/// iterators
/// @param nthread : Number of threads to use in the process. When this value
/// is lower than 2, the sorting is done with 1 thread
//-----------------------------------------------------------------------------
template <class Iter_t, class Compare>
parallel_stable_sort <Iter_t, Compare>
::parallel_stable_sort (Iter_t first, Iter_t last, Compare comp,
uint32_t nthread) : nelem(0), ptr(nullptr)
{
range<Iter_t> range_initial(first, last);
assert(range_initial.valid());
nelem = range_initial.size();
size_t nptr = (nelem + 1) >> 1;
if (nelem < nelem_min or nthread < 2)
{
bss::spinsort<Iter_t, Compare>
(range_initial.first, range_initial.last, comp);
return;
};
//------------------- check if sort --------------------------------------
bool sw = true;
for (Iter_t it1 = first, it2 = first + 1;
it2 != last and (sw = not comp(*it2, *it1)); it1 = it2++);
if (sw) return;
//------------------- check if reverse sort ---------------------------
sw = true;
for (Iter_t it1 = first, it2 = first + 1;
it2 != last and (sw = comp(*it2, *it1)); it1 = it2++);
if (sw)
{
size_t nelem2 = nelem >> 1;
Iter_t it1 = first, it2 = last - 1;
for (size_t i = 0; i < nelem2; ++i)
std::swap(*(it1++), *(it2--));
return;
};
ptr = std::get_temporary_buffer<value_t>(nptr).first;
if (ptr == nullptr) throw std::bad_alloc();
//---------------------------------------------------------------------
// Parallel Process
//---------------------------------------------------------------------
range<Iter_t> range_first(range_initial.first, range_initial.first + nptr);
range<Iter_t> range_second(range_initial.first + nptr, range_initial.last);
range<value_t *> range_buffer(ptr, ptr + nptr);
try
{
sample_sort<Iter_t, Compare>
(range_initial.first, range_initial.first + nptr,
comp, nthread, range_buffer);
} catch (std::bad_alloc &)
{
destroy_all();
throw std::bad_alloc();
};
try
{
sample_sort<Iter_t, Compare>
(range_initial.first + nptr,
range_initial.last, comp, nthread, range_buffer);
} catch (std::bad_alloc &)
{
destroy_all();
throw std::bad_alloc();
};
range_buffer = move_forward(range_buffer, range_first);
range_initial = merge_half(range_initial, range_buffer, range_second, comp);
}; // end of constructor
//
//****************************************************************************
};// End namespace stable_detail
//****************************************************************************
//
//---------------------------------------------------------------------------
// USING SENTENCES
//---------------------------------------------------------------------------
namespace bsc = boost::sort::common;
namespace bscu = bsc::util;
namespace bss = boost::sort::spin_detail;
using bsc::range;
using bsc::merge_half;
//
//############################################################################
// ##
// ##
// P A R A L L E L _ S T A B L E _ S O R T ##
// ##
// ##
//############################################################################
//
//-----------------------------------------------------------------------------
// function : parallel_stable_sort
/// @brief : parallel stable sort with 2 parameters
///
/// @param first : iterator to the first element of the range to sort
/// @param last : iterator after the last element to the range to sort
//-----------------------------------------------------------------------------
template<class Iter_t>
void parallel_stable_sort(Iter_t first, Iter_t last)
{
typedef bscu::compare_iter<Iter_t> Compare;
stable_detail::parallel_stable_sort<Iter_t, Compare>(first, last);
};
//
//-----------------------------------------------------------------------------
// function : parallel_stable_sort
/// @brief parallel stable sort with 3 parameters. The third is the number
/// of threads
///
/// @param first : iterator to the first element of the range to sort
/// @param last : iterator after the last element to the range to sort
/// @param nthread : Number of threads to use in the process. When this value
/// is lower than 2, the sorting is done with 1 thread
//-----------------------------------------------------------------------------
template<class Iter_t>
void parallel_stable_sort(Iter_t first, Iter_t last, uint32_t nthread)
{
typedef bscu::compare_iter<Iter_t> Compare;
stable_detail::parallel_stable_sort<Iter_t, Compare>(first, last, nthread);
};
//
//-----------------------------------------------------------------------------
// function : parallel_stable_sort
/// @brief : parallel stable sort with 3 parameters. The thisrd is the
/// comparison object
///
/// @param first : iterator to the first element of the range to sort
/// @param last : iterator after the last element to the range to sort
/// @param comp : object for to compare two elements pointed by Iter_t
/// iterators
//-----------------------------------------------------------------------------
template <class Iter_t, class Compare,
bscu::enable_if_not_integral<Compare> * = nullptr>
void parallel_stable_sort(Iter_t first, Iter_t last, Compare comp)
{
stable_detail::parallel_stable_sort<Iter_t, Compare>(first, last, comp);
};
//
//-----------------------------------------------------------------------------
// function : parallel_stable_sort
/// @brief : parallel stable sort with 3 parameters.
///
/// @param first : iterator to the first element of the range to sort
/// @param last : iterator after the last element to the range to sort
/// @param comp : object for to compare two elements pointed by Iter_t
/// iterators
/// @param nthread : Number of threads to use in the process. When this value
/// is lower than 2, the sorting is done with 1 thread
//-----------------------------------------------------------------------------
template<class Iter_t, class Compare>
void parallel_stable_sort (Iter_t first, Iter_t last, Compare comp,
uint32_t nthread)
{
stable_detail::parallel_stable_sort<Iter_t, Compare>
(first, last, comp, nthread);
}
//
//****************************************************************************
};// End namespace sort
};// End namespace boost
//****************************************************************************
//
#endif