#include <assert.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <deque>
#include <vector>
#include <set>
#include <list>
#include <rpa/platforms.h>
#include <rpa/algorithms/transform.h>
#include <rpa/testing.h>
Classes | |
class | DataT |
struct | Char2Data |
This functor will be applied to each argument of the command line. More... | |
class | t_nobuf< ThrTree > |
Test without output buffer, but with a mutex to protect the output. More... | |
class | t_unbounded_noall< ThrTree > |
class | t_unbounded_alloc< ThrTree, IterBuf > |
Test with an output buffer of unlimited size. More... | |
class | t_bounded_noall< ThrTree > |
class | t_bounded_alloc< ThrTree, IterBuf > |
Defines | |
#define | NB_THR 128 |
General purpose macros. | |
#define | NB_SAMPLES ( 100000 * TST_RATIO ) |
#define | TST_BUF_SZ 43 |
Typedefs | |
typedef rpa::testing_mutex | mtx_t |
typedef vector< DataT > | VecDataT |
typedef back_insert_iterator< VecDataT > | BackInsT |
Functions | |
template<class ThrTree> | |
t_nobuf< ThrTree > | make_nobuf (ThrTree aThrTree) |
template<class ThrTree> | |
t_unbounded_noall< ThrTree > | make_unbounded_noall (ThrTree aThrTree) |
template<class ThrTree, class IterBuf> | |
t_unbounded_alloc< ThrTree, IterBuf > | make_unbounded_alloc (ThrTree aThrTree, IterBuf aIterBuf) |
template<class ThrTree> | |
t_bounded_noall< ThrTree > | make_bounded_noall (ThrTree aThrTree, size_t aBufSz) |
template<class ThrTree, class IterBuf> | |
t_bounded_alloc< ThrTree, IterBuf > | make_bounded_alloc (ThrTree aThrTree, size_t aBufSz, IterBuf aIterBuf) |
static void | CompareUntilEnd (size_t aArgC, const char *const *aArgV, const VecDataT &aVecStr) |
template<class Functor> | |
static void | Cmp (int aArgC, const char *const *aArgV, Functor aFunc) |
Tries with various input container types. | |
static list< vector< DataT > > | myLstVecBuf (NB_THR) |
static vector< list< DataT > > | myVecLstBuf (NB_THR) |
template<class ThrTree> | |
static void | mainInternMtx (int aArgC, const char *const *aArgV, size_t aBufSz, ThrTree aThrTree) |
Tests the various output sequences configurations. | |
static void | mainIntern (int aArgC, const char *const *aArgV, size_t aBufSz) |
int | main (int aArgC, const char **aArgV) |
Loops on internal data and on the command line. | |
Variables | |
static rpa::testing_thread | myPosixThr [NB_THR] |
mtx_t | myMtx |
All-purpose mutex used everywhere in many places of this test program. | |
static DataT | tstBufGood [NB_SAMPLES] |
This buffer is used for storing the good result. | |
static DataT | tstBufTest [NB_SAMPLES] |
This buffer is used for storing the result to be tested. | |
static DataT | myArrArrBuf [NB_THR][TST_BUF_SZ] |
static deque< DataT > | myArrDeqBuf [NB_THR] |
static char | myStr [NB_SAMPLES][RPA_INT_STR] |
static char * | myPtr [NB_SAMPLES] |
This array is global because it is too big to be allocated on the stack. |
#define NB_SAMPLES ( 100000 * TST_RATIO ) |
We want to have many elements because it helps detecting race conditions. The duration of tests can be adjusted.
#define NB_THR 128 |
General purpose macros.
Our thread pool. The threads are 'create'-d by the algorithm. A excessively big number of thread is used, for testing purpose. On Cygwin, it does not work by default with thousand threads.
#define TST_BUF_SZ 43 |
The size of fixed-size buffers. This stores integers written in text. Any size should work.
typedef rpa::testing_mutex mtx_t |
Tests are done with different mutex for the input and the output, but also with the same one, to prove that using the same mutex does not imply a deadlock. A dependency between these two mutex may happen because the user has the possibility to use any datatype as a mutex. And some external resources may have unpredictable side effects.
static void Cmp | ( | int | aArgC, | |
const char *const * | aArgV, | |||
Functor | aFunc | |||
) | [static] |
Tries with various input container types.
static void CompareUntilEnd | ( | size_t | aArgC, | |
const char *const * | aArgV, | |||
const VecDataT & | aVecStr | |||
) | [static] |
If there is no mutex, this means we must test with a range_step, an input sequence for dynamic scheduling policy, without mutex, which means that it is based on atomic data types. This stops the program if there is an error.
int main | ( | int | aArgC, | |
const char ** | aArgV | |||
) |
Loops on internal data and on the command line.
There must be sorted with string order.
Tries the algorithm with various number of elements, much smaller and much bigger than the number of threads and the size of buffers. We do not try all possible numbers of elements, because it would take ages to run. The maximum number of elements is divided by eight at each loop.
Different buffer sizes
static void mainIntern | ( | int | aArgC, | |
const char *const * | aArgV, | |||
size_t | aBufSz | |||
) | [static] |
Run the tests with several mutex for the input :
Intentionaly try first a zero number of threads. With zero threads, it must work in plain sequential mode. The number of threads is multiplied by four at each loop.
static void mainInternMtx | ( | int | aArgC, | |
const char *const * | aArgV, | |||
size_t | aBufSz, | |||
ThrTree | aThrTree | |||
) | [static] |
Tests the various output sequences configurations.
It is impossible to make unlimited-size buffering, with a fixed size buffer. Therefore, this simply does not compile. Cmp( aArgC, aArgV, make_unbounded_alloc(aThrTree, myArrArrBuf ) );
Unbounded buffer
Bounded buffer.
Without output buffer.
t_bounded_alloc< ThrTree, IterBuf > make_bounded_alloc | ( | ThrTree | aThrTree, | |
size_t | aBufSz, | |||
IterBuf | aIterBuf | |||
) |
t_bounded_noall< ThrTree > make_bounded_noall | ( | ThrTree | aThrTree, | |
size_t | aBufSz | |||
) |
t_nobuf< ThrTree > make_nobuf | ( | ThrTree | aThrTree | ) |
t_unbounded_alloc< ThrTree, IterBuf > make_unbounded_alloc | ( | ThrTree | aThrTree, | |
IterBuf | aIterBuf | |||
) |
t_unbounded_noall< ThrTree > make_unbounded_noall | ( | ThrTree | aThrTree | ) |
static list< vector< DataT > > myLstVecBuf | ( | NB_THR | ) | [static] |
static vector< list< DataT > > myVecLstBuf | ( | NB_THR | ) | [static] |
DataT myArrArrBuf[NB_THR][TST_BUF_SZ] [static] |
Different types of buffer 'bags' are used. We try not to use typedefs, to make code samples lighter and shorter. These are simply fixed-size arrays of static or dynamic buffers. It is not a problem to put buffers in fixed size arrays, because the maximum number of threads is small. Anyway, buffers can be put in any sort of container, as long as it has a STL-like iterator.
deque< DataT > myArrDeqBuf[NB_THR] [static] |
rpa::testing_thread myPosixThr[NB_THR] [static] |
char* myPtr[NB_SAMPLES] [static] |
This array is global because it is too big to be allocated on the stack.
char myStr[NB_SAMPLES][RPA_INT_STR] [static] |
Setup a buffer of random strings. These two arrays are defined are global because they are too big to be allocated on the stack.
DataT tstBufGood[NB_SAMPLES] [static] |
This buffer is used for storing the good result.
DataT tstBufTest[NB_SAMPLES] [static] |
This buffer is used for storing the result to be tested.