#include <pthread.h>
#include <iterator>
#include <vector>
#include <iostream>
#include <sstream>
#include <stdlib.h>
#include <algorithm>
#include <numeric>
#include <set>
#include <list>
#include <deque>
#include <rpa/architectures/posix.h>
#include <rpa/algorithms/accumulate.h>
#include <rpa/algorithms/transform.h>
#include <rpa/containers/list.h>
#include <rpa/containers/deque.h>
#include <rpa/containers/vector.h>
#include <rpa/containers/pipeline.h>
Classes | |
struct | identity24< Type > |
struct | adder24< Type > |
This functor is used by rpa::accumulate, and is identical to std::plus. More... | |
Defines | |
#define | Test(a) _Test24(#a,a) |
Typedefs | |
typedef rpa::posix_condition | cond_main_t |
Used everywhere. | |
typedef rpa::posix_mutex | mutex_lock_type |
Functions | |
static void | _Test24 (const char *aMsg, bool aBool) |
Simple comparison and display of a messqge, for debugging. | |
template<class SubThr, class Container, class PipTyp> | |
static void | tst24OneSubThr (const Container &lstDat, typename Container::value_type sumDat, size_t nbDbls, size_t nbThrs, size_t szPipCirc) |
Only one subthread for the input algorithm. | |
template<class SubThr, class Container, class PipTyp> | |
static void | tst24OneSubThrRange (const Container &lstDat, typename Container::value_type sumDat, size_t nbDbls, size_t nbThrs, size_t szPipCirc, size_t nbStps) |
template<class SubThr, class Container, class PipTyp> | |
static void | tst24OutputInSubThr (const Container &lstDat, typename Container::value_type sumDat, size_t nbDbls, size_t nbThrs, size_t szPipCirc, size_t nbStps) |
template<class SubThr, class Container, class PipTyp> | |
static void | tst24ConstPipeAccumRng (const Container &lstDat, typename Container::value_type sumDat, size_t nbDbls, size_t nbThrs, size_t szPipCirc, size_t nbStps) |
template<class SubThr, class Container, class PipTyp> | |
static void | tst24CpyOrdInfiniteAccum (const Container &lstDat, typename Container::value_type sumDat, size_t nbDbls, size_t nbThrs, size_t nbStps) |
template<class SubThr, class Container, class PipTyp> | |
static void | tst24CopyRangeToCont (const Container &lstDat, typename Container::value_type sumDat, size_t nbDbls, size_t nbThrs, size_t nbStps) |
This tests checks that elements can be read only once from a pipe line. | |
template<class SubThr, class Container, class PipTyp> | |
static void | tst24CopyRangeToArc (const Container &lstDat, typename Container::value_type sumDat, size_t nbDbls, size_t nbThrs, size_t szPipCirc, size_t nbStps) |
This tests checks that elements can be read only once from a pipe line. | |
template<class SubThr, class Container, class PipTyp> | |
static void | tst24MergeDynamic (const Container &lstDat, typename Container::value_type sumDat, size_t nbDbls, size_t nbThrs, size_t szPipCirc, size_t nbStps) |
template<class SubThr, class Container, class PipTyp> | |
static void | tst24MergeDynamicAsym (const Container &lstDat, typename Container::value_type sumDat, size_t nbDbls, size_t nbThrs, size_t szPipCirc, size_t nbStps) |
template<class SubThr, class Container, class PipTyp> | |
static void | tst24MonoCircular (const Container &lstDat, typename Container::value_type sumDat, size_t nbDbls, size_t nbThrs, size_t nbStps) |
template<class SubThr, class Container, class PipTyp> | |
static void | tst24MonoArchiver (const Container &lstDat, typename Container::value_type sumDat, size_t nbDbls, size_t nbThrs, size_t nbStps) |
template<class SubThr, class Container, class PipTyp> | |
static void | tst24DualArchiver (const Container &lstDat, typename Container::value_type sumDat, size_t nbDbls, size_t nbThrs, size_t nbStps) |
template<class SubThr, class Cont, class PipTyp> | |
static void | tst24ContBuf (const Cont &lstDat, typename Cont::value_type sumDat, size_t nbDbls, size_t nbThrs) |
template<class SubThr, class Cont> | |
static void | tst24Containers (size_t nbDbls, size_t nbThrs) |
template<class SubThr> | |
void | tst24Thr (size_t nbE, size_t nbThrs) |
int | main (int aArgC, const char **aArgV) |
#define Test | ( | a | ) | _Test24(#a,a) |
typedef rpa::posix_condition cond_main_t |
Used everywhere.
typedef rpa::posix_mutex mutex_lock_type |
This is used each time several threads write into the same output iterator.
static void _Test24 | ( | const char * | aMsg, | |
bool | aBool | |||
) | [static] |
Simple comparison and display of a messqge, for debugging.
Necessary because we need to know whether the iterators are invalidated when an insertion is done in the containers.
int main | ( | int | aArgC, | |
const char ** | aArgV | |||
) |
static void tst24ConstPipeAccumRng | ( | const Container & | lstDat, | |
typename Container::value_type | sumDat, | |||
size_t | nbDbls, | |||
size_t | nbThrs, | |||
size_t | szPipCirc, | |||
size_t | nbStps | |||
) | [static] |
We build first a circular pipeline which is constant, and big enough to contain all input data. And later run on it 'accumulate' which reads range of data.
This pipeline is shut at the beginning. It means that a reading thread will detect the end of the pipeline.
This checks that the init value is correct.
Execution of this functor, which now waits until its subthreads have finished. They do not need to wait for the input pipeline which is full and shut.
This waits for the final result. This is a blocking call until the thread is 'joined'. A thread is created for running the algorithm, and this thread may create sub-threads.
static void tst24Containers | ( | size_t | nbDbls, | |
size_t | nbThrs | |||
) | [static] |
static void tst24ContBuf | ( | const Cont & | lstDat, | |
typename Cont::value_type | sumDat, | |||
size_t | nbDbls, | |||
size_t | nbThrs | |||
) | [static] |
static void tst24CopyRangeToArc | ( | const Container & | lstDat, | |
typename Container::value_type | sumDat, | |||
size_t | nbDbls, | |||
size_t | nbThrs, | |||
size_t | szPipCirc, | |||
size_t | nbStps | |||
) | [static] |
This tests checks that elements can be read only once from a pipe line.
The output pipe may have another type of underlying container. The output pipes have a limit.
A shutter_thread sets the pipe as closed at the end of the thread. So, the reader know that no other data will come from this pipe, and then they stop waiting.
A back_insert_iterator into a pipeline is protected because the method push_back() is therad_safe. Therefore, it is not necessary to protect it with a mutex.
This functor will be started in a subthread.
The output elements might not be in the right order. So we sort them before comparing. This happens if there are genuine subthreads.
static void tst24CopyRangeToCont | ( | const Container & | lstDat, | |
typename Container::value_type | sumDat, | |||
size_t | nbDbls, | |||
size_t | nbThrs, | |||
size_t | nbStps | |||
) | [static] |
This tests checks that elements can be read only once from a pipe line.
A shutter_thread sets the pipe as closed at the end of the thread. So, the reader know that no other data will come from this pipe, and then they stop waiting. The insertion into the container is not protected because it will be executed without subthreads.
This is the thread tree containing just one top-level sub-thread. Therefore, it is not necessary to lock the insertion iterator into the container, because just one will write into it at a time.
This functor will be started in a subthread.
This starts the algorithm in a thread tree which has just a thread at its head.
It waits until the end of the algorithm. The output container must NOT be used until the end, because it is not protected by a mutex.
These containers must be identical.
static void tst24CpyOrdInfiniteAccum | ( | const Container & | lstDat, | |
typename Container::value_type | sumDat, | |||
size_t | nbDbls, | |||
size_t | nbThrs, | |||
size_t | nbStps | |||
) | [static] |
This checks that the output must be the same as the input. Test with a pipeline of infinite size. The elements are read with a range,
When a pipeline is initialised with a pair of iterators, by default, the flag 'shut' is set to true, which means that there will be no more insertions.
Now the pipe must be empty.
static void tst24DualArchiver | ( | const Container & | lstDat, | |
typename Container::value_type | sumDat, | |||
size_t | nbDbls, | |||
size_t | nbThrs, | |||
size_t | nbStps | |||
) | [static] |
This tests checks that elements can be read only once from a pipe line. The input elements must absolutely be sorted.
Two different ranges are reading the same input This functor will be started in a subthread.
This functor will be started in a subthread.
We wait until the sub-threads are finished, otherwise the size would be meaningless. The output pipes must be limitless to contain the whole output.
We try another combination for sorting before testing.
These containers must be identical.
static void tst24MergeDynamic | ( | const Container & | lstDat, | |
typename Container::value_type | sumDat, | |||
size_t | nbDbls, | |||
size_t | nbThrs, | |||
size_t | szPipCirc, | |||
size_t | nbStps | |||
) | [static] |
This tests checks that elements can be read only once from a pipe line. Two different threads read the same pipe_circular, with ranges. The input elements must absolutely be sorted.
The output pipe may have another type of underlying container. The output pipes have a limit.
A shutter_thread sets the pipe as closed at the end of the thread. So, the readers know that no other data will come from this pipe, and then they stop waiting.
Two different ranges are reading the same input. This functor will be started in a subthread.
This functor will be started in a subthread.
There may be several sub-threads and therefore the results have a changed order.
This is computed before waiting the end of the subthreads.
These containers must be identical.
static void tst24MergeDynamicAsym | ( | const Container & | lstDat, | |
typename Container::value_type | sumDat, | |||
size_t | nbDbls, | |||
size_t | nbThrs, | |||
size_t | szPipCirc, | |||
size_t | nbStps | |||
) | [static] |
This tests checks that elements can be read only once from a pipe line. Two threads read the same pipe. One of them uses a range, the other reads the elements one after the other. The input elements must absolutely be sorted.
The output pipe may have another type of underlying container. The output pipes have a limit.
A shutter_thread sets the pipe as closed at the end of the thread. So, the readers know that no ther data will come from this pipe, and then they stop waiting.
Two different ranges are reading the same input. This functor will be started in a subthread. The elements are read slice by slice.
The output pipe must be able to store all elements otherwise it would hang forever, because the last reading call runs in the same thread.
This functor is run in the same thread. It does not matter if it starves, because the subthread will read from the input pipe too. The elements are read one after the other.
This is computed before waiting the end of the subthreads.
These containers must be identical.
static void tst24MonoArchiver | ( | const Container & | lstDat, | |
typename Container::value_type | sumDat, | |||
size_t | nbDbls, | |||
size_t | nbThrs, | |||
size_t | nbStps | |||
) | [static] |
Simply reads from a pipe_archiver into a plain container. This is exactly the same as tst24MonoArchiver except that a circular is used instead of an archiver.
This pipe is initially shut. We will read its content and will not wait when it will be empty. There is no write access during the reads.
The type of the main thread running the algorithm which reads the input pipe.
The output iterator must be protected because several sub-threads will write into it. The mutex can have any type and is independent of the mutex locking read accesses from the pipeline.
The type of the algorithm which reads the input data slices by slices (And not element by element, hence the range_step_type).
The output container must be limitless to contain the whole data.
Two different ranges are reading the same input This functor will be started in a subthread.
We wait until the sub-threads are finished, otherwise the size would be meaningless.
We try another combination for sorting before testing.
Simply copies the elements which are already allocated.
These containers must be identical.
static void tst24MonoCircular | ( | const Container & | lstDat, | |
typename Container::value_type | sumDat, | |||
size_t | nbDbls, | |||
size_t | nbThrs, | |||
size_t | nbStps | |||
) | [static] |
Simply reads from a pipe_circular into a plain container. This is basically the same as tst24MonoArchiver except that a circular is used instead of an archiver.
This pipe is initially shut. We will read its content and will not wait when it will be empty. There is no write access during the reads.
The output iterator must be protected because several sub-threads will write into it. The mutex can have any type and is independent of the mutex locking read accesses from the pipeline.
The type of the algorithm which reads the input data slices by slices (And not element by element, hence the range_step_type).
The output container must be limitless to contain the whole data.
Two different ranges are reading the same input This functor is started in the main thread. It starts its sub-threads.
This will exit when the result will be computed.
Using sets is necessary because several threads may insert the elements in a different order.
These containers must be identical.
static void tst24OneSubThr | ( | const Container & | lstDat, | |
typename Container::value_type | sumDat, | |||
size_t | nbDbls, | |||
size_t | nbThrs, | |||
size_t | szPipCirc | |||
) | [static] |
Only one subthread for the input algorithm.
The buffer is not big enough to store all the input data, but the main thread is running at the same time and reads from it.
Finite-size pipeline. There may not be enough room for the result of 'transform'.
This functor will be started in a subthread.
This is the thread tree containing just one top-level sub-thread.
This is the result of the detached execution of the functor in a sub-thread.
static void tst24OneSubThrRange | ( | const Container & | lstDat, | |
typename Container::value_type | sumDat, | |||
size_t | nbDbls, | |||
size_t | nbThrs, | |||
size_t | szPipCirc, | |||
size_t | nbStps | |||
) | [static] |
Only one subthread for the input algorithm. The buffer is not big enough to store all the input data, but the main thread is running at the same time and reads from it.
Finite-size pipeline. There may not be enough room to store the result of the 'transform'algorithm.
This functor will be started in a subthread.
This is the thread tree containing just one top-level sub-thread.
This is the result of the detached execution of the functor in a sub-thread.
static void tst24OutputInSubThr | ( | const Container & | lstDat, | |
typename Container::value_type | sumDat, | |||
size_t | nbDbls, | |||
size_t | nbThrs, | |||
size_t | szPipCirc, | |||
size_t | nbStps | |||
) | [static] |
This test is composed of a 'transform' algorithm, whose output is piped (circular-pipe) into a 'accumulate' algorithm. The accumulate algorithm runs in a sub-thread. The transform algorithm runs in a sub-thread too, which shuts the pipe at its end.
This pipeline is not shut at the beginning. It means that a reading thread will hang, until it is shut or not empty.
Now this sub-thread is waiting for data to be written in the pipe.
Execution of this functor, which now waits for all data written in the pipeline.
This functor will be started in a subthread.
And waits for the final result. This is a blocking call until the thread is 'joined'.
void tst24Thr | ( | size_t | nbE, | |
size_t | nbThrs | |||
) |
There are two imbricated loop on the containers type. The external container type is always limit-less. The internal one may have a limit and will therefore never used for infinite pipelines.