#include <common.h>
Inheritance diagram for rpa::range_step< It, void >:
Public Types | |
typedef atomic< It > | atom_it |
typedef It | iterator |
typedef std::iterator_traits< It >::value_type | value_type |
typedef range_step_base< It >::slice | slice |
Public Member Functions | |
iterator | begin (void) const |
const iterator | end (void) const |
size_t | size_safe (void) const |
For debugging. Returns an 'absurd' value if the iterators are 'output_type'. | |
range_step (const range_step &aRS) | |
Plain copy constructor. Same as the compiler-generated copy ctor (To remove ???). | |
range_step (It aBeg, It aEnd, size_t aStep=StepUndef, chunk_t aMinChkSz=chunk_t()) | |
This constructor allows to choose exactly the value of the step. | |
range_step (It aBeg, It aEnd, chunk_t aMinChkSz=chunk_t()) | |
If the 'step' of each sequential execution is not given, it gets the default value. | |
slice | chop (void) |
size_t | chop_again (slice &refSlice) |
template<class Rng2> | |
size_t | chop_again (tuple2< slice, typename Rng2::slice > &aPairRef, Rng2 &aSq2) |
template<class Rng2> | |
tuple2< slice, typename Rng2::slice > | chop_init_lock (Rng2 &aSq2) |
template<class Rng2> | |
tuple2< slice, typename Rng2::slice > | chop_init_nolock (Rng2 &aSq2) |
slice | chop_init_lock_cond (bool) |
template<class Rng2> | |
tuple2< slice, typename Rng2::slice > | chop_init_lock_cond (Rng2 &aSq2, bool mustLock) |
Private Member Functions | |
range_step () | |
range_step & | operator= (const range_step &) |
Private Attributes | |
atom_it::atomic_type | _RngBeg |
const It | _RngEnd |
Classes | |
struct | chop_atom_t |
struct | chop_atom_t< range_outp< obuf_iterator< IterOut, Buffer, IterBuf, Mutex > > > |
struct | range_out |
struct | range_out< It2, std::bidirectional_iterator_tag > |
For exemple, if we write into an output sequence which is already allocated. More... | |
struct | range_out< It2, std::forward_iterator_tag > |
struct | range_out< It2, std::random_access_iterator_tag > |
struct | range_out< iterator_lock< It2, Mutex >, std::bidirectional_iterator_tag > |
This template specialization, to forbid this case to happen. More... | |
struct | range_out< iterator_lock< It2, Mutex >, std::forward_iterator_tag > |
This template specialization, to forbid this case to happen. More... | |
struct | range_out< iterator_lock< It2, Mutex >, std::input_iterator_tag > |
This template specialization, to forbid this case to happen. More... | |
struct | range_out< iterator_lock< It2, Mutex >, std::output_iterator_tag > |
For the moment, just to compile, and reuse the defaut existing range_out. More... | |
struct | range_out< iterator_lock< It2, Mutex >, std::random_access_iterator_tag > |
This template specialization, to forbid this case to happen. More... | |
struct | range_out< obuf_iterator< IterOut, Buffer, IterBuf, Mutex >, std::bidirectional_iterator_tag > |
This template specialization, to forbid this case to happen. More... | |
struct | range_out< obuf_iterator< IterOut, Buffer, IterBuf, Mutex >, std::forward_iterator_tag > |
This template specialization, to forbid this case to happen. More... | |
struct | range_out< obuf_iterator< IterOut, Buffer, IterBuf, Mutex >, std::input_iterator_tag > |
This template specialization, to forbid this case to happen. More... | |
struct | range_out< obuf_iterator< IterOut, Buffer, IterBuf, Mutex >, std::output_iterator_tag > |
struct | range_out< obuf_iterator< IterOut, Buffer, IterBuf, Mutex >, std::random_access_iterator_tag > |
This template specialization, to forbid this case to happen. More... | |
class | range_type_iterator_lock |
This to avoid an ambiguous template instantiation. More... |
typedef atomic< It > rpa::range_step< It, void >::atom_it |
About the same as 'range_lambda', but we must be able to read atomically the beginning of the sequence. Therefore, this beginning is encapsulated.
typedef It rpa::range_step< It, void >::iterator |
typedef range_step_base< It >::slice rpa::range_step< It, void >::slice |
typedef std::iterator_traits< It >::value_type rpa::range_step< It, void >::value_type |
rpa::range_step< It, void >::range_step | ( | ) | [private] |
rpa::range_step< It, void >::range_step | ( | const range_step< It, void > & | aRS | ) | [inline] |
Plain copy constructor. Same as the compiler-generated copy ctor (To remove ???).
rpa::range_step< It, void >::range_step | ( | It | aBeg, | |
It | aEnd, | |||
size_t | aStep = StepUndef , |
|||
chunk_t | aMinChkSz = chunk_t() | |||
) | [inline] |
This constructor allows to choose exactly the value of the step.
rpa::range_step< It, void >::range_step | ( | It | aBeg, | |
It | aEnd, | |||
chunk_t | aMinChkSz = chunk_t() | |||
) | [inline] |
If the 'step' of each sequential execution is not given, it gets the default value.
iterator rpa::range_step< It, void >::begin | ( | void | ) | const [inline] |
slice rpa::range_step< It, void >::chop | ( | void | ) | [inline] |
Maybe other synchronization possibilities.
This picks up on the two ranges (Input and output ranges), 'slices' of data to be given to a sub-thread. The difficulty here is that we have to take these slices in an atomic manner. Just as the Motorola instruction CAS2 (Compare and swap on two memory words) works. So, this may not work on first try, and we have to loop until the CompareAndSwap is successful.
The read access must be atomic, because of the other sub-threads.
In the mean time, '_RngBeg' may have changed.
This is why we use CompareAndSwap.
size_t rpa::range_step< It, void >::chop_again | ( | tuple2< slice, typename Rng2::slice > & | aPairRef, | |
Rng2 & | aSq2 | |||
) | [inline] |
This picks up on the two ranges (Input and output ranges), 'slices' of data to be given to a sub-thread. The difficulty here is that we have to take these slices the atomic way. Just like the Motorola instruction CAS2 (Compare and swap on two memory words) used to work. So, this may not work on first try, and we have to loop until the CompareAndSwap is successful.
Do not reuse '_RngBeg' which may have changed in the mean time, because of another subthread : For 'range_step', the input sequence is 'write-shared' by all subthreads. This is why we use an atomic 'load'.
size_t rpa::range_step< It, void >::chop_again | ( | slice & | refSlice | ) | [inline] |
Does the same as 'chop' but the slice is reused and its destructor is not called - which is the goal: NOTE: Temporary sub-optimal solution.
The read access must be atomic, because of the other sub-threads.
In the mean time, '_RngBeg' may have changed.
This is why we use CompareAndSwap.
tuple2< slice, typename Rng2::slice > rpa::range_step< It, void >::chop_init_lock | ( | Rng2 & | aSq2 | ) | [inline] |
tuple2< slice, typename Rng2::slice > rpa::range_step< It, void >::chop_init_lock_cond | ( | Rng2 & | aSq2, | |
bool | mustLock | |||
) | [inline] |
Called only by the constructor of 'coroutine_step', that is, the object used as a functor for each sub-thread. Therefore, we are sure that this constructor is called by the main thread, sequentially. Anyway, as long as the first sub-thread is created, we must lock the input range.
slice rpa::range_step< It, void >::chop_init_lock_cond | ( | bool | ) | [inline] |
Called only by the constructor of 'coroutine_step', that is, the object used as a functor for each sub-thread. Therefore, we are sure that this constructor is called by the main thread, sequentially. Anyway, as long as the first sub-thread is created, we must lock the input range. TODO: It always locks, this should be optimised.
tuple2< slice, typename Rng2::slice > rpa::range_step< It, void >::chop_init_nolock | ( | Rng2 & | aSq2 | ) | [inline] |
const iterator rpa::range_step< It, void >::end | ( | void | ) | const [inline] |
range_step& rpa::range_step< It, void >::operator= | ( | const range_step< It, void > & | ) | [private] |
size_t rpa::range_step< It, void >::size_safe | ( | void | ) | const [inline] |
For debugging. Returns an 'absurd' value if the iterators are 'output_type'.
atom_it::atomic_type rpa::range_step< It, void >::_RngBeg [private] |
const It rpa::range_step< It, void >::_RngEnd [private] |