Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
21.string.cons.mt.cpp
Go to the documentation of this file.
1
30#include <string> // for string
31
32#include <cstddef> // for size_t
33
34#include <rw_driver.h> // for rw_test()
35#include <rw_thread.h> // for rw_thread_pool(), ...
36#include <rw_valcmp.h> // for rw_strncmp()
37
38
40#define MAX_THREADS 32
41#define MAX_LOOPS 100000
42
43const char* const
44data [] = {
45 /* 0 */ "",
46 /* 1 */ "a",
47 /* 2 */ "bc",
48 /* 3 */ "cde",
49 /* 4 */ "defg",
50 /* 5 */ "efghi",
51 /* 6 */ "fghijk",
52 /* 7 */ "ghijklm"
53};
54
55const std::size_t
56nstrings = sizeof data / sizeof *data;
57
58const std::string
60 data [0], data [1], data [2], data [3],
61 data [4], data [5], data [6], data [7]
62};
63
64
65#ifndef _RWSTD_NO_WCHAR_T
66
67const wchar_t* const
68wdata [] = {
69 /* 0 */ L"",
70 /* 1 */ L"a",
71 /* 2 */ L"bc",
72 /* 3 */ L"cde",
73 /* 4 */ L"defg",
74 /* 5 */ L"efghi",
75 /* 6 */ L"fghijk",
76 /* 7 */ L"ghijklm"
77};
78
79const std::wstring
81 wdata [0], wdata [1], wdata [2], wdata [3],
82 wdata [4], wdata [5], wdata [6], wdata [7]
83};
84
85#endif // _RWSTD_NO_WCHAR_T
86
87
89#ifdef _RWSTD_REENTRANT
90int rw_opt_nthreads = 4;
91#else // if !defined (_RWSTD_REENTRANT)
92// in non-threaded builds use just one thread
94#endif // _RWSTD_REENTRANT
95
96// the number of times each thread should iterate
98
99
100template <class T>
101void
102test_string_cons (const T* const *pdata,
103 const std::basic_string<T> *pshared,
104 std::size_t threadno)
105{
106 typedef std::basic_string<T> String;
107
108 for (std::size_t i = 0; i != std::size_t (rw_opt_nloops); ++i) {
109
110 const std::size_t inx1 = (i + threadno) % nstrings;
111 const std::size_t inx2 = (inx1 + 1) % nstrings;
112
113 // create a copy of the global string
114 const String copy (pshared [inx1]);
115
116 String assigned (pshared [inx2]);
117
118 {
119 // create another copy of the same global string
120 const String copy2 (pshared [inx1]);
121
122 // verify that this copy has the expected length...
123 RW_ASSERT (pshared [inx1].length () == copy2.length ());
124
125 // ...and the expected data
126 RW_ASSERT (0 == rw_strncmp (pdata [inx1], copy2.data ()));
127
128 assigned = pshared [inx1];
129
130 // copy2 gets destroyed...
131 }
132
133 // verify that local copy has the expected length...
134 RW_ASSERT (pshared [inx1].length () == copy.length ());
135
136 // ...and the expected data
137 RW_ASSERT (0 == rw_strncmp (pdata [inx1], copy.data ()));
138
139 // verify that assigned string has the expected length...
140 RW_ASSERT (pshared [inx1].length () == assigned.length ());
141
142 // ...and the expected data
143 RW_ASSERT (0 == rw_strncmp (pdata [inx1], assigned.data ()));
144
145 // reassign and verify again
146 assigned = pdata [inx2];
147
148 RW_ASSERT (pshared [inx2].length () == assigned.length ());
149 RW_ASSERT (0 == rw_strncmp (pdata [inx2], assigned.data ()));
150 }
151
152}
153
154
155extern "C" {
156
158
159static void*
160thread_func (void *arg)
161{
162 const rw_thread_t* const pthread = (rw_thread_t*)arg;
163
164 // get the 0-based thread number
165 const std::size_t threadno = std::size_t (pthread->threadno);
166
167 if (test_wstring) {
168
169#ifndef _RWSTD_NO_WCHAR_T
170
171 test_string_cons<wchar_t>(wdata, wshared, threadno);
172
173#endif // _RWSTD_NO_WCHAR_T
174
175 }
176 else {
177 test_string_cons (data, shared, threadno);
178 }
179
180 return 0;
181}
182
183} // extern "C"
184
185
187static int
188run_test (int, char**)
189{
190 rw_info (0, 0, 0,
191 "testing std::string with %d thread%{?}s%{;}, "
192 "%d iteration%{?}s%{;} each",
195
196 test_wstring = false;
197
198 // create and start a pool of threads and wait for them to finish
199 int result =
200 rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0);
201
202 rw_error (result == 0, 0, __LINE__,
203 "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
204 rw_opt_nthreads, thread_func);
205
206 for (std::size_t i = 0; i != nstrings; ++i) {
207
208 const std::size_t size =
209 std::string::traits_type::length (data [i]);
210
211 rw_assert (size == shared [i].size (), 0, 0,
212 "shared string modifed from %#s to %{#S}",
213 data [i], &shared [i]);
214 }
215
216#ifndef _RWSTD_NO_WCHAR_T
217
218 rw_info (0, 0, 0,
219 "testing std::wstring with %d thread%{?}s%{;}, "
220 "%d iteration%{?}s%{;} each",
223
224 test_wstring = true;
225
226 // start a pool of threads to exercise wstring thread safety
227 result =
228 rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0);
229
230 rw_error (result == 0, 0, __LINE__,
231 "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
232 rw_opt_nthreads, thread_func);
233
234 for (std::size_t i = 0; i != nstrings; ++i) {
235
236 const std::size_t size =
237 std::wstring::traits_type::length (wdata [i]);
238
239 rw_assert (size == wshared [i].size (), 0, 0,
240 "shared string modifed from %#ls to %{#lS}",
241 wdata [i], &wshared [i]);
242 }
243
244#endif // _RWSTD_NO_WCHAR_T
245
246 return result;
247}
248
249
251int main (int argc, char *argv[])
252{
253 return rw_test (argc, argv, __FILE__,
254 "lib.string.cons",
255 "thread safety", run_test,
256 "|-nloops#0 " // must be non-negative
257 "|-nthreads#0-*", // must be in [0, MAX_THREADS]
259 int (MAX_THREADS),
261}
#define i
Definition 17.names.cpp:126
#define T
Definition 17.names.cpp:163
volatile int result
void test_string_cons(const T *const *pdata, const std::basic_string< T > *pshared, std::size_t threadno)
const std::string shared[nstrings]
const wchar_t *const wdata[]
int rw_opt_nthreads
const std::size_t nstrings
bool test_wstring
#define MAX_THREADS
const std::wstring wshared[nstrings]
const char *const data[]
#define MAX_LOOPS
int rw_opt_nloops
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
#define main
_TEST_EXPORT int rw_test(int argc, char *argv[], const char *filename, const char *clause, const char *comment, int(*testfun)(int, char **), const char *optspec,...)
_TEST_EXPORT int rw_info(int, const char *, int, const char *,...)
Definition driver.cpp:1681
_TEST_EXPORT int rw_assert(int, const char *, int, const char *,...)
Definition driver.cpp:1630
_TEST_EXPORT int rw_error(int, const char *, int, const char *,...)
Definition driver.cpp:1613
#define RW_ASSERT(expr)
_TEST_EXPORT int rw_thread_pool(rw_thread_t *, _RWSTD_SIZE_T, rw_thread_attr_t *, rw_thread_proc *, void **, _RWSTD_SIZE_T=0)
_TEST_EXPORT int rw_strncmp(const char *, const char *, _RWSTD_SIZE_T=_RWSTD_SIZE_MAX, int=CMP_NULTERM)
long threadno
Definition rw_thread.h:43
int arg
Definition locale.cpp:2806