1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
22 #include <sal/types.h>
23 #include <cppunit/TestAssert.h>
24 #include <cppunit/TestFixture.h>
25 #include <cppunit/extensions/HelperMacros.h>
26 #include <cppunit/plugin/TestPlugIn.h>
27 #include "osl_Mutex_Const.h"
31 /** pause nSec seconds helper function.
33 namespace ThreadHelper
35 static void thread_sleep_tenth_sec(sal_uInt32 _nTenthSec
)
37 osl::Thread::wait(std::chrono::milliseconds(_nTenthSec
* 100));
39 static void thread_sleep( sal_uInt32 _nSec
)
41 /// print statement in thread process must use fflush() to force display.
42 // t_print("# wait %d seconds. ", _nSec );
45 thread_sleep_tenth_sec( _nSec
* 10 );
46 // printf("# done\n" );
50 // Beginning of the test cases for osl_Mutex class
52 /** mutually exclusive data
60 /** IncreaseThread provide data.
62 class IncreaseThread
: public Thread
65 explicit IncreaseThread( struct resource
*pData
): pResource( pData
) { }
67 virtual ~IncreaseThread( ) override
69 CPPUNIT_ASSERT_MESSAGE( "#IncreaseThread does not shutdown properly.\n", !isRunning( ) );
72 struct resource
*pResource
;
74 void SAL_CALL
run( ) override
76 pResource
->lock
.acquire( );
77 for( sal_Int8 i
= 0; i
< 3; i
++ )
80 yield( ); //yield() give CPU time to other thread, other thread if not block, they will change the data;
82 if ( pResource
->data2
== 0 )
83 pResource
->data2
= ( pResource
->data1
> 0 ? pResource
->data1
: 0 - pResource
->data1
);
84 pResource
->lock
.release();
88 /** DecreaseThread consume data.
90 class DecreaseThread
: public Thread
93 explicit DecreaseThread( struct resource
*pData
): pResource( pData
) { }
95 virtual ~DecreaseThread( ) override
97 CPPUNIT_ASSERT_MESSAGE( "#DecreaseThread does not shutdown properly.\n", !isRunning( ) );
100 struct resource
*pResource
;
102 void SAL_CALL
run( ) override
104 pResource
->lock
.acquire( );
105 for( sal_Int8 i
= 0; i
< 3; i
++ )
108 yield( ); //yield() give CPU time to other thread, other thread if not block, they will change the data;
110 if ( pResource
->data2
== 0 )
111 pResource
->data2
= ( pResource
->data1
> 0 ? pResource
->data1
: 0 - pResource
->data1
);
112 pResource
->lock
.release();
116 /** chain structure used in Threads as critical resource
119 sal_Int32 buffer
[ BUFFER_SIZE
];
124 /** PutThread write to the chain structure in a mutex manner.
126 class PutThread
: public Thread
129 //get the struct pointer to write data to buffer
130 explicit PutThread( struct chain
* pData
): pChain( pData
) { }
132 virtual ~PutThread( ) override
134 CPPUNIT_ASSERT_MESSAGE( "#PutThread does not shutdown properly.\n", !isRunning( ) );
137 struct chain
* pChain
;
139 void SAL_CALL
run( ) override
141 //block here if the mutex has been acquired
142 pChain
->lock
.acquire( );
144 //current position in buffer to write
145 sal_Int8 nPos
= pChain
->pos
;
146 oslThreadIdentifier oId
= getIdentifier( );
149 for ( i
= 0; i
< 5; i
++ )
151 pChain
->buffer
[ nPos
+ i
] = oId
;
154 //revise the position
155 pChain
->pos
= nPos
+ i
;
157 //finish writing, release the mutex
158 pChain
->lock
.release();
162 /** thread for testing Mutex acquire.
164 class HoldThread
: public Thread
167 //get the Mutex pointer to operate
168 explicit HoldThread( Mutex
* pMutex
): pMyMutex( pMutex
) { }
170 virtual ~HoldThread( ) override
172 CPPUNIT_ASSERT_MESSAGE( "#HoldThread does not shutdown properly.\n", !isRunning( ) );
177 void SAL_CALL
run() override
179 // block here if the mutex has been acquired
180 pMyMutex
->acquire( );
181 printf("# Mutex acquired. \n" );
182 pMyMutex
->release( );
186 class WaitThread
: public Thread
189 //get the Mutex pointer to operate
190 explicit WaitThread( Mutex
* pMutex
): pMyMutex( pMutex
) { }
192 virtual ~WaitThread( ) override
194 CPPUNIT_ASSERT_MESSAGE( "#WaitThread does not shutdown properly.\n", !isRunning( ) );
199 void SAL_CALL
run( ) override
201 // block here if the mutex has been acquired
202 pMyMutex
->acquire( );
203 ThreadHelper::thread_sleep_tenth_sec( 2 );
204 pMyMutex
->release( );
208 /** thread for testing getGlobalMutex.
210 class GlobalMutexThread
: public Thread
213 //get the Mutex pointer to operate
214 GlobalMutexThread( ){ }
216 virtual ~GlobalMutexThread( ) override
218 CPPUNIT_ASSERT_MESSAGE( "#GlobalMutexThread does not shutdown properly.\n", !isRunning( ) );
221 void SAL_CALL
run( ) override
223 // block here if the mutex has been acquired
225 pGlobalMutex
= Mutex::getGlobalMutex( );
226 pGlobalMutex
->acquire( );
227 printf("# Global Mutex acquired. \n" );
228 pGlobalMutex
->release( );
235 /** Test of the osl::Mutex::constructor
237 class ctor
: public CppUnit::TestFixture
240 // initialise your test code values here.
242 struct resource m_Res
;
244 void setUp( ) override
246 for ( sal_Int8 i
=0; i
< BUFFER_SIZE
; i
++ )
247 m_Data
.buffer
[i
] = 0;
254 /** Create two threads to write data to the same buffer, use Mutex to assure
255 during one thread write data five times, the other thread should not begin writing.
256 the two threads wrote two different data: their thread ID, so we can check the data
257 in buffer to know the order of the two threads writing
261 PutThread
myThread1( &m_Data
);
262 PutThread
myThread2( &m_Data
);
267 //wait until the two threads terminate
273 // every 5 data should the same
274 // LLA: this is not a good check, it's too fix
275 if (m_Data
.buffer
[0] == m_Data
.buffer
[1] &&
276 m_Data
.buffer
[1] == m_Data
.buffer
[2] &&
277 m_Data
.buffer
[2] == m_Data
.buffer
[3] &&
278 m_Data
.buffer
[3] == m_Data
.buffer
[4] &&
279 m_Data
.buffer
[5] == m_Data
.buffer
[6] &&
280 m_Data
.buffer
[6] == m_Data
.buffer
[7] &&
281 m_Data
.buffer
[7] == m_Data
.buffer
[8] &&
282 m_Data
.buffer
[8] == m_Data
.buffer
[9])
285 /*for (sal_Int8 i=0; i<BUFFER_SIZE; i++)
286 printf("#data in buffer is %d\n", m_Data.buffer[i]);
289 CPPUNIT_ASSERT_MESSAGE("Mutex ctor", bRes
);
293 /** Create two threads to write data to operate on the same number , use Mutex to assure,
294 one thread increase data 3 times, the other thread decrease 3 times, store the operate
295 result when the first thread complete, if it is interrupt by the other thread, the stored
296 number will not be 3.
300 IncreaseThread
myThread1( &m_Res
);
301 DecreaseThread
myThread2( &m_Res
);
306 //wait until the two threads terminate
312 // every 5 data should the same
313 if ( ( m_Res
.data1
== 0 ) && ( m_Res
.data2
== 3 ) )
316 CPPUNIT_ASSERT_MESSAGE( "test Mutex ctor function: increase and decrease a number 3 times without interrupt.", bRes
);
319 CPPUNIT_TEST_SUITE( ctor
);
320 CPPUNIT_TEST( ctor_001
);
321 CPPUNIT_TEST( ctor_002
);
322 CPPUNIT_TEST_SUITE_END( );
325 /** Test of the osl::Mutex::acquire method
327 class acquire
: public CppUnit::TestFixture
330 // acquire mutex in main thread, and then call acquire again in myThread,
331 // the child thread should block, wait 2 secs, it still block.
332 // Then release mutex in main thread, the child thread could return from acquire,
333 // and go to exec next statement, so could terminate quickly.
338 bool bRes
= aMutex
.acquire( );
339 // pass the pointer of mutex to child thread
340 HoldThread
myThread( &aMutex
);
343 ThreadHelper::thread_sleep_tenth_sec( 2 );
344 // if acquire in myThread does not work, 2 secs is long enough,
345 // myThread should terminate now, and bRes1 should be sal_False
346 bool bRes1
= myThread
.isRunning( );
349 ThreadHelper::thread_sleep_tenth_sec( 1 );
350 // after release mutex, myThread stops blocking and will terminate immediately
351 bool bRes2
= myThread
.isRunning( );
354 CPPUNIT_ASSERT_MESSAGE( "Mutex acquire", bRes
);
355 CPPUNIT_ASSERT_MESSAGE( "Mutex acquire", bRes1
);
356 CPPUNIT_ASSERT_MESSAGE( "Mutex acquire", !bRes2
);
359 //in the same thread, acquire twice should success
364 bool bRes
= aMutex
.acquire();
365 bool bRes1
= aMutex
.acquire();
367 bool bRes2
= aMutex
.tryToAcquire();
371 CPPUNIT_ASSERT_MESSAGE("Mutex acquire", bRes
);
372 CPPUNIT_ASSERT_MESSAGE("Mutex acquire", bRes1
);
373 CPPUNIT_ASSERT_MESSAGE("Mutex acquire", bRes2
);
377 CPPUNIT_TEST_SUITE( acquire
);
378 CPPUNIT_TEST( acquire_001
);
379 CPPUNIT_TEST( acquire_002
);
380 CPPUNIT_TEST_SUITE_END( );
383 /** Test of the osl::Mutex::tryToAcquire method
385 class tryToAcquire
: public CppUnit::TestFixture
388 // First let child thread acquire the mutex, and wait 2 secs, during the 2 secs,
389 // in main thread, tryToAcquire mutex should return False
390 // then after the child thread terminated, tryToAcquire should return True
391 void tryToAcquire_001()
394 WaitThread
myThread(&aMutex
);
397 // ensure the child thread acquire the mutex
398 ThreadHelper::thread_sleep_tenth_sec(1);
400 bool bRes1
= aMutex
.tryToAcquire();
404 // wait the child thread terminate
407 bool bRes2
= aMutex
.tryToAcquire();
412 CPPUNIT_ASSERT_MESSAGE("Try to acquire Mutex", !bRes1
);
413 CPPUNIT_ASSERT_MESSAGE("Try to acquire Mutex", bRes2
);
416 CPPUNIT_TEST_SUITE(tryToAcquire
);
417 CPPUNIT_TEST(tryToAcquire_001
);
418 CPPUNIT_TEST_SUITE_END();
419 }; // class tryToAcquire
421 /** Test of the osl::Mutex::release method
423 class release
: public CppUnit::TestFixture
426 /** acquire/release are not used in pairs: after child thread acquired mutex,
427 the main thread release it, then any thread could acquire it.
432 WaitThread
myThread( &aMutex
);
435 // ensure the child thread acquire the mutex
436 ThreadHelper::thread_sleep_tenth_sec( 1 );
438 bool bRunning
= myThread
.isRunning( );
439 bool bRes1
= aMutex
.tryToAcquire( );
440 // wait the child thread terminate
443 bool bRes2
= aMutex
.tryToAcquire( );
448 CPPUNIT_ASSERT_MESSAGE( "release Mutex: try to acquire before and after the mutex has been released",
450 CPPUNIT_ASSERT_MESSAGE( "release Mutex: try to acquire before and after the mutex has been released",
452 CPPUNIT_ASSERT_MESSAGE( "release Mutex: try to acquire before and after the mutex has been released",
457 // how about release twice?
462 CPPUNIT_TEST_SUITE( release
);
463 CPPUNIT_TEST( release_001
);
464 CPPUNIT_TEST( release_002
);
465 CPPUNIT_TEST_SUITE_END( );
468 /** Test of the osl::Mutex::getGlobalMutex method
470 class getGlobalMutex
: public CppUnit::TestFixture
473 // initialise your test code values here.
474 void getGlobalMutex_001()
477 pGlobalMutex
= Mutex::getGlobalMutex();
478 pGlobalMutex
->acquire();
480 GlobalMutexThread myThread
;
483 ThreadHelper::thread_sleep_tenth_sec(1);
484 bool bRes1
= myThread
.isRunning();
486 pGlobalMutex
->release();
487 ThreadHelper::thread_sleep_tenth_sec(1);
488 // after release mutex, myThread stops blocking and will terminate immediately
489 bool bRes2
= myThread
.isRunning();
491 CPPUNIT_ASSERT_MESSAGE("Global Mutex works", bRes1
);
492 CPPUNIT_ASSERT_MESSAGE("Global Mutex works", !bRes2
);
495 void getGlobalMutex_002( )
500 pGlobalMutex
= Mutex::getGlobalMutex( );
501 pGlobalMutex
->acquire( );
503 Mutex
*pGlobalMutex1
;
504 pGlobalMutex1
= Mutex::getGlobalMutex( );
505 bRes
= pGlobalMutex1
->release( );
508 CPPUNIT_ASSERT_MESSAGE( "Global Mutex works: if the code between {} get the different mutex as the former one, it will return false when release.",
512 CPPUNIT_TEST_SUITE(getGlobalMutex
);
513 CPPUNIT_TEST(getGlobalMutex_001
);
514 CPPUNIT_TEST(getGlobalMutex_002
);
515 CPPUNIT_TEST_SUITE_END();
516 }; // class getGlobalMutex
518 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Mutex::ctor
, "osl_Mutex");
519 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Mutex::acquire
, "osl_Mutex");
520 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Mutex::tryToAcquire
, "osl_Mutex");
521 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Mutex::release
, "osl_Mutex");
522 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Mutex::getGlobalMutex
, "osl_Mutex");
523 } // namespace osl_Mutex
525 // Beginning of the test cases for osl_Guard class
527 class GuardThread
: public Thread
530 //get the Mutex pointer to operate
531 explicit GuardThread( Mutex
* pMutex
): pMyMutex( pMutex
) { }
533 virtual ~GuardThread( ) override
535 CPPUNIT_ASSERT_MESSAGE( "#GuardThread does not shutdown properly.\n", !isRunning( ) );
540 void SAL_CALL
run( ) override
542 // block here if the mutex has been acquired
543 MutexGuard
aGuard( pMyMutex
);
544 ThreadHelper::thread_sleep_tenth_sec( 2 );
550 class ctor
: public CppUnit::TestFixture
553 // insert your test code here.
557 GuardThread
myThread(&aMutex
);
560 ThreadHelper::thread_sleep_tenth_sec(1);
561 bool bRes
= aMutex
.tryToAcquire();
562 // after 1 second, the mutex has been guarded, and the child thread should be running
563 bool bRes1
= myThread
.isRunning();
566 bool bRes2
= aMutex
.tryToAcquire();
568 CPPUNIT_ASSERT_MESSAGE("GuardThread constructor",
570 CPPUNIT_ASSERT_MESSAGE("GuardThread constructor",
572 CPPUNIT_ASSERT_MESSAGE("GuardThread constructor",
580 /// use reference constructor here
581 MutexGuard
myGuard( aMutex
);
583 /// the GuardThread will block here when it is initialised.
584 GuardThread
myThread( &aMutex
);
587 /// is it still blocking?
588 ThreadHelper::thread_sleep_tenth_sec( 2 );
589 bool bRes
= myThread
.isRunning( );
595 CPPUNIT_ASSERT_MESSAGE("GuardThread constructor: reference initialization, acquire the mutex before running the thread, then check if it is blocking.",
599 CPPUNIT_TEST_SUITE(ctor
);
600 CPPUNIT_TEST(ctor_001
);
601 CPPUNIT_TEST(ctor_002
);
602 CPPUNIT_TEST_SUITE_END();
605 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Guard::ctor
, "osl_Guard");
606 } // namespace osl_Guard
608 // Beginning of the test cases for osl_ClearableGuard class
610 /** Thread for test ClearableGuard
612 class ClearGuardThread
: public Thread
615 //get the Mutex pointer to operate
616 explicit ClearGuardThread( Mutex
* pMutex
): pMyMutex( pMutex
) {}
618 virtual ~ClearGuardThread( ) override
620 CPPUNIT_ASSERT_MESSAGE( "#ClearGuardThread does not shutdown properly.\n", !isRunning( ) );
625 void SAL_CALL
run( ) override
628 // printf("# ClearGuardThread" );
629 ClearableMutexGuard
aGuard( pMyMutex
);
630 ThreadHelper::thread_sleep( 5 );
634 ThreadHelper::thread_sleep( 2 );
638 namespace osl_ClearableGuard
641 class ctor
: public CppUnit::TestFixture
648 /// now, the aMutex has been guarded.
649 ClearableMutexGuard
myMutexGuard( &aMutex
);
651 /// it will return sal_False if the aMutex has not been Guarded.
652 bool bRes
= aMutex
.release( );
654 CPPUNIT_ASSERT_MESSAGE("ClearableMutexGuard constructor, test the acquire operation when initialized.",
662 /// now, the aMutex has been guarded, this time, we use reference constructor.
663 ClearableMutexGuard
myMutexGuard( aMutex
);
665 /// it will return sal_False if the aMutex has not been Guarded.
666 bool bRes
= aMutex
.release( );
668 CPPUNIT_ASSERT_MESSAGE("ClearableMutexGuard constructor, test the acquire operation when initialized, we use reference constructor this time.",
672 CPPUNIT_TEST_SUITE(ctor
);
673 CPPUNIT_TEST(ctor_001
);
674 CPPUNIT_TEST(ctor_002
);
675 CPPUNIT_TEST_SUITE_END();
678 class clear
: public CppUnit::TestFixture
684 ClearGuardThread
myThread(&aMutex
);
687 TimeValue aTimeVal_befor
;
688 osl_getSystemTime( &aTimeVal_befor
);
689 // wait 1 second to assure the child thread has begun
690 ThreadHelper::thread_sleep(1);
694 if (aMutex
.tryToAcquire())
698 ThreadHelper::thread_sleep(1);
700 TimeValue aTimeVal_after
;
701 osl_getSystemTime( &aTimeVal_after
);
702 sal_Int32 nSec
= aTimeVal_after
.Seconds
- aTimeVal_befor
.Seconds
;
703 printf("nSec is %" SAL_PRIdINT32
"\n", nSec
);
707 CPPUNIT_ASSERT_MESSAGE("ClearableGuard method: clear",
709 CPPUNIT_ASSERT_MESSAGE("ClearableGuard method: clear",
717 /// now, the aMutex has been guarded.
718 ClearableMutexGuard
myMutexGuard( &aMutex
);
720 /// launch the HoldThread, it will be blocked here.
721 HoldThread
myThread( &aMutex
);
725 ThreadHelper::thread_sleep_tenth_sec( 4 );
726 bool bRes
= myThread
.isRunning( );
728 /// use clear to release.
729 myMutexGuard
.clear( );
731 bool bRes1
= myThread
.isRunning( );
733 CPPUNIT_ASSERT_MESSAGE( "ClearableGuard method: clear, control the HoldThread's running status!",
735 CPPUNIT_ASSERT_MESSAGE( "ClearableGuard method: clear, control the HoldThread's running status!",
739 CPPUNIT_TEST_SUITE( clear
);
740 CPPUNIT_TEST( clear_001
);
741 CPPUNIT_TEST( clear_002
);
742 CPPUNIT_TEST_SUITE_END( );
745 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( osl_ClearableGuard::ctor
, "osl_ClearableGuard" );
746 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( osl_ClearableGuard::clear
, "osl_ClearableGuard" );
747 } // namespace osl_ClearableGuard
749 // Beginning of the test cases for osl_ResettableGuard class
751 /** Thread for test ResettableGuard
753 class ResetGuardThread
: public Thread
756 //get the Mutex pointer to operate
757 explicit ResetGuardThread( Mutex
* pMutex
): pMyMutex( pMutex
) {}
759 virtual ~ResetGuardThread( ) override
761 CPPUNIT_ASSERT_MESSAGE( "#ResetGuardThread does not shutdown properly.\n", !isRunning( ) );
766 void SAL_CALL
run( ) override
769 printf("# ResettableGuard\n" );
770 ResettableMutexGuard
aGuard( pMyMutex
);
773 ThreadHelper::thread_sleep_tenth_sec( 2 );
777 namespace osl_ResettableGuard
779 class ctor
: public CppUnit::TestFixture
786 /// now, the aMutex has been guarded.
787 ResettableMutexGuard
myMutexGuard( &aMutex
);
789 /// it will return sal_False if the aMutex has not been Guarded.
790 bool bRes
= aMutex
.release( );
792 CPPUNIT_ASSERT_MESSAGE("ResettableMutexGuard constructor, test the acquire operation when initialized.",
800 /// now, the aMutex has been guarded, this time, we use reference constructor.
801 ResettableMutexGuard
myMutexGuard( aMutex
);
803 /// it will return sal_False if the aMutex has not been Guarded.
804 bool bRes
= aMutex
.release( );
806 CPPUNIT_ASSERT_MESSAGE( "ResettableMutexGuard constructor, test the acquire operation when initialized, we use reference constructor this time.",
810 CPPUNIT_TEST_SUITE(ctor
);
811 CPPUNIT_TEST(ctor_001
);
812 CPPUNIT_TEST(ctor_002
);
813 CPPUNIT_TEST_SUITE_END();
816 class reset
: public CppUnit::TestFixture
822 ResetGuardThread
myThread( &aMutex
);
823 ResettableMutexGuard
myMutexGuard( aMutex
);
826 /// is it running? and clear done?
827 bool bRes
= myThread
.isRunning( );
828 myMutexGuard
.clear( );
829 ThreadHelper::thread_sleep_tenth_sec( 1 );
831 /// if reset is not success, the release will return sal_False
832 myMutexGuard
.reset( );
833 bool bRes1
= aMutex
.release( );
836 CPPUNIT_ASSERT_MESSAGE( "ResettableMutexGuard method: reset",
838 CPPUNIT_ASSERT_MESSAGE( "ResettableMutexGuard method: reset",
846 ResettableMutexGuard
myMutexGuard( &aMutex
);
848 /// shouldn't release after clear;
849 myMutexGuard
.clear( );
850 bool bRes
= aMutex
.release( );
852 /// can release after reset.
853 myMutexGuard
.reset( );
854 bool bRes1
= aMutex
.release( );
856 CPPUNIT_ASSERT_MESSAGE( "ResettableMutexGuard method: reset, release after clear and reset, on Solaris, the mutex can be release without acquire, so it can not passed on (SOLARIS), but not the reason for reset_002",
858 CPPUNIT_ASSERT_MESSAGE( "ResettableMutexGuard method: reset, release after clear and reset, on Solaris, the mutex can be release without acquire, so it can not passed on (SOLARIS), but not the reason for reset_002",
863 CPPUNIT_TEST_SUITE(reset
);
864 CPPUNIT_TEST(reset_001
);
866 CPPUNIT_TEST(reset_002
);
868 CPPUNIT_TEST_SUITE_END();
871 CPPUNIT_TEST_SUITE_REGISTRATION(osl_ResettableGuard::ctor
);
872 CPPUNIT_TEST_SUITE_REGISTRATION(osl_ResettableGuard::reset
);
873 } // namespace osl_ResettableGuard
875 // The following sets variables for GNU EMACS
880 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */