%PDF- %PDF-
| Direktori : /proc/self/root/usr/include/boost/sort/block_indirect_sort/blk_detail/ |
| Current File : //proc/self/root/usr/include/boost/sort/block_indirect_sort/blk_detail/move_blocks.hpp |
//----------------------------------------------------------------------------
/// @file move_blocks.hpp
/// @brief contains the class move_blocks, which is part of the
/// block_indirect_sort algorithm
///
/// @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_MOVE_BLOCKS_HPP
#define __BOOST_SORT_PARALLEL_DETAIL_MOVE_BLOCKS_HPP
#include <atomic>
#include <boost/sort/block_indirect_sort/blk_detail/backbone.hpp>
#include <future>
#include <iostream>
#include <iterator>
namespace boost
{
namespace sort
{
namespace blk_detail
{
//----------------------------------------------------------------------------
// USING SENTENCES
//----------------------------------------------------------------------------
namespace bsc = boost::sort::common;
//
///---------------------------------------------------------------------------
/// @struct move_blocks
/// @brief This class move the blocks, trnasforming a logical sort by an index,
/// in physical sort
//----------------------------------------------------------------------------
template<uint32_t Block_size, uint32_t Group_size, class Iter_t, class Compare>
struct move_blocks
{
//-------------------------------------------------------------------------
// D E F I N I T I O N S
//-------------------------------------------------------------------------
typedef move_blocks<Block_size, Group_size, Iter_t, Compare> this_type;
typedef typename std::iterator_traits<Iter_t>::value_type value_t;
typedef std::atomic<uint32_t> atomic_t;
typedef bsc::range<size_t> range_pos;
typedef bsc::range<Iter_t> range_it;
typedef bsc::range<value_t *> range_buf;
typedef std::function<void(void)> function_t;
typedef backbone<Block_size, Iter_t, Compare> backbone_t;
//------------------------------------------------------------------------
// V A R I A B L E S
//------------------------------------------------------------------------
// Object with the elements to sort and all internal data structures of the
// algorithm
backbone_t &bk;
//------------------------------------------------------------------------
// F U N C T I O N S
//------------------------------------------------------------------------
move_blocks(backbone_t &bkb);
void move_sequence(const std::vector<size_t> &init_sequence);
void move_long_sequence(const std::vector<size_t> &init_sequence);
//
//------------------------------------------------------------------------
// function : function_move_sequence
/// @brief create a function_t with a call to move_sequence, and insert
/// in the stack of the backbone
///
/// @param sequence :sequence of positions for to move the blocks
/// @param counter : atomic variable which is decremented when finish
/// the function. This variable is used for to know
/// when are finished all the function_t created
/// inside an object
/// @param error : global indicator of error.
//------------------------------------------------------------------------
void function_move_sequence(std::vector<size_t> &sequence,
atomic_t &counter, bool &error)
{
bscu::atomic_add(counter, 1);
function_t f1 = [this, sequence, &counter, &error]( ) -> void
{
if (not error)
{
try
{
this->move_sequence (sequence);
}
catch (std::bad_alloc &)
{
error = true;
};
}
bscu::atomic_sub (counter, 1);
};
bk.works.emplace_back(f1);
}
//
//------------------------------------------------------------------------
// function : function_move_long_sequence
/// @brief create a function_t with a call to move_long_sequence, and
/// insert in the stack of the backbone
//
/// @param sequence :sequence of positions for to move the blocks
/// @param counter : atomic variable which is decremented when finish
/// the function. This variable is used for to know
/// when are finished all the function_t created
/// inside an object
/// @param error : global indicator of error.
//------------------------------------------------------------------------
void function_move_long_sequence(std::vector<size_t> &sequence,
atomic_t &counter, bool &error)
{
bscu::atomic_add(counter, 1);
function_t f1 = [this, sequence, &counter, &error]( ) -> void
{
if (not error)
{
try
{
this->move_long_sequence (sequence);
}
catch (std::bad_alloc &)
{
error = true;
};
}
bscu::atomic_sub (counter, 1);
};
bk.works.emplace_back(f1);
}
;
//---------------------------------------------------------------------------
}; // end of struct move_blocks
//---------------------------------------------------------------------------
//
//############################################################################
// ##
// ##
// N O N I N L I N E F U N C T I O N S ##
// ##
// ##
//############################################################################
//
//-------------------------------------------------------------------------
// function : move_blocks
/// @brief constructor of the class for to move the blocks to their true
/// position obtained from the index
//
/// @param bkb : backbone with the index and the blocks
//-------------------------------------------------------------------------
template<uint32_t Block_size, uint32_t Group_size, class Iter_t, class Compare>
move_blocks<Block_size, Group_size, Iter_t, Compare>
::move_blocks(backbone_t &bkb) : bk(bkb)
{
std::vector<std::vector<size_t> > vsequence;
vsequence.reserve(bk.index.size() >> 1);
std::vector<size_t> sequence;
atomic_t counter(0);
size_t pos_index_ini = 0, pos_index_src = 0, pos_index_dest = 0;
while (pos_index_ini < bk.index.size())
{
while (pos_index_ini < bk.index.size()
and bk.index[pos_index_ini].pos() == pos_index_ini)
{
++pos_index_ini;
};
if (pos_index_ini == bk.index.size()) break;
sequence.clear();
pos_index_src = pos_index_dest = pos_index_ini;
sequence.push_back(pos_index_ini);
while (bk.index[pos_index_dest].pos() != pos_index_ini)
{
pos_index_src = bk.index[pos_index_dest].pos();
sequence.push_back(pos_index_src);
bk.index[pos_index_dest].set_pos(pos_index_dest);
pos_index_dest = pos_index_src;
};
bk.index[pos_index_dest].set_pos(pos_index_dest);
vsequence.push_back(sequence);
if (sequence.size() < Group_size)
{
function_move_sequence(vsequence.back(), counter, bk.error);
}
else
{
function_move_long_sequence(vsequence.back(), counter, bk.error);
};
};
bk.exec(counter);
}
;
//
//-------------------------------------------------------------------------
// function : move_sequence
/// @brief move the blocks, following the positions of the init_sequence
//
/// @param init_sequence : vector with the positions from and where move the
/// blocks
//-------------------------------------------------------------------------
template<uint32_t Block_size, uint32_t Group_size, class Iter_t, class Compare>
void move_blocks<Block_size, Group_size, Iter_t, Compare>
::move_sequence(const std::vector<size_t> &init_sequence)
{
range_buf rbuf = bk.get_range_buf();
size_t pos_range2 = init_sequence[0];
range_it range2 = bk.get_range(pos_range2);
move_forward(rbuf, range2);
for (size_t i = 1; i < init_sequence.size(); ++i)
{
pos_range2 = init_sequence[i];
range_it range1(range2);
range2 = bk.get_range(pos_range2);
move_forward(range1, range2);
};
move_forward(range2, rbuf);
};
//
//-------------------------------------------------------------------------
// function : move_long_sequence
/// @brief move the blocks, following the positions of the init_sequence.
/// if the sequence is greater than Group_size, it is divided in small
/// sequences, creating function_t elements, for to be inserted in the
/// concurrent stack
//
/// @param init_sequence : vector with the positions from and where move the
/// blocks
//-------------------------------------------------------------------------
template<uint32_t Block_size, uint32_t Group_size, class Iter_t, class Compare>
void move_blocks<Block_size, Group_size, Iter_t, Compare>
::move_long_sequence(const std::vector<size_t> &init_sequence)
{
if (init_sequence.size() < Group_size) return move_sequence(init_sequence);
size_t npart = (init_sequence.size() + Group_size - 1) / Group_size;
size_t size_part = init_sequence.size() / npart;
atomic_t son_counter(0);
std::vector<size_t> sequence;
sequence.reserve(size_part);
std::vector<size_t> index_seq;
index_seq.reserve(npart);
auto it_pos = init_sequence.begin();
for (size_t i = 0; i < (npart - 1); ++i, it_pos += size_part)
{
sequence.assign(it_pos, it_pos + size_part);
index_seq.emplace_back(*(it_pos + size_part - 1));
function_move_sequence(sequence, son_counter, bk.error);
};
sequence.assign(it_pos, init_sequence.end());
index_seq.emplace_back(init_sequence.back());
function_move_sequence(sequence, son_counter, bk.error);
bk.exec(son_counter);
if (bk.error) return;
move_long_sequence(index_seq);
}
//
//****************************************************************************
}; // End namespace blk_detail
}; // End namespace sort
}; // End namespace boost
//****************************************************************************
//
#endif