3
Copyright (C) 2000 CoreLinux Consortium
5
The CoreLinux++ Library is free software; you can redistribute it and/or
6
modify it under the terms of the GNU Library General Public License as
7
published by the Free Software Foundation; either version 2 of the
8
License, or (at your option) any later version.
10
The CoreLinux++ Library Library is distributed in the hope that it will
11
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
Library General Public License for more details.
15
You should have received a copy of the GNU Library General Public
16
License along with the GNU C Library; see the file COPYING.LIB. If not,
17
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18
Boston, MA 02111-1307, USA.
21
/** \example examp13.cpp
22
This example is to show use of the SemaphoreGroup and Semaphore.
24
For this test we use the MutexSemaphoreGroup and related type to emulate
25
a double exchange example:
27
Thread 1 (main) : Performs the housekeeping and data source
28
Thread 2 (child) : Is the data sink
30
Both threads have a control semaphore which the other thread uses to
31
control access to a resource , in this case the the data counter gvalue.
32
They are also used as a synchronization mechanism,
34
A third semaphore is used as a flag/signal to indicate that the
35
threads should drop out of the source->sink loop.
50
#include <corelinux/Common.hpp>
51
#include <corelinux/AbstractSemaphore.hpp>
52
#include <corelinux/MutexSemaphoreGroup.hpp>
54
using namespace corelinux;
61
// In module function prototypes
71
void handleAssertion( AssertionCref );
72
void handleException( ExceptionCref );
73
void handleStatus( SemaphoreOperationStatus );
76
// Thread entry point declarations
79
Int threadTest( VoidPtr );
85
const int STACKSIZE(8192); // Thread stack size
86
SemaphoreIdentifier parentSemId(0); // Identifier for control
87
SemaphoreIdentifier childSemId(1); // Identifier for control
88
SemaphoreIdentifier completeSemId(2); // Identifier for control
89
ThreadIdentifier badThread(-1); // Use for testing
90
Dword gvalue(0); // Resource being protected
92
MutexSemaphoreGroupPtr agGroup( NULLPTR );
102
AbstractSemaphorePtr amutexParent( NULLPTR );
103
AbstractSemaphorePtr amutexChild( NULLPTR );
104
AbstractSemaphorePtr amutexFlag( NULLPTR );
107
// Practice graceful exception management
113
// Setup our SemaphoreGroup and control Semaphores
116
agGroup = new MutexSemaphoreGroup
118
3, OWNER_ALL | GROUP_ALL | PUBLIC_ALL
123
// Start with two (2) locks enabled, and one not
127
amutexParent = agGroup->createLockedSemaphore
129
parentSemId, FAIL_IF_EXISTS
133
amutexChild = agGroup->createLockedSemaphore
135
childSemId, FAIL_IF_EXISTS
139
amutexFlag = agGroup->createSemaphore
141
completeSemId, FAIL_IF_EXISTS
145
// Setup thread stack and point to bottom
148
VoidPtr *newstack((VoidPtr*) new Byte[STACKSIZE]);
150
newstack = (void **)(STACKSIZE + (char *) newstack);
154
// threadTest - entry point int (fn*func)(void*arg)
156
// flags - Share everything
157
// agGroup - SemaphoreGroupPtr (arg)
160
ThreadIdentifier aChildId =
165
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD,
173
if( aChildId != badThread )
177
// Signal handling would be a better mechanism, but for now
181
bool childError( false );
182
ThreadIdentifier myId(Thread::getThreadIdentifier());
184
for( int x = 0; x < 10 ; ++x )
186
if( amutexFlag->isLocked() == false )
193
cout << "[" << IntRef(myId) <<
194
"]\tWriting resource = " << gvalue << endl;
196
// Prepare the last resource read
200
amutexFlag->lockWithWait();
201
amutexParent->release();
205
amutexParent->release();
206
amutexChild->lockWithWait();
212
cout << "Child aborted run." << endl;
218
waitpid(aChildId.getScalar(),&aStatus,0);
224
amutexParent->release();
225
amutexChild->release();
226
amutexFlag->release();
231
cerr << "Error number from thread" << Thread::getKernelError() << endl;
232
handleStatus(amutexParent->release());
239
agGroup->destroySemaphore(amutexChild);
240
amutexChild = NULLPTR;
241
agGroup->destroySemaphore(amutexParent);
242
amutexParent = NULLPTR;
243
agGroup->destroySemaphore(amutexFlag);
244
amutexParent = NULLPTR;
250
catch( SemaphoreExceptionRef aRef )
252
handleException(aRef);
253
cerr << "Error number " << aRef.getErrNum() << endl;
255
catch( AssertionRef aAssert )
257
handleAssertion(aAssert);
259
catch( ExceptionRef aException )
261
handleException(aException);
263
catch( std::exception & e )
265
cerr << e.what() << endl;
269
cerr << "Unknown exception." << endl;
273
// If we have not gone through the housekeeping
276
if( agGroup != NULLPTR )
278
if( amutexParent != NULLPTR )
280
agGroup->destroySemaphore(amutexParent);
287
if( amutexChild != NULLPTR )
289
agGroup->destroySemaphore(amutexChild);
295
if( amutexFlag != NULLPTR )
297
agGroup->destroySemaphore(amutexFlag);
310
// Child thread implementation
313
Int threadTest( void *aV )
315
AbstractSemaphorePtr aParent( NULLPTR );
316
AbstractSemaphorePtr aChild( NULLPTR );
317
AbstractSemaphorePtr aFlag( NULLPTR );
318
ThreadIdentifier myId(Thread::getThreadIdentifier());
322
SemaphoreGroupPtr aSG( (SemaphoreGroupPtr)aV );
324
aParent = aSG->createSemaphore( parentSemId, FAIL_IF_NOTEXISTS );
325
aChild = aSG->createSemaphore( childSemId, FAIL_IF_NOTEXISTS );
326
aFlag = aSG->createSemaphore( completeSemId, FAIL_IF_NOTEXISTS );
329
while( aFlag->isLocked() == false )
331
aParent->lockWithWait();
332
cout << "\t[" << IntRef(myId) <<
333
"]\tReading resource = " << gvalue << endl;
339
catch(SemaphoreExceptionRef aSemExcp )
341
cerr << "Thread bailing out with exception" << endl;
342
handleException( aSemExcp );
343
aFlag->lockWithWait();
347
cerr << "Thread bailing out with exception" << endl;
348
aFlag->lockWithWait();
356
// Peform defaults (just show it)
359
void handleStatus( SemaphoreOperationStatus aStatus )
364
cerr << "Success" << endl;
367
cerr << "Request balked" << endl;
370
cerr << "Request timed out" << endl;
373
cerr << "Request not satisfied" << endl;
376
cerr << "Kernel reported error : " << Thread::getKernelError() << endl;
386
void handleAssertion( AssertionCref aAssert )
388
cerr << aAssert.getFile() << ":" << aAssert.getLine() << ":" <<
391
if( aAssert.getType() == Assertion::NEVERGETHERE )
393
cerr << "NEVER_GET_HERE";
397
if( aAssert.getType() == Assertion::REQUIRE )
401
else if( aAssert.getType() == Assertion::ENSURE )
405
else if( aAssert.getType() == Assertion::CHECK )
413
cerr << "( " << aAssert.getWhy() << " )";
419
void handleException( ExceptionCref aExcp )
421
cerr << aExcp.getFile() << ":" << aExcp.getLine() << ":" <<
422
"Exception: " << aExcp.getWhy() << endl;
426
Common rcs information do not modify
429
$Date: 2000/09/07 12:54:44 $