]>
Commit | Line | Data |
---|---|---|
37667812 VZ |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: samples/console/console.cpp | |
3 | // Purpose: a sample console (as opposed to GUI) progam using wxWindows | |
4 | // Author: Vadim Zeitlin | |
5 | // Modified by: | |
6 | // Created: 04.10.99 | |
7 | // RCS-ID: $Id$ | |
8 | // Copyright: (c) 1999 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr> | |
9 | // Licence: wxWindows license | |
10 | ///////////////////////////////////////////////////////////////////////////// | |
11 | ||
e87271f3 VZ |
12 | // ============================================================================ |
13 | // declarations | |
14 | // ============================================================================ | |
15 | ||
16 | // ---------------------------------------------------------------------------- | |
17 | // headers | |
18 | // ---------------------------------------------------------------------------- | |
19 | ||
37667812 VZ |
20 | #include <stdio.h> |
21 | ||
22 | #include <wx/string.h> | |
bbfa0322 | 23 | #include <wx/file.h> |
37667812 | 24 | #include <wx/app.h> |
e87271f3 VZ |
25 | |
26 | // ---------------------------------------------------------------------------- | |
27 | // conditional compilation | |
28 | // ---------------------------------------------------------------------------- | |
29 | ||
30 | // what to test? | |
378b05f7 VZ |
31 | |
32 | //#define TEST_ARRAYS | |
b568d04f | 33 | //#define TEST_LOG |
9fc3ad34 VZ |
34 | //#define TEST_STRINGS |
35 | #define TEST_THREADS | |
b76b015e | 36 | //#define TEST_TIME |
9fc3ad34 | 37 | //#define TEST_LONGLONG |
e87271f3 VZ |
38 | |
39 | // ============================================================================ | |
40 | // implementation | |
41 | // ============================================================================ | |
42 | ||
b76b015e VZ |
43 | // ---------------------------------------------------------------------------- |
44 | // long long | |
45 | // ---------------------------------------------------------------------------- | |
46 | ||
47 | #ifdef TEST_LONGLONG | |
48 | ||
49 | #include <wx/longlong.h> | |
50 | #include <wx/timer.h> | |
51 | ||
52 | static void TestSpeed() | |
53 | { | |
54 | static const long max = 100000000; | |
55 | long n; | |
9fc3ad34 | 56 | |
b76b015e VZ |
57 | { |
58 | wxStopWatch sw; | |
59 | ||
60 | long l = 0; | |
61 | for ( n = 0; n < max; n++ ) | |
62 | { | |
63 | l += n; | |
64 | } | |
65 | ||
66 | printf("Summing longs took %ld milliseconds.\n", sw.Time()); | |
67 | } | |
68 | ||
69 | { | |
70 | wxStopWatch sw; | |
71 | ||
72 | __int64 l = 0; | |
73 | for ( n = 0; n < max; n++ ) | |
74 | { | |
75 | l += n; | |
76 | } | |
77 | ||
78 | printf("Summing __int64s took %ld milliseconds.\n", sw.Time()); | |
79 | } | |
80 | ||
81 | { | |
82 | wxStopWatch sw; | |
83 | ||
84 | wxLongLong l; | |
85 | for ( n = 0; n < max; n++ ) | |
86 | { | |
87 | l += n; | |
88 | } | |
89 | ||
90 | printf("Summing wxLongLongs took %ld milliseconds.\n", sw.Time()); | |
91 | } | |
92 | } | |
93 | ||
94 | static void TestDivision() | |
95 | { | |
96 | wxLongLong ll = 0x38417388; // some number < LONG_MAX | |
97 | ||
98 | wxASSERT( (ll / 1000l)*1000l == ll ); | |
99 | } | |
100 | ||
101 | #endif // TEST_LONGLONG | |
102 | ||
103 | // ---------------------------------------------------------------------------- | |
104 | // date time | |
105 | // ---------------------------------------------------------------------------- | |
106 | ||
107 | #ifdef TEST_TIME | |
108 | ||
109 | #include <wx/datetime.h> | |
110 | ||
111 | #endif // TEST_TIME | |
112 | ||
e87271f3 VZ |
113 | // ---------------------------------------------------------------------------- |
114 | // threads | |
115 | // ---------------------------------------------------------------------------- | |
116 | ||
117 | #ifdef TEST_THREADS | |
118 | ||
bbfa0322 | 119 | #include <wx/thread.h> |
37667812 | 120 | |
bbfa0322 VZ |
121 | static size_t gs_counter = (size_t)-1; |
122 | static wxCriticalSection gs_critsect; | |
b568d04f | 123 | static wxCondition gs_cond; |
bbfa0322 | 124 | |
b568d04f | 125 | class MyJoinableThread : public wxThread |
bbfa0322 VZ |
126 | { |
127 | public: | |
b568d04f VZ |
128 | MyJoinableThread(size_t n) : wxThread(wxTHREAD_JOINABLE) |
129 | { m_n = n; Create(); } | |
bbfa0322 VZ |
130 | |
131 | // thread execution starts here | |
b568d04f | 132 | virtual ExitCode Entry(); |
bbfa0322 | 133 | |
b568d04f VZ |
134 | private: |
135 | size_t m_n; | |
bbfa0322 VZ |
136 | }; |
137 | ||
b568d04f | 138 | wxThread::ExitCode MyJoinableThread::Entry() |
bbfa0322 | 139 | { |
b568d04f VZ |
140 | unsigned long res = 1; |
141 | for ( size_t n = 1; n < m_n; n++ ) | |
142 | { | |
143 | res *= n; | |
144 | ||
145 | // it's a loooong calculation :-) | |
146 | Sleep(100); | |
147 | } | |
bbfa0322 | 148 | |
b568d04f | 149 | return (ExitCode)res; |
bbfa0322 VZ |
150 | } |
151 | ||
b568d04f VZ |
152 | class MyDetachedThread : public wxThread |
153 | { | |
154 | public: | |
9fc3ad34 | 155 | MyDetachedThread(size_t n, char ch) { m_n = n; m_ch = ch; Create(); } |
b568d04f VZ |
156 | |
157 | // thread execution starts here | |
158 | virtual ExitCode Entry(); | |
159 | ||
160 | // and stops here | |
161 | virtual void OnExit(); | |
162 | ||
163 | private: | |
9fc3ad34 VZ |
164 | size_t m_n; // number of characters to write |
165 | char m_ch; // character to write | |
b568d04f VZ |
166 | }; |
167 | ||
168 | wxThread::ExitCode MyDetachedThread::Entry() | |
bbfa0322 VZ |
169 | { |
170 | { | |
171 | wxCriticalSectionLocker lock(gs_critsect); | |
172 | if ( gs_counter == (size_t)-1 ) | |
173 | gs_counter = 1; | |
174 | else | |
175 | gs_counter++; | |
176 | } | |
177 | ||
9fc3ad34 | 178 | for ( size_t n = 0; n < m_n; n++ ) |
bbfa0322 VZ |
179 | { |
180 | if ( TestDestroy() ) | |
181 | break; | |
182 | ||
183 | putchar(m_ch); | |
184 | fflush(stdout); | |
185 | ||
186 | wxThread::Sleep(100); | |
187 | } | |
188 | ||
b568d04f | 189 | return 0; |
bbfa0322 VZ |
190 | } |
191 | ||
b568d04f | 192 | void MyDetachedThread::OnExit() |
bbfa0322 | 193 | { |
9fc3ad34 VZ |
194 | wxLogTrace("thread", "Thread %ld is in OnExit", GetId()); |
195 | ||
bbfa0322 | 196 | wxCriticalSectionLocker lock(gs_critsect); |
b568d04f VZ |
197 | if ( !--gs_counter ) |
198 | gs_cond.Signal(); | |
bbfa0322 VZ |
199 | } |
200 | ||
9fc3ad34 VZ |
201 | void TestDetachedThreads() |
202 | { | |
203 | puts("*** Testing detached threads ***"); | |
204 | ||
205 | static const size_t nThreads = 3; | |
206 | MyDetachedThread *threads[nThreads]; | |
207 | size_t n; | |
208 | for ( n = 0; n < nThreads; n++ ) | |
209 | { | |
210 | threads[n] = new MyDetachedThread(10, 'A' + n); | |
211 | } | |
212 | ||
213 | threads[0]->SetPriority(WXTHREAD_MIN_PRIORITY); | |
214 | threads[1]->SetPriority(WXTHREAD_MAX_PRIORITY); | |
215 | ||
216 | for ( n = 0; n < nThreads; n++ ) | |
217 | { | |
218 | threads[n]->Run(); | |
219 | } | |
220 | ||
221 | // wait until all threads terminate | |
222 | gs_cond.Wait(); | |
223 | ||
224 | puts(""); | |
225 | } | |
226 | ||
227 | void TestJoinableThreads() | |
228 | { | |
229 | puts("*** Testing a joinable thread (a loooong calculation...) ***"); | |
230 | ||
231 | // calc 10! in the background | |
232 | MyJoinableThread thread(10); | |
233 | thread.Run(); | |
234 | ||
235 | printf("\nThread terminated with exit code %lu.\n", | |
236 | (unsigned long)thread.Wait()); | |
237 | } | |
238 | ||
239 | void TestThreadSuspend() | |
240 | { | |
241 | MyDetachedThread *thread = new MyDetachedThread(30, 'X'); | |
242 | ||
243 | thread->Run(); | |
244 | ||
245 | // this is for this demo only, in a real life program we'd use another | |
246 | // condition variable which would be signaled from wxThread::Entry() to | |
247 | // tell us that the thread really started running - but here just wait a | |
248 | // bit and hope that it will be enough (the problem is, of course, that | |
249 | // the thread might still not run when we call Pause() which will result | |
250 | // in an error) | |
251 | wxThread::Sleep(300); | |
252 | ||
253 | for ( size_t n = 0; n < 3; n++ ) | |
254 | { | |
255 | thread->Pause(); | |
256 | ||
257 | puts("\nThread suspended"); | |
258 | if ( n > 0 ) | |
259 | { | |
260 | // don't sleep but resume immediately the first time | |
261 | wxThread::Sleep(300); | |
262 | } | |
263 | puts("Going to resume the thread"); | |
264 | ||
265 | thread->Resume(); | |
266 | } | |
267 | ||
268 | // wait until the thread terminates | |
269 | gs_cond.Wait(); | |
270 | ||
271 | puts(""); | |
272 | } | |
273 | ||
e87271f3 VZ |
274 | #endif // TEST_THREADS |
275 | ||
276 | // ---------------------------------------------------------------------------- | |
277 | // arrays | |
278 | // ---------------------------------------------------------------------------- | |
279 | ||
280 | #ifdef TEST_ARRAYS | |
281 | ||
282 | void PrintArray(const char* name, const wxArrayString& array) | |
283 | { | |
284 | printf("Dump of the array '%s'\n", name); | |
285 | ||
286 | size_t nCount = array.GetCount(); | |
287 | for ( size_t n = 0; n < nCount; n++ ) | |
288 | { | |
289 | printf("\t%s[%u] = '%s'\n", name, n, array[n].c_str()); | |
290 | } | |
291 | } | |
292 | ||
293 | #endif // TEST_ARRAYS | |
294 | ||
9fc3ad34 VZ |
295 | // ---------------------------------------------------------------------------- |
296 | // strings | |
297 | // ---------------------------------------------------------------------------- | |
298 | ||
299 | #ifdef TEST_STRINGS | |
300 | ||
301 | #include "wx/timer.h" | |
302 | ||
303 | void TestString() | |
304 | { | |
305 | wxStopWatch sw; | |
306 | ||
307 | wxString a, b, c; | |
308 | ||
309 | a.reserve (128); | |
310 | b.reserve (128); | |
311 | c.reserve (128); | |
312 | ||
313 | for (int i = 0; i < 1000000; ++i) | |
314 | { | |
315 | a = "Hello"; | |
316 | b = " world"; | |
317 | c = "! How'ya doin'?"; | |
318 | a += b; | |
319 | a += c; | |
320 | c = "Hello world! What's up?"; | |
321 | if (c != a) | |
322 | c = "Doh!"; | |
323 | } | |
324 | ||
325 | printf ("TestString elapsed time: %ld\n", sw.Time()); | |
326 | } | |
327 | ||
328 | void TestPChar() | |
329 | { | |
330 | wxStopWatch sw; | |
331 | ||
332 | char a [128]; | |
333 | char b [128]; | |
334 | char c [128]; | |
335 | ||
336 | for (int i = 0; i < 1000000; ++i) | |
337 | { | |
338 | strcpy (a, "Hello"); | |
339 | strcpy (b, " world"); | |
340 | strcpy (c, "! How'ya doin'?"); | |
341 | strcat (a, b); | |
342 | strcat (a, c); | |
343 | strcpy (c, "Hello world! What's up?"); | |
344 | if (strcmp (c, a) == 0) | |
345 | strcpy (c, "Doh!"); | |
346 | } | |
347 | ||
348 | printf ("TestPChar elapsed time: %ld\n", sw.Time()); | |
349 | } | |
350 | ||
351 | #endif // TEST_STRINGS | |
352 | ||
e87271f3 VZ |
353 | // ---------------------------------------------------------------------------- |
354 | // entry point | |
355 | // ---------------------------------------------------------------------------- | |
356 | ||
bbfa0322 | 357 | int main(int argc, char **argv) |
37667812 VZ |
358 | { |
359 | if ( !wxInitialize() ) | |
360 | { | |
361 | fprintf(stderr, "Failed to initialize the wxWindows library, aborting."); | |
362 | } | |
363 | ||
9fc3ad34 VZ |
364 | #ifdef TEST_STRINGS |
365 | TestPChar(); | |
366 | TestString(); | |
367 | #endif // TEST_STRINGS | |
368 | ||
e87271f3 VZ |
369 | #ifdef TEST_ARRAYS |
370 | wxArrayString a1; | |
371 | a1.Add("tiger"); | |
372 | a1.Add("cat"); | |
373 | a1.Add("lion"); | |
374 | a1.Add("dog"); | |
375 | a1.Add("human"); | |
376 | a1.Add("ape"); | |
377 | ||
378 | puts("*** Initially:"); | |
379 | ||
380 | PrintArray("a1", a1); | |
381 | ||
382 | wxArrayString a2(a1); | |
383 | PrintArray("a2", a2); | |
384 | ||
385 | wxSortedArrayString a3(a1); | |
386 | PrintArray("a3", a3); | |
387 | ||
388 | puts("*** After deleting a string from a1"); | |
389 | a1.Remove(2); | |
390 | ||
391 | PrintArray("a1", a1); | |
392 | PrintArray("a2", a2); | |
393 | PrintArray("a3", a3); | |
394 | ||
395 | puts("*** After reassigning a1 to a2 and a3"); | |
396 | a3 = a2 = a1; | |
397 | PrintArray("a2", a2); | |
398 | PrintArray("a3", a3); | |
399 | #endif // TEST_ARRAYS | |
400 | ||
378b05f7 VZ |
401 | #ifdef TEST_LOG |
402 | wxString s; | |
403 | for ( size_t n = 0; n < 8000; n++ ) | |
404 | { | |
405 | s << (char)('A' + (n % 26)); | |
406 | } | |
407 | ||
408 | wxString msg; | |
409 | msg.Printf("A very very long message: '%s', the end!\n", s.c_str()); | |
410 | ||
411 | // this one shouldn't be truncated | |
412 | printf(msg); | |
413 | ||
414 | // but this one will because log functions use fixed size buffer | |
b568d04f VZ |
415 | // (note that it doesn't need '\n' at the end neither - will be added |
416 | // by wxLog anyhow) | |
417 | wxLogMessage("A very very long message 2: '%s', the end!", s.c_str()); | |
378b05f7 VZ |
418 | #endif // TEST_LOG |
419 | ||
e87271f3 | 420 | #ifdef TEST_THREADS |
9fc3ad34 VZ |
421 | if ( argc > 1 && argv[1][0] == 't' ) |
422 | wxLog::AddTraceMask("thread"); | |
b568d04f | 423 | |
9fc3ad34 VZ |
424 | TestThreadSuspend(); |
425 | if ( 0 ) | |
bbfa0322 | 426 | { |
9fc3ad34 VZ |
427 | TestDetachedThreads(); |
428 | TestJoinableThreads(); | |
bbfa0322 | 429 | } |
e87271f3 | 430 | #endif // TEST_THREADS |
37667812 | 431 | |
b76b015e VZ |
432 | #ifdef TEST_LONGLONG |
433 | if ( 0 ) | |
434 | TestSpeed(); | |
435 | if ( 1 ) | |
436 | TestDivision(); | |
437 | #endif // TEST_LONGLONG | |
438 | ||
439 | #ifdef TEST_TIME | |
440 | wxDateTime time = wxDateTime::Now(); | |
441 | printf("Current time: '%s', current year %u is %sa leap one", | |
442 | time.Format().c_str(), | |
443 | time.GetYear(), | |
444 | wxDateTime::IsLeapYear(time.GetYear()) ? "" : "not"); | |
445 | #endif // TEST_TIME | |
446 | ||
37667812 VZ |
447 | wxUninitialize(); |
448 | ||
449 | return 0; | |
450 | } |