~ubuntu-branches/ubuntu/gutsy/libcorelinux/gutsy

« back to all changes in this revision

Viewing changes to src/testdrivers/ex13/examp13.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Christophe Prud'homme
  • Date: 2001-12-29 17:43:34 UTC
  • Revision ID: james.westby@ubuntu.com-20011229174334-ejlsuilsiro5vmzr
Tags: 0.4.32-4
* fix config.{guess,sub} out of date on hppa and s390 (closes: #124296,#121830)
* try to be more descriptive in the description of the package  (closes: #115758)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  CoreLinux++ 
 
3
  Copyright (C) 2000 CoreLinux Consortium
 
4
  
 
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.
 
9
 
 
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.
 
14
 
 
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.  
 
19
*/   
 
20
 
 
21
/** \example examp13.cpp
 
22
   This example is to show use of the SemaphoreGroup and Semaphore. 
 
23
   
 
24
   For this test we use the MutexSemaphoreGroup and related type to emulate
 
25
   a double exchange example:
 
26
   
 
27
   Thread 1 (main)  : Performs the housekeeping and data source
 
28
   Thread 2 (child) : Is the data sink
 
29
   
 
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,
 
33
   
 
34
   A third semaphore is used as a flag/signal to indicate that the
 
35
   threads should drop out of the source->sink loop.
 
36
   
 
37
*/                   
 
38
 
 
39
//
 
40
// For clone()
 
41
//
 
42
 
 
43
extern "C"
 
44
{
 
45
   #include <signal.h>
 
46
   #include <sys/wait.h>
 
47
   #include <sched.h>
 
48
}
 
49
 
 
50
#include <corelinux/Common.hpp>
 
51
#include <corelinux/AbstractSemaphore.hpp>
 
52
#include <corelinux/MutexSemaphoreGroup.hpp>
 
53
 
 
54
using namespace corelinux;
 
55
 
 
56
#include <iostream>
 
57
#include <exception>
 
58
 
 
59
 
 
60
//
 
61
// In module function prototypes
 
62
//
 
63
 
 
64
int   main( void );
 
65
 
 
66
 
 
67
//
 
68
// General Functions 
 
69
//
 
70
 
 
71
void  handleAssertion( AssertionCref );
 
72
void  handleException( ExceptionCref );
 
73
void  handleStatus( SemaphoreOperationStatus );
 
74
 
 
75
//
 
76
// Thread entry point declarations
 
77
//
 
78
 
 
79
Int   threadTest( VoidPtr );
 
80
 
 
81
//
 
82
// Global data
 
83
//
 
84
 
 
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
 
91
 
 
92
      MutexSemaphoreGroupPtr  agGroup( NULLPTR );
 
93
//
 
94
// Main entry point
 
95
//
 
96
 
 
97
int main( void )
 
98
{
 
99
 
 
100
   cout << endl;
 
101
 
 
102
   AbstractSemaphorePtr    amutexParent( NULLPTR );
 
103
   AbstractSemaphorePtr    amutexChild( NULLPTR );
 
104
   AbstractSemaphorePtr    amutexFlag( NULLPTR );
 
105
 
 
106
   //
 
107
   // Practice graceful exception management
 
108
   //
 
109
 
 
110
   try
 
111
   {
 
112
      //
 
113
      // Setup our SemaphoreGroup and control Semaphores
 
114
      //
 
115
 
 
116
      agGroup = new MutexSemaphoreGroup
 
117
         ( 
 
118
            3, OWNER_ALL | GROUP_ALL | PUBLIC_ALL 
 
119
         );
 
120
 
 
121
 
 
122
      //
 
123
      // Start with two (2) locks enabled, and one not
 
124
      // the flag.
 
125
      //
 
126
 
 
127
      amutexParent  = agGroup->createLockedSemaphore
 
128
         ( 
 
129
            parentSemId, FAIL_IF_EXISTS
 
130
         );
 
131
 
 
132
 
 
133
      amutexChild = agGroup->createLockedSemaphore
 
134
         ( 
 
135
            childSemId, FAIL_IF_EXISTS
 
136
         );
 
137
 
 
138
 
 
139
      amutexFlag = agGroup->createSemaphore
 
140
         ( 
 
141
            completeSemId, FAIL_IF_EXISTS
 
142
         );
 
143
 
 
144
      //
 
145
      // Setup thread stack and point to bottom
 
146
      //
 
147
 
 
148
      VoidPtr  *newstack((VoidPtr*) new Byte[STACKSIZE]);
 
149
 
 
150
      newstack = (void **)(STACKSIZE + (char *) newstack);
 
151
      
 
152
      //
 
153
      // Spawn thread
 
154
      // threadTest - entry point int (fn*func)(void*arg)
 
155
      // newstack - bos
 
156
      // flags - Share everything
 
157
      // agGroup - SemaphoreGroupPtr (arg)
 
158
      //
 
159
 
 
160
      ThreadIdentifier  aChildId =
 
161
         clone
 
162
            (
 
163
               threadTest,
 
164
               newstack,
 
165
               CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD, 
 
166
               agGroup
 
167
            );
 
168
 
 
169
      //
 
170
      // Check for errors
 
171
      //
 
172
 
 
173
      if( aChildId != badThread )
 
174
      {
 
175
 
 
176
         //
 
177
         // Signal handling would be a better mechanism, but for now
 
178
         // loop a few
 
179
         //
 
180
 
 
181
         bool              childError( false );
 
182
         ThreadIdentifier  myId(Thread::getThreadIdentifier());
 
183
 
 
184
         for( int x = 0;  x < 10 ; ++x )
 
185
         {
 
186
            if( amutexFlag->isLocked() == false )
 
187
            {
 
188
               //
 
189
               // Do some work
 
190
               //
 
191
 
 
192
               ++gvalue;
 
193
               cout << "[" << IntRef(myId) << 
 
194
                  "]\tWriting resource  = " << gvalue << endl;
 
195
 
 
196
               // Prepare the last resource read
 
197
 
 
198
               if( gvalue == 10 )
 
199
               {
 
200
                  amutexFlag->lockWithWait();
 
201
                  amutexParent->release();
 
202
               }
 
203
               else
 
204
               {
 
205
                  amutexParent->release();
 
206
                  amutexChild->lockWithWait();
 
207
               }
 
208
            }
 
209
            else
 
210
            {
 
211
               childError = true;
 
212
               cout << "Child aborted run." << endl;
 
213
               x = 10;
 
214
            }
 
215
         }
 
216
 
 
217
         Int   aStatus(0);
 
218
         waitpid(aChildId.getScalar(),&aStatus,0);
 
219
 
 
220
         //
 
221
         // Clear semaphores
 
222
         //
 
223
 
 
224
         amutexParent->release();
 
225
         amutexChild->release();
 
226
         amutexFlag->release();
 
227
 
 
228
      }
 
229
      else
 
230
      {
 
231
         cerr << "Error number from thread" << Thread::getKernelError() << endl;
 
232
         handleStatus(amutexParent->release());
 
233
      }
 
234
   
 
235
      //
 
236
      // Housekeeping
 
237
      //
 
238
 
 
239
      agGroup->destroySemaphore(amutexChild);
 
240
      amutexChild = NULLPTR;
 
241
      agGroup->destroySemaphore(amutexParent);
 
242
      amutexParent = NULLPTR;
 
243
      agGroup->destroySemaphore(amutexFlag);
 
244
      amutexParent = NULLPTR;
 
245
 
 
246
      delete agGroup;
 
247
      agGroup = NULLPTR;
 
248
   }
 
249
 
 
250
   catch( SemaphoreExceptionRef aRef )
 
251
   {
 
252
      handleException(aRef);
 
253
      cerr << "Error number " << aRef.getErrNum() << endl;
 
254
   }
 
255
   catch( AssertionRef aAssert )
 
256
   {
 
257
      handleAssertion(aAssert);
 
258
   }
 
259
   catch( ExceptionRef aException )
 
260
   {
 
261
      handleException(aException);
 
262
   }
 
263
   catch( std::exception & e )
 
264
   {
 
265
      cerr  << e.what() << endl;
 
266
   }
 
267
   catch( ... )
 
268
   {
 
269
      cerr  << "Unknown exception." << endl;
 
270
   }
 
271
 
 
272
   //
 
273
   // If we have not gone through the housekeeping
 
274
   //
 
275
 
 
276
   if( agGroup != NULLPTR )
 
277
   {
 
278
      if( amutexParent != NULLPTR )
 
279
      {
 
280
         agGroup->destroySemaphore(amutexParent);
 
281
      }
 
282
      else
 
283
      {
 
284
         ;  // do nothing
 
285
      }
 
286
 
 
287
      if( amutexChild != NULLPTR )
 
288
      {
 
289
         agGroup->destroySemaphore(amutexChild);
 
290
      }
 
291
      else
 
292
      {
 
293
         ; // do nothing
 
294
      }
 
295
      if( amutexFlag != NULLPTR )
 
296
      {
 
297
         agGroup->destroySemaphore(amutexFlag);
 
298
      }
 
299
      else
 
300
      {
 
301
         ; // do nothing
 
302
      }
 
303
      delete agGroup;
 
304
   }
 
305
 
 
306
   return 0;               
 
307
}
 
308
 
 
309
//
 
310
// Child thread implementation
 
311
//
 
312
 
 
313
Int threadTest( void *aV )
 
314
{
 
315
   AbstractSemaphorePtr    aParent( NULLPTR );
 
316
   AbstractSemaphorePtr    aChild( NULLPTR );
 
317
   AbstractSemaphorePtr    aFlag( NULLPTR );
 
318
   ThreadIdentifier        myId(Thread::getThreadIdentifier());
 
319
 
 
320
   try
 
321
   {
 
322
      SemaphoreGroupPtr       aSG( (SemaphoreGroupPtr)aV );
 
323
 
 
324
      aParent = aSG->createSemaphore( parentSemId, FAIL_IF_NOTEXISTS );
 
325
      aChild =  aSG->createSemaphore( childSemId, FAIL_IF_NOTEXISTS );
 
326
      aFlag =  aSG->createSemaphore( completeSemId, FAIL_IF_NOTEXISTS );
 
327
 
 
328
 
 
329
      while( aFlag->isLocked() == false )
 
330
      {
 
331
         aParent->lockWithWait();
 
332
         cout << "\t[" << IntRef(myId) << 
 
333
            "]\tReading resource  = " << gvalue << endl;
 
334
         aChild->release();
 
335
      }
 
336
 
 
337
   }
 
338
 
 
339
   catch(SemaphoreExceptionRef aSemExcp )
 
340
   {
 
341
      cerr << "Thread bailing out with exception" << endl;
 
342
      handleException( aSemExcp );
 
343
      aFlag->lockWithWait();
 
344
   }
 
345
   catch( ... )
 
346
   {
 
347
      cerr << "Thread bailing out with exception" << endl;
 
348
      aFlag->lockWithWait();
 
349
   }
 
350
 
 
351
   return 0;
 
352
}
 
353
 
 
354
 
 
355
//
 
356
// Peform defaults (just show it)
 
357
//
 
358
 
 
359
void  handleStatus( SemaphoreOperationStatus aStatus )
 
360
{
 
361
   switch( aStatus )
 
362
   {
 
363
      case  SUCCESS:
 
364
         cerr << "Success" << endl;
 
365
         break;
 
366
      case  BALKED:
 
367
         cerr << "Request balked" << endl;
 
368
         break;
 
369
      case  TIMEDOUT:
 
370
         cerr << "Request timed out" << endl;
 
371
         break;
 
372
      case UNAVAILABLE:
 
373
         cerr << "Request not satisfied" << endl;
 
374
         break;
 
375
      case  KERNELERROR:
 
376
         cerr << "Kernel reported error : " << Thread::getKernelError() << endl;
 
377
         break;
 
378
      default:
 
379
         NEVER_GET_HERE;
 
380
         break;
 
381
   }
 
382
 
 
383
   return;
 
384
}
 
385
 
 
386
void  handleAssertion( AssertionCref aAssert )
 
387
{
 
388
   cerr << aAssert.getFile() << ":" << aAssert.getLine() << ":" << 
 
389
      "Assertion: ";
 
390
 
 
391
   if( aAssert.getType() == Assertion::NEVERGETHERE )
 
392
   {
 
393
      cerr << "NEVER_GET_HERE";
 
394
   }
 
395
   else
 
396
   {
 
397
      if( aAssert.getType() == Assertion::REQUIRE )
 
398
      {
 
399
         cerr  << "REQUIRE";
 
400
      }
 
401
      else if( aAssert.getType() == Assertion::ENSURE )
 
402
      {
 
403
         cerr  << "ENSURE";
 
404
      }
 
405
      else if( aAssert.getType() == Assertion::CHECK )
 
406
      {
 
407
         cerr  << "CHECK";
 
408
      }
 
409
      else 
 
410
      {
 
411
         cerr  << "ASSERT";
 
412
      }
 
413
      cerr << "( " << aAssert.getWhy() << " )";
 
414
   }
 
415
 
 
416
   cerr << endl;
 
417
}
 
418
 
 
419
void  handleException( ExceptionCref aExcp )
 
420
{
 
421
   cerr << aExcp.getFile() << ":" << aExcp.getLine() << ":" <<
 
422
      "Exception: " << aExcp.getWhy() << endl;
 
423
}
 
424
 
 
425
/*
 
426
   Common rcs information do not modify
 
427
   $Author: frankc $
 
428
   $Revision: 1.9 $
 
429
   $Date: 2000/09/07 12:54:44 $
 
430
   $Locker:  $
 
431
*/
 
432
 
 
433