update dev300-m58
[ooovba.git] / sal / qa / osl / semaphore / osl_Semaphore.cxx
blob0e2ec5d84a83d36645918a0f30b00a86120636a1
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: osl_Semaphore.cxx,v $
10 * $Revision: 1.7 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sal.hxx"
34 //------------------------------------------------------------------------
35 // include files
36 //------------------------------------------------------------------------
37 #include <osl_Semaphore_Const.h>
39 using namespace osl;
40 using namespace rtl;
43 //------------------------------------------------------------------------
44 // helper functions and classes
45 //------------------------------------------------------------------------
47 /** print Boolean value.
49 inline void printBool( sal_Bool bOk )
51 t_print("#printBool# " );
52 ( sal_True == bOk ) ? t_print("YES!\n" ): t_print("NO!\n" );
55 /** print a UNI_CODE String.
57 inline void printUString( const ::rtl::OUString & str )
59 rtl::OString aString;
61 t_print("#printUString_u# " );
62 aString = ::rtl::OUStringToOString( str, RTL_TEXTENCODING_ASCII_US );
63 t_print("%s\n", aString.getStr( ) );
66 /** wait _nSec seconds.
68 void thread_sleep( sal_Int32 _nSec )
70 /// print statement in thread process must use fflush() to force display.
71 // t_print("wait %d seconds. ", _nSec );
72 // fflush( stdout );
74 #ifdef WNT //Windows
75 Sleep( _nSec * 1000 );
76 #endif
77 #if ( defined UNX ) || ( defined OS2 ) //Unix
78 sleep( _nSec );
79 #endif
82 void thread_sleep_tenth_sec(sal_Int32 _nTenthSec)
84 #ifdef WNT //Windows
85 Sleep(_nTenthSec * 100 );
86 #endif
87 #if ( defined UNX ) || ( defined OS2 ) //Unix
88 TimeValue nTV;
89 nTV.Seconds = static_cast<sal_uInt32>( _nTenthSec/10 );
90 nTV.Nanosec = ( (_nTenthSec%10 ) * 100000000 );
91 osl_waitThread(&nTV);
92 #endif
95 /** thread for testing Semaphore acquire.
97 class HoldThread : public Thread
99 public:
100 //get the Semaphores to operate
101 HoldThread( ::osl::Semaphore& Sem ): MySem( Sem ) { }
103 ~HoldThread( )
105 CPPUNIT_ASSERT_MESSAGE( "#HoldThread does not shutdown properly.\n", sal_False == this -> isRunning( ) );
107 protected:
108 ::osl::Semaphore& MySem;
110 void SAL_CALL run()
112 // block here if it tries to decrease below zero.
113 MySem.acquire( );
114 t_print("Semaphore acquired. \n" );
115 MySem.release( );
119 /** thread for testing Semaphore release and tryToAcquire.
121 class WaitThread : public Thread
123 public:
124 //get the Semaphore pointer to operate
125 WaitThread( ::osl::Semaphore& Sem ): MySem( Sem ) { }
127 ~WaitThread( )
129 CPPUNIT_ASSERT_MESSAGE( "WaitThread does not shutdown properly.\n", sal_False == this -> isRunning( ) );
131 protected:
132 Semaphore& MySem;
134 void SAL_CALL run( )
136 // block here if the semaphore has been acquired
137 MySem.acquire( );
138 thread_sleep_tenth_sec( 2 );
139 MySem.release( );
143 /** thread for producer-consumer model.
145 #define BSIZE 50
146 class SemBuffer
148 public:
149 sal_Int32 Buf[BSIZE];
150 ::osl::Semaphore& aSemOccupied;
151 ::osl::Semaphore& aSemEmpty;
152 ::osl::Mutex& aMutex;
154 SemBuffer( ::osl::Semaphore& Sem, ::osl::Semaphore& Sem1, ::osl::Mutex& Mut )
155 :aSemOccupied( Sem ), aSemEmpty( Sem1 ), aMutex( Mut )
157 for ( sal_Int8 iCount=0; iCount < BSIZE; iCount++ )
158 Buf[iCount] = 0;
162 class WriterThread : public Thread
164 public:
165 //get the Semaphores to operate
166 WriterThread( SemBuffer& aSemBuffer ): MySemBuffer( aSemBuffer ){ }
168 ~WriterThread( )
170 CPPUNIT_ASSERT_MESSAGE( "WriterThread does not shutdown properly.\n", sal_False == this -> isRunning( ) );
172 protected:
173 SemBuffer& MySemBuffer;
175 void SAL_CALL run( )
177 for ( sal_Int32 iCount = 0; iCount < BSIZE; iCount++ )
179 MySemBuffer.aSemEmpty.acquire( ) ;
180 MySemBuffer.aMutex.acquire( ) ;
181 MySemBuffer.Buf[iCount] = iCount;
182 MySemBuffer.aMutex.release( ) ;
183 MySemBuffer.aSemOccupied.release( ) ;
188 class ReaderThread : public Thread
190 public:
191 //get the Semaphores to operate
192 ReaderThread( SemBuffer& aSemBuffer ): MySemBuffer( aSemBuffer ){ }
194 ~ReaderThread( )
196 CPPUNIT_ASSERT_MESSAGE( "ReaderThread does not shutdown properly.\n", sal_False == this -> isRunning( ) );
199 protected:
200 SemBuffer& MySemBuffer;
202 void SAL_CALL run( )
204 for ( sal_Int32 iCount = 0; iCount < BSIZE; iCount++ )
206 MySemBuffer.aSemOccupied.acquire( ) ;
207 MySemBuffer.aMutex.acquire( ) ;
208 MySemBuffer.Buf[iCount] *= MySemBuffer.Buf[iCount];
209 MySemBuffer.aMutex.release( ) ;
210 MySemBuffer.aSemEmpty.release( ) ;
217 //------------------------------------------------------------------------
218 // test code start here
219 //------------------------------------------------------------------------
221 namespace osl_Semaphore
224 /** testing the method:
225 Semaphore(sal_uInt32 initialCount);
227 class ctors : public CppUnit::TestFixture
229 public:
230 sal_Bool bRes, bRes1;
232 void ctors_001( )
234 ::osl::Semaphore aSem(sal_uInt32(0));
235 bRes = aSem.tryToAcquire( );
237 CPPUNIT_ASSERT_MESSAGE( "#test comment#: create semaphore with initialCount = 0. the first acquire will block.",
238 sal_False == bRes );
241 void ctors_002( )
243 ::osl::Semaphore aSem(sal_uInt32(1));
244 bRes = aSem.tryToAcquire( );
245 if ( sal_True == bRes )
246 aSem.release( );
248 CPPUNIT_ASSERT_MESSAGE( "#test comment#: create semaphore with initialCount = 1. the first acquire will not block.",
249 sal_True == bRes );
252 void ctors_003( )
254 ::osl::Semaphore aSem(sal_uInt32(1));
255 bRes = aSem.tryToAcquire( );
256 bRes1 = aSem.tryToAcquire( );
258 CPPUNIT_ASSERT_MESSAGE( "#test comment#: create semaphore with initialCount = 1. acquire twice will cause block.",
259 sal_True == bRes && sal_False == bRes1);
262 void ctors_004( )
264 oslSemaphore hSem = new ::osl::Semaphore(sal_uInt32(1));
266 CPPUNIT_ASSERT_MESSAGE( "#test comment#: test return value of the constructor, it should not be NULL.",
267 NULL != hSem );
270 void ctors_005( )
272 ::osl::Semaphore aSemaphore(sal_uInt32(2));
273 bRes = aSemaphore.tryToAcquire( )&&
274 aSemaphore.tryToAcquire( )&&
275 !aSemaphore.tryToAcquire( );
277 CPPUNIT_ASSERT_MESSAGE( "#test comment#: create semaphore with initialCount = 2. guess what behaviour will the semaphore act like.",
278 sal_True == bRes );
281 CPPUNIT_TEST_SUITE( ctors );
282 CPPUNIT_TEST( ctors_001 );
283 CPPUNIT_TEST( ctors_002 );
284 CPPUNIT_TEST( ctors_003 );
285 CPPUNIT_TEST( ctors_004 );
286 CPPUNIT_TEST( ctors_005 );
287 CPPUNIT_TEST_SUITE_END( );
288 }; // class ctors
291 /** testing the method:
292 sal_Bool acquire();
294 class acquire : public CppUnit::TestFixture
296 public:
297 sal_Bool bRes, bRes1, bRes2;
299 /** tester comment:
300 acquire semaphore in main thread, and then call acquire again in myThread,
301 the child thread should block, wait 2 secs, it still block. Then release
302 semaphore in main thread, the child thread could return from acquire, and
303 go to exec next statement, so could terminate quickly.
306 void acquire_001( )
308 // launch the child thread
309 ::osl::Semaphore aSemaphore(1);
310 bRes = aSemaphore.acquire( );
311 HoldThread myThread( aSemaphore );
312 myThread.create( );
314 // if acquire in myThread does not work, 2 secs is long enough,
315 // myThread should terminate now, and bRes1 should be sal_False
316 thread_sleep_tenth_sec( 2 );
317 bRes1 = myThread.isRunning( );
319 // after release semaphore, myThread stops blocking and will terminate immediately
320 aSemaphore.release( );
321 thread_sleep_tenth_sec( 1 );
322 bRes2 = myThread.isRunning( );
323 myThread.join( );
325 CPPUNIT_ASSERT_MESSAGE( "#test comment#: test acquire of Semaphore.",
326 bRes == sal_True && bRes1 == sal_True && bRes2 == sal_False );
329 /** tester comment:
330 launch 3 thread for testing acquirement inter-process.
333 void acquire_002( )
335 // launch three child threads
336 ::osl::Semaphore aSemaphore(1);
337 bRes = aSemaphore.acquire( );
338 HoldThread myThread1( aSemaphore );
339 myThread1.create( );
340 HoldThread myThread2( aSemaphore );
341 myThread2.create( );
342 HoldThread myThread3( aSemaphore );
343 myThread3.create( );
345 // if acquire in myThread does not work, 2 secs is long enough,
346 thread_sleep_tenth_sec( 2 );
347 bRes1 = myThread1.isRunning( ) && myThread2.isRunning( ) && myThread3.isRunning( );
349 // after release semaphore, myThread stops blocking and will terminate immediately
350 aSemaphore.release( );
351 thread_sleep_tenth_sec( 1 );
352 bRes2 = myThread1.isRunning( ) || myThread2.isRunning( ) || myThread3.isRunning( );
353 myThread1.join( );
354 myThread2.join( );
355 myThread3.join( );
357 CPPUNIT_ASSERT_MESSAGE( "#test comment#: test acquire of Semaphore in multithreaded environment.",
358 bRes == sal_True && bRes1 == sal_True && bRes2 == sal_False );
363 /** tester comment:
364 launch 3 thread for testing acquirement inter-process. in this test,
365 we use two threads as producer and consumer, operate together on an
366 array which is initialized to 0 for every item. producer takes action
367 as follow:
368 p(A), p(M), Buf[i]=i, v(M), v(B).
369 consumer's action is like:
370 p(B), p(M), Buf[i]=Buf[i]*Buf[i], v(M), v(A).
371 consumer must operate on the array after producer does sequetially,
372 otherwise, the array will contain items remain zero after all threads
373 terminate. array will be filled with index^2 in the end.
376 void acquire_003( )
378 // initialization.
379 ::osl::Semaphore aSemOccupied( sal_uInt32(0) );
380 ::osl::Semaphore aSemEmpty( BSIZE );
381 ::osl::Mutex aMutex;
383 // launch two threads.
384 SemBuffer aBuffer( aSemOccupied, aSemEmpty, aMutex );
385 WriterThread myThread1( aBuffer );
386 ReaderThread myThread2( aBuffer );
387 myThread1.create( );
388 myThread2.create( );
390 myThread1.join( );
391 myThread2.join( );
393 bRes = sal_True;
394 for ( sal_Int32 iCount = 0; iCount < BSIZE; iCount++ )
395 bRes = bRes && ( aBuffer.Buf[iCount] == iCount*iCount );
397 CPPUNIT_ASSERT_MESSAGE( "#test comment#: test acquire of Semaphore using Producer-Consumer model.",
398 sal_True == bRes );
401 CPPUNIT_TEST_SUITE( acquire );
402 CPPUNIT_TEST( acquire_001 );
403 CPPUNIT_TEST( acquire_002 );
404 CPPUNIT_TEST( acquire_003 );
405 CPPUNIT_TEST_SUITE_END( );
406 }; // class acquire
409 /** testing the method:
410 sal_Bool tryToAcquire();
412 class tryToAcquire : public CppUnit::TestFixture
414 public:
415 sal_Bool bRes, bRes1, bRes2;
416 /** tester comment:
417 First let child thread acquire the semaphore, and wait 2 secs, during the 2 secs,
418 in main thread, tryToAcquire semaphore should return False, then after the
419 child thread terminated, tryToAcquire should return True
421 void tryToAcquire_001()
423 ::osl::Semaphore aSemaphore(1);
424 WaitThread myThread( aSemaphore );
425 myThread.create();
427 // ensure the child thread acquire the semaphore
428 thread_sleep_tenth_sec(1);
429 bRes1 = aSemaphore.tryToAcquire();
431 if (bRes1 == sal_True)
432 aSemaphore.release();
433 // wait the child thread terminate
434 myThread.join();
436 bRes2 = aSemaphore.tryToAcquire();
437 if (bRes2 == sal_True)
438 aSemaphore.release();
440 CPPUNIT_ASSERT_MESSAGE("#test comment#: Try to acquire Semaphore",
441 bRes1 == sal_False && bRes2 == sal_True);
444 void tryToAcquire_002()
446 ::osl::Semaphore aSem(1);
447 bRes = aSem.tryToAcquire( );
448 bRes1 = aSem.tryToAcquire( );
451 CPPUNIT_ASSERT_MESSAGE("#test comment#: Try to acquire Semaphore twice should block.",
452 sal_True == bRes && sal_False == bRes1);
455 CPPUNIT_TEST_SUITE( tryToAcquire );
456 CPPUNIT_TEST( tryToAcquire_001 );
457 CPPUNIT_TEST( tryToAcquire_002 );
458 CPPUNIT_TEST_SUITE_END( );
459 }; // class tryToAcquire
462 /** testing the method:
463 sal_Bool release();
465 class release : public CppUnit::TestFixture
467 public:
468 sal_Bool bRes, bRes1, bRes2, bRunning;
469 sal_Int32 nCount;
470 /** acquire/release are not used in pairs: after child thread acquired semaphore,
471 the main thread release it, then any thread could acquire it.
473 void release_001()
475 Semaphore aSemaphore(1);
476 WaitThread myThread( aSemaphore );
477 myThread.create( );
479 // ensure the child thread acquire the mutex
480 thread_sleep_tenth_sec( 1 );
482 bRunning = myThread.isRunning( );
483 bRes1 = aSemaphore.tryToAcquire( );
484 // wait the child thread terminate
485 myThread.join( );
487 bRes2 = aSemaphore.tryToAcquire( );
488 if ( bRes2 == sal_True )
489 aSemaphore.release( );
491 CPPUNIT_ASSERT_MESSAGE( "release Semaphore: try to aquire before and after the semaphore has been released",
492 bRes1 == sal_False && bRes2 == sal_True && bRunning == sal_True );
496 void release_002()
498 Semaphore aSemaphore(sal_uInt32(0));
499 bRes1 = sal_True;
500 for ( nCount = 0; nCount < 10; nCount++, aSemaphore.release( ) ) { }
501 for ( nCount = 0; nCount < 10; nCount++, bRes1 = bRes1 && aSemaphore.tryToAcquire( ) ) { }
502 bRes = aSemaphore.tryToAcquire( );
504 CPPUNIT_ASSERT_MESSAGE( "release Semaphore: release ten times and acquire eleven times.",
505 sal_False == bRes && sal_True == bRes1);
508 CPPUNIT_TEST_SUITE( release );
509 CPPUNIT_TEST( release_001 );
510 CPPUNIT_TEST( release_002 );
511 CPPUNIT_TEST_SUITE_END( );
512 }; // class release
514 // -----------------------------------------------------------------------------
515 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Semaphore::ctors, "osl_Semaphore");
516 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Semaphore::acquire, "osl_Semaphore");
517 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Semaphore::tryToAcquire, "osl_Semaphore");
518 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Semaphore::release, "osl_Semaphore");
519 // -----------------------------------------------------------------------------
521 } // namespace osl_Semaphore
524 // -----------------------------------------------------------------------------
526 // this macro creates an empty function, which will called by the RegisterAllFunctions()
527 // to let the user the possibility to also register some functions by hand.
528 NOADDITIONAL;