KWStyle - itkSemaphore.cxx
 
Matrix View
Description

1 /*=========================================================================
2
3   Program:   Insight Segmentation & Registration Toolkit
4   Module:    $RCSfile: itkSemaphore.cxx.html,v $
5   Language:  C++
6   Date:      $Date: 2006/01/17 19:15:47 $
7   Version:   $Revision: 1.4 $
8
9   Copyright (c) Insight Software Consortium. All rights reserved.
10   See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
11
12      This software is distributed WITHOUT ANY WARRANTY; without even 
13      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
14      PURPOSE.  See the above copyright notices for more information.
15
16 =========================================================================*/
17 DEF #ifndef __itkSemaphore_cxx_
18 DEF #define __itkSemaphore_cxx_
19
20 #include "itkConfigure.h"
21 #include "itkSemaphore.h"
22
23 #ifdef __APPLE__
24 extern "C" {
25 #include <stdio.h>
26 #include <time.h>
27 IND }
28 #endif
29
30 /// DEBUG
31 extern "C" {
32 #include <stdio.h>
33 #include <errno.h>
34 IND }
35 ///
36
37 namespace itk {
38
39 #ifdef __APPLE__
40 int Semaphore::m_SemaphoreCount = 0;
41 #endif
42
43 #ifdef ITK_USE_UNIX_IPC_SEMAPHORES
44 int Semaphore::m_IPCSemaphoreKey = 12345;
45 SimpleMutexLock Semaphore::m_Mutex;
46 #endif
47
48 #ifdef __APPLE__
49 std::string Semaphore::GetUniqueName()
50 {
51   char s[255];  
52   time_t t = time(0);
53   snprintf(s,254,"MACSEM%d%d",static_cast<int>(t),m_SemaphoreCount); 
54   return std::string(s); 
55 }
56 #endif
57
58 Semaphore::Semaphore ()
59 {
60 #ifdef ITK_USE_UNIX_IPC_SEMAPHORES
61   m_Sema= -1;
62 #endif
63
64
65 #ifdef __APPLE__
66   m_Sema = 0;
67   m_SemaphoreCount++;
68   m_SemaphoreName = Semaphore::GetUniqueName();
69 #endif
70   
71 #ifndef ITK_USE_UNIX_IPC_SEMAPHORES  
72
73 #ifdef ITK_USE_SPROC
74   m_Sema = 0;
75 #endif
76
77 #endif
78   
79 #ifdef ITK_USE_WIN32_THREADS
80   m_Sema = 0;
81 #endif
82
83 #ifdef ITK_USE_PTHREADS
84   m_PThreadsSemaphoreRemoved = false;
85 #endif
86 }
87   
88 void Semaphore::Initialize(unsigned int value)
89 {
90   
91 #ifdef ITK_USE_UNIX_IPC_SEMAPHORES
92   // Obtain a lock over the m_IPCSemaphoreKey so that the new semaphore is
93   // created with a unique unix_semaphore_key 
94   Semaphore::m_Mutex.Lock();
95   m_Sema = Semaphore::UnixIpcSemaphoreCreate(Semaphore::m_IPCSemaphoreKey);
96   
97   // by default the semaphore created has value 0
98   Semaphore::m_IPCSemaphoreKey++;
99   Semaphore::m_Mutex.Unlock();
100   
101   for (unsigned int i = 0; i < value; i++)
102     {
103     this->Up();
104     }
105 #endif
106   
107 #ifndef ITK_USE_UNIX_IPC_SEMAPHORES  
108 #ifdef ITK_USE_SPROC
109   if (MultiThreader::GetInitialized() == false)
110     {
111 IND ******MultiThreader::Initialize();
112     }
113
114   m_Sema = usnewsema(MultiThreader::GetThreadArena(), static_cast<int>(value));
115   if ( ! m_Sema )
116     {
117 IND ******itkExceptionMacro( << " sem_init call failed with code " << m_Sema );
118     }
119   
120 #endif
121 #ifdef ITK_USE_PTHREADS
122
123 m_PThreadsSemaphoreRemoved = false;
124
125 #if defined sun
126   if ( sema_init(&m_Sema, 0, value, NULL ) != 0 )
127     {
128     itkExceptionMacro( << "sema_init call failed" );
129     }
130 #elif defined  __APPLE__
131   m_Sema  = sem_open( m_SemaphoreName.c_str(), O_CREAT, 0x0644, value );
132   if ( m_Sema == (sem_t *)SEM_FAILED )
133     {
134     //  perror("FAILED WITH ERROR:" );
135 LEN     itkExceptionMacro( << "sem_open call failed on " << m_SemaphoreName.c_str() );
136     }
137 #else
138   if ( sem_init(&m_Sema, 0, value) != 0 )
139     {
140       itkExceptionMacro( << "sem_init call failed" );
141     }
142 #endif // if defined sun
143
144 #endif // ifdef ITK_USE_PTHREADS
145 #endif // ifndef ITK_USE_UNIX_IPC_SEMAPHORES
146   
147 #ifdef ITK_USE_WIN32_THREADS
148   m_Sema = CreateSemaphore( 0, value, 0x7FFFFFFF, 0);
149   if (m_Sema == 0)
150     {
151       itkExceptionMacro( << "CreateSemaphore call failed" );
152     }
153 #endif
154 }
155   
156 void Semaphore::Up()
157 {
158 #ifdef ITK_USE_UNIX_IPC_SEMAPHORES
159   Semaphore::UnixIpcSemaphoreUp(m_Sema);
160 #endif
161   
162 #ifndef ITK_USE_UNIX_IPC_SEMAPHORES
163
164 #ifdef ITK_USE_SPROC
165   if (usvsema(m_Sema) == -1)
166     {
167       itkExceptionMacro( << "usvsema call failed." );
168     }
169 #endif
170 #ifdef ITK_USE_PTHREADS
171 #ifdef sun
172   if ( sema_post(&m_Sema) != 0 )
173     {
174       itkExceptionMacro( << "sema_post call failed." );
175     }
176 #else
177 #ifdef __APPLE__
178   if ( sem_post(m_Sema) != 0 )
179     {
180     itkExceptionMacro( << "sem_post call failed." );
181     }
182 #else
183   if ( sem_post(&m_Sema) != 0 )
184     {
185       itkExceptionMacro( << "sem_post call failed." );
186     }
187 #endif
188 #endif // ifdef sun
189 #endif
190
191 #endif  // ITK_USE_UNIX_SEMAPHORES
192   
193 #ifdef ITK_USE_WIN32_THREADS
194   if ( ! ReleaseSemaphore ((HANDLE) m_Sema, 1 , 0) )
195     {
196       itkExceptionMacro( << "Semaphore post call failed." );
197     }
198 #endif
199 }
200
201 void Semaphore::Down()
202 {
203 #ifdef ITK_USE_UNIX_IPC_SEMAPHORES
204   Semaphore::UnixIpcSemaphoreDown (m_Sema);
205 #endif
206   
207 #ifndef ITK_USE_UNIX_IPC_SEMAPHORES
208 #ifdef ITK_USE_SPROC
209   if (uspsema(m_Sema) == -1)
210     {
211       itkExceptionMacro( << "uspsema call failed." );
212     }
213 #endif
214 #ifdef ITK_USE_PTHREADS
215 #ifdef sun
216   if (sema_wait(&m_Sema) != 0)
217     {
218     itkExceptionMacro( << "sema_wait call failed." );
219     }
220 #else
221 #ifdef __APPLE__
222   if (sem_wait(m_Sema) != 0)
223     {
224       itkExceptionMacro( << "sem_wait call failed." );
225     }
226 #else
227   
228   if (sem_wait(&m_Sema) != 0)
229     {
230       itkExceptionMacro( << "sem_wait call failed." );
231     }
232 #endif
233 #endif
234 #endif
235 #endif
236
237 #ifdef ITK_USE_WIN32_THREADS
238   if ( WaitForSingleObject(m_Sema, INFINITE) == WAIT_FAILED )
239     {
240       itkExceptionMacro( << "WaitForSingleObject call failed. ");
241     }
242 #endif
243 }
244
245 Semaphore::~Semaphore()
246 {
247 #ifdef ITK_USE_UNIX_IPC_SEMAPHORES
248   if (m_Sema != -1)
249     {
250       this->Remove();
251     }
252 #endif
253   
254 #ifndef ITK_USE_UNIX_IPC_SEMAPHORES  
255 #ifdef ITK_USE_SPROC
256   if (m_Sema != 0)
257     {
258 IND ******this->Remove();
259     }
260 #endif
261 #ifdef ITK_USE_PTHREADS  
262   if(!m_PThreadsSemaphoreRemoved)
263     {
264     this->Remove();
265     }
266 #endif
267 #endif
268   
269 #ifdef ITK_USE_WIN32_THREADS
270   if (m_Sema != 0)
271     {
272 IND ******this->Remove();
273     }
274 #endif
275 }
276
277 void Semaphore::Remove()
278 {
279 #ifdef ITK_USE_UNIX_IPC_SEMAPHORES
280   if (m_Sema != -1)
281     {
282 IND ******Semaphore::UnixIpcSemaphoreRemove(m_Sema);
283 IND ******m_Sema= -1;
284     }
285 #endif
286   
287 #ifndef ITK_USE_UNIX_IPC_SEMAPHORES
288
289 #ifdef ITK_USE_SPROC
290   if (MultiThreader::GetThreadArena() != 0)
291     {
292     if (m_Sema != 0)
293       {
294       usfreesema(m_Sema, MultiThreader::GetThreadArena());
295       }
296     m_Sema = 0;
297     }
298 #endif
299
300 #ifdef ITK_USE_PTHREADS
301 IND m_PThreadsSemaphoreRemoved = true;
302 #ifdef sun
303   if ( sema_destroy(&m_Sema) != 0 )
304     {
305     itkExceptionMacro( << "sema_destroy call failed. " );
306     }
307 #else
308
309 #ifndef __sgi
310 #ifndef __APPLE__
311   // IRIX pthreads implementation of sem_destroy is buggy
312   if ( sem_destroy(&m_Sema) != 0 )
313     {
314     itkExceptionMacro( << "sem_destroy call failed. " );
315     }
316 LEN #else //Still need to close semaphore and delete the file descriptor on MacOSX, otherwise the shared memory space is eventually exhosted.
317 LEN   //Eventually (i.e. after several days of ITK regresssion testing) the semaphore creation process was failing with errno=ENOSPC
318 LEN   //This implementation detail was taken from http://developer.apple.com/macosx/multithreadedprogramming.html
319   if ( sem_close(this->m_Sema) !=0 )
320 IND ******{
321 IND *******itkExceptionMacro( << "sem_close call failed. " );
322       }
323   if ( sem_unlink(this->m_SemaphoreName.c_str()) !=0 )
324 IND ******{
325 IND *******itkExceptionMacro( << "sem_unlink call failed. " );
326 IND ******}
327 #endif
328 #endif
329
330 #endif  // sun
331 #endif // pthreads
332   
333 #endif // semaphores
334   //#endif
335   
336 #ifdef ITK_USE_WIN32_THREADS
337   if (m_Sema != 0)
338     {
339     CloseHandle(m_Sema);
340     }
341   m_Sema= 0;
342 #endif
343 }
344
345 #ifdef ITK_USE_UNIX_IPC_SEMAPHORES
346
347 // UnixIpcSemaphoreCreate: will return the semaphore id (system wide)
348 // of the semaphore number (key) you give.
349 // If no semaphore has been established for this number, one is created.
350 int Semaphore::UnixIpcSemaphoreCreate(int unix_semaphore_key)
351 {
352   int sid = -1;
353   std::string s; 
354  
355   if( (sid = semget( (key_t)unix_semaphore_key, 1, 0666 | IPC_CREAT )) == -1 )
356     {
357     s =  "Error# %i in function UnixIpcSemaphoreCreate. - ";
358     switch (errno)
359       {
360       case EEXIST:
361 IND ********s += "Semaphore already exists. - ";
362 IND ********break;
363       case ENOSPC:
364 IND ********s+= "System imposed limit on the number of semaphores is exceeded - ";
365 IND ********break;
366       case EACCES:
367 IND ********s+= "Permission is denied - ";
368 IND ********break;
369       }
370     itkExceptionMacro( << s.c_str() );
371     }
372   
373   return( sid );
374 }
375
376 // UnixIpcSemaphoreDown: the semaphore signal operation.
377 // sid must be the system wide semaphore number
378 // returned by UnixIpcSemaphoreCreate above
379 void Semaphore::UnixIpcSemaphoreDown(int sid)
380 {
381   Semaphore::UnixIpcSemaphoreCall(sid, -1);
382 }
383
384 // UnixIpcSemaphoreUp: the semaphore release operation.
385 // sid must be the system wide semaphore number
386 // returned by UnixIpcSemaphoreCreate above
387 void Semaphore::UnixIpcSemaphoreUp(int sid)
388 {
389   Semaphore::UnixIpcSemaphoreCall(sid, 1);
390 }
391
392 // UixIpcSemaphoreRemove: remove a semaphore from the system.
393 // sid must be the system wide semaphore number
394 // returned from UnixIpcSemaphoreCreate
395 void Semaphore::UnixIpcSemaphoreRemove(int sid)
396 {
397   std::string s;
398   
399   if( semctl( sid, 0, IPC_RMID, 0 ) == -1 )
400     {
401     s =  "Error removing semaphore %i - ";
402     switch (errno)
403       {
404       case EINVAL:
405 IND ********s +=  "Semaphore id# is not valid. - ";
406 IND ********break;
407       case EACCES:
408 IND ********s+=  "Permission is denied - ";
409 IND ********break;
410       case EPERM:
411 IND ********s+= "Permission is denied - ";
412 IND ********break;
413       }
414     itkExceptionMacro ( << s.c_str() );
415     }
416 }
417
418 // UnixIpcSemaphoreCall: makes the system call semop for your given
419 // semaphore and operation.
420 void Semaphore::UnixIpcSemaphoreCall (int sid, int op)
421 {
422   struct sembuf sb;
423   std::string s;
424   
425   sb.sem_num = 0;
426   sb.sem_op = op;
427   sb.sem_flg = 0;
428   if( semop( sid, &sb, 1 ) == -1 )
429     {
430     
431     if( op == -1 )
432       {
433       s =  "Error %i in UnixIpcSemaphoreDown call for semaphore %i - ";
434       }
435     else
436       {
437       s =  "Error %i in UnixIpcSemaphoreUp call for semaphore %i - ";
438       }
439     switch (errno)
440       {
441       case EINVAL:
442 IND ********s +=  "Semaphore id# is not valid. -";
443 IND ********break;
444       case EFBIG:
445 IND ********s +=  "Invalid sem_num for semaphore - ";
446 IND ********break;
447       case EACCES:
448 IND ********s += "Permission denied for semaphore - ";
449 IND ********break;
450       case EAGAIN:
451 LEN,IND ********s += "The operation would result in suspension of the calling process but NOWAIT is true.";
452 IND ********break;
453       case EIDRM:
454 IND ********s += "The semid is removed from the system.";
455 IND ********break;
456       }
457     itkExceptionMacro( << s.c_str() );
458     }
459 }
460
461 #endif
462
463 }//end if namespace itk
464
465 #endif
466

Generated by KWStyle 1.0b on Tuesday January,17 at 02:14:45PM
© Kitware Inc.