#include <SV_Semaphore_Complex.h>
Inheritance diagram for ACE_SV_Semaphore_Complex:


Public Types | |
| enum | { ACE_CREATE = IPC_CREAT, ACE_OPEN = 0 } | 
Public Member Functions | |
| ACE_SV_Semaphore_Complex (void) | |
| ACE_SV_Semaphore_Complex (key_t key, short create=ACE_SV_Semaphore_Complex::ACE_CREATE, int initial_value=1, u_short nsems=1, mode_t perms=ACE_DEFAULT_FILE_PERMS) | |
| ACE_SV_Semaphore_Complex (const char *name, short create=ACE_SV_Semaphore_Complex::ACE_CREATE, int initial_value=1, u_short nsems=1, mode_t perms=ACE_DEFAULT_FILE_PERMS) | |
| ~ACE_SV_Semaphore_Complex (void) | |
| int | open (const char *name, short flags=ACE_SV_Semaphore_Simple::ACE_CREATE, int initial_value=1, u_short nsems=1, mode_t perms=ACE_DEFAULT_FILE_PERMS) | 
| int | open (key_t key, short flags=ACE_SV_Semaphore_Simple::ACE_CREATE, int initial_value=1, u_short nsems=1, mode_t perms=ACE_DEFAULT_FILE_PERMS) | 
| int | close (void) | 
| int | acquire (u_short n=0, short flags=0) const | 
| Acquire the semaphore.   | |
| int | acquire_read (u_short n=0, short flags=0) const | 
| Acquire a semaphore for reading.   | |
| int | acquire_write (u_short n=0, short flags=0) const | 
| Acquire a semaphore for writing.   | |
| int | tryacquire (u_short n=0, short flags=0) const | 
| Try to acquire the semaphore.   | |
| int | tryacquire_read (u_short n=0, short flags=0) const | 
| Try to acquire the semaphore for reading.   | |
| int | tryacquire_write (u_short n=0, short flags=0) const | 
| Try to acquire the semaphore for writing.   | |
| int | release (u_short n=0, short flags=0) const | 
| Release the semaphore.   | |
| int | op (short val, u_short n=0, short flags=0) const | 
| int | op (sembuf op_vec[], u_short n) const | 
| General ACE_SV_Semaphore operation on an array of SV_Semaphores.   | |
| int | control (int cmd, semun arg, u_short n=0) const | 
| int | control (int cmd, int value=0, u_short n=0) const | 
| void | dump (void) const | 
| Dump the state of an object.   | |
| int | get_id (void) const | 
| Get underlying internal id.   | |
| int | remove (void) const | 
Public Attributes | |
| ACE_ALLOC_HOOK_DECLARE | |
| Declare the dynamic allocation hooks.   | |
Static Private Attributes | |
| const int | BIGCOUNT_ = 10000 | 
| sembuf | op_lock_ [2] | 
| sembuf | op_endcreate_ [2] | 
| sembuf | op_open_ [1] | 
| sembuf | op_close_ [3] | 
| sembuf | op_unlock_ [1] | 
This code is a port to C++, inspired by: W. Richard Stevens from his book: UNIX Network Programming (Prentice Hall, ISBN 0-13-949876-1 - 1990). We provide a simpler and easier to understand interface to the System V Semaphore system calls. We create and use a 2 + n-member set for the requested . The first member, [0], is a counter used to know when all processes have finished with the . The counter is initialized to a large number, decremented on every create or open and incremented on every close. This way we can use the "adjust" feature provided by System V so that any process that exit's without calling is accounted for. It doesn't help us if the last process does this (as we have no way of getting control to remove the ) but it will work if any process other than the last does an exit (intentional or unintentional). The second member, [1], of the semaphore is used as a lock variable to avoid any race conditions in the and functions. The members beyond [1] are actual semaphore values in the array of semaphores, which may be sized by the user in the constructor.
Definition at line 54 of file SV_Semaphore_Complex.h.
      
  | 
  
| 
 
 Definition at line 57 of file SV_Semaphore_Complex.h. 
 00058   {
00059     ACE_CREATE = IPC_CREAT,
00060     ACE_OPEN   = 0
00061   };
 | 
  
      
  | 
  
| 
 
 Definition at line 253 of file SV_Semaphore_Complex.cpp. References ACE_TRACE, and ACE_SV_Semaphore_Simple::init(). 
  | 
  
      
  | 
  ||||||||||||||||||||||||
| 
 
 Definition at line 216 of file SV_Semaphore_Complex.cpp. References ACE_ERROR, ACE_TEXT, ACE_TRACE, LM_ERROR, mode_t, and open(). 
  | 
  
      
  | 
  ||||||||||||||||||||||||
| 
 
 Definition at line 227 of file SV_Semaphore_Complex.cpp. References ACE_DEFAULT_SEM_KEY, ACE_ERROR, ACE_TEXT, ACE_TRACE, LM_ERROR, mode_t, ACE_SV_Semaphore_Simple::name_2_key(), and open(). 
 00232 {
00233   ACE_TRACE ("ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex");
00234 
00235   key_t key;
00236 
00237   if (name == 0)
00238     key = ACE_DEFAULT_SEM_KEY;
00239   else
00240     key = this->name_2_key (name);
00241 
00242   if (this->open (key, flags, initial_value, nsems, perms) == -1)
00243     ACE_ERROR ((LM_ERROR,  ACE_TEXT ("%p\n"),  ACE_TEXT ("ACE_SV_Semaphore_Complex")));
00244 }
 | 
  
      
  | 
  
| 
 
 Definition at line 246 of file SV_Semaphore_Complex.cpp. References ACE_TRACE, and close(). 
 00247 {
00248   ACE_TRACE ("ACE_SV_Semaphore_Complex::~ACE_SV_Semaphore_Complex");
00249   if (this->internal_id_ >= 0)
00250     this->close ();
00251 }
 | 
  
      
  | 
  ||||||||||||
| 
 Acquire the semaphore. 
 Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 8 of file SV_Semaphore_Complex.inl. References ACE_TRACE, and ACE_SV_Semaphore_Simple::acquire(). Referenced by acquire_read(), and acquire_write(). 
 00009 {
00010   ACE_TRACE ("ACE_SV_Semaphore_Complex::acquire");
00011   return ACE_SV_Semaphore_Simple::acquire ((u_short) n + 2, flags);
00012 }
 | 
  
      
  | 
  ||||||||||||
| 
 Acquire a semaphore for reading. 
 Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 15 of file SV_Semaphore_Complex.inl. References ACE_TRACE, and acquire(). 
  | 
  
      
  | 
  ||||||||||||
| 
 Acquire a semaphore for writing. 
 Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 22 of file SV_Semaphore_Complex.inl. References ACE_TRACE, and acquire(). 
  | 
  
      
  | 
  
| 
 Close an ACE_SV_Semaphore. Unlike the method, this method is for a process to call before it exits, when it is done with the ACE_SV_Semaphore. We "decrement" the counter of processes using the ACE_SV_Semaphore, and if this was the last one, we can remove the ACE_SV_Semaphore. Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 180 of file SV_Semaphore_Complex.cpp. References ACE_TRACE, BIGCOUNT_, ACE_SV_Semaphore_Simple::control(), GETVAL, ACE_SV_Semaphore_Simple::init(), op_close_, op_unlock_, ACE_SV_Semaphore_Simple::remove(), and ACE_OS::semop(). Referenced by ~ACE_SV_Semaphore_Complex(). 
 00181 {
00182   ACE_TRACE ("ACE_SV_Semaphore_Complex::close");
00183   int semval;
00184 
00185   if (this->key_ == (key_t) - 1 || this->internal_id_ == -1)
00186     return -1;
00187 
00188   // The following semop() first gets a lock on the ACE_SV_Semaphore,
00189   // then increments [1] - the process number.
00190 
00191   if (ACE_OS::semop (this->internal_id_,
00192                      &ACE_SV_Semaphore_Complex::op_close_[0],
00193                      3) == -1)
00194     return -1;
00195 
00196   // Now that we have a lock, read the value of the process counter to
00197   // see if this is the last reference to the ACE_SV_Semaphore. There
00198   // is a race condition here - see the comments in create ().
00199 
00200   if ((semval = ACE_SV_Semaphore_Simple::control (GETVAL, 0, 1)) == -1)
00201     return -1;
00202 
00203   if (semval > ACE_SV_Semaphore_Complex::BIGCOUNT_)
00204     return -1;
00205   else if (semval == ACE_SV_Semaphore_Complex::BIGCOUNT_)
00206     return this->remove ();
00207   else
00208     {
00209       int result = ACE_OS::semop (this->internal_id_,
00210                                   &ACE_SV_Semaphore_Complex::op_unlock_[0], 1);
00211       this->init ();
00212       return result;
00213     }
00214 }
 | 
  
      
  | 
  ||||||||||||||||
| 
 
 Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 78 of file SV_Semaphore_Complex.inl. References ACE_TRACE, and ACE_SV_Semaphore_Simple::control(). 
 00079 {
00080   ACE_TRACE ("ACE_SV_Semaphore_Complex::control");
00081   return ACE_SV_Semaphore_Simple::control (cmd, value, (u_short) n + 2);
00082 }
 | 
  
      
  | 
  ||||||||||||||||
| 
 
 Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 71 of file SV_Semaphore_Complex.inl. References ACE_TRACE, and ACE_SV_Semaphore_Simple::control(). Referenced by open(). 
 00072 {
00073   ACE_TRACE ("ACE_SV_Semaphore_Complex::control");
00074   return ACE_SV_Semaphore_Simple::control (cmd, arg, (u_short) n + 2);
00075 }
 | 
  
      
  | 
  
| 
 Dump the state of an object. 
 Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 19 of file SV_Semaphore_Complex.cpp. References ACE_TRACE. 
 00020 {
00021 #if defined (ACE_HAS_DUMP)
00022   ACE_TRACE ("ACE_SV_Semaphore_Complex::dump");
00023 #endif /* ACE_HAS_DUMP */
00024 }
 | 
  
      
  | 
  
| 
 Get underlying internal id. 
 Definition at line 122 of file SV_Semaphore_Simple.inl. 
 00123 {
00124   ACE_TRACE ("ACE_SV_Semaphore_Simple::get_id");
00125   return this->internal_id_;
00126 }
 | 
  
      
  | 
  ||||||||||||
| 
 General ACE_SV_Semaphore operation on an array of SV_Semaphores. 
 Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 64 of file SV_Semaphore_Complex.inl. References ACE_TRACE, and ACE_SV_Semaphore_Simple::op(). 
 00065 {
00066   ACE_TRACE ("ACE_SV_Semaphore_Complex::op");
00067   return ACE_SV_Semaphore_Simple::op (op_vec, (u_short) n + 2);
00068 }
 | 
  
      
  | 
  ||||||||||||||||
| 
 General ACE_SV_Semaphore operation. Increment or decrement by a specific amount (positive or negative; amount can`t be zero). Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 57 of file SV_Semaphore_Complex.inl. References ACE_TRACE, and ACE_SV_Semaphore_Simple::op(). 
 00058 {
00059   ACE_TRACE ("ACE_SV_Semaphore_Complex::op");
00060   return ACE_SV_Semaphore_Simple::op (val, (u_short) n + 2, flags);
00061 }
 | 
  
      
  | 
  ||||||||||||||||||||||||
| 
 Open or create an array of SV_Semaphores. We return 0 if all is OK, else -1. Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 67 of file SV_Semaphore_Complex.cpp. References ACE_CREATE, ACE_TRACE, BIGCOUNT_, control(), ACE_SV_Semaphore_Simple::control(), EIDRM, GETVAL, ACE_SV_Semaphore_Simple::init(), IPC_PRIVATE, mode_t, op_endcreate_, op_lock_, op_open_, ACE_OS::semget(), ACE_OS::semop(), and SETVAL. 
 00072 {
00073   ACE_TRACE ("ACE_SV_Semaphore_Complex::open");
00074   if (k == IPC_PRIVATE)
00075     return -1;
00076 
00077   this->key_ = k;
00078 
00079   // Must include a count for the 2 additional semaphores we use
00080   // internally.
00081   this->sem_number_ = nsems + 2;
00082 
00083   if (create == ACE_SV_Semaphore_Complex::ACE_CREATE)
00084     {
00085       int result;
00086 
00087       do
00088         {
00089           this->internal_id_ = ACE_OS::semget
00090             (this->key_,
00091              (u_short) 2 + nsems,
00092              perms | ACE_SV_Semaphore_Complex::ACE_CREATE);
00093 
00094           if (this->internal_id_ == -1)
00095             return -1; // permission problem or tables full
00096 
00097           // When the <ACE_SV_Semaphore_Complex> is created, we know
00098           // that the value of all 3 members is 0.  Get a lock on the
00099           // <ACE_SV_Semaphore_Complex> by waiting for [0] to equal 0,
00100           // then increment it.
00101 
00102           // There is a race condition here. There is the possibility
00103           // that between the <semget> above and the <semop> below,
00104           // another process can call out <close> function which can
00105           // remove the <ACE_SV_Semaphore> if that process is the last
00106           // one using it.  Therefor we handle the error condition of
00107           // an invalid <ACE_SV_Semaphore> ID specifically below, and
00108           // if it does happen, we just go back and create it again.
00109           result = ACE_OS::semop (this->internal_id_,
00110                                   &ACE_SV_Semaphore_Complex::op_lock_[0],
00111                                   2);
00112         }
00113       while (result == -1 && (errno == EINVAL || errno == EIDRM));
00114 
00115       if (result == -1)
00116         return -1;
00117 
00118       // Get the value of the process counter. If it equals 0, then no
00119       // one has initialized the ACE_SV_Semaphore yet.
00120 
00121       int semval = ACE_SV_Semaphore_Simple::control (GETVAL, 0, 1);
00122 
00123       if (semval == -1)
00124         return this->init ();
00125       else if (semval == 0)
00126         {
00127           // We should initialize by doing a SETALL, but that would
00128           // clear the adjust value that we set when we locked the
00129           // ACE_SV_Semaphore above. Instead we do system calls to
00130           // initialize [1], as well as all the nsems SV_Semaphores.
00131 
00132           if (ACE_SV_Semaphore_Simple::control (SETVAL,
00133                                                 ACE_SV_Semaphore_Complex::BIGCOUNT_,
00134                                                 1) == -1)
00135             return -1;
00136           else
00137             for (u_short i = 0; i < nsems; i++)
00138               if (this->control (SETVAL, initial_value, i) == -1)
00139                 return -1;
00140         }
00141 
00142       // Decrement the process counter and then release the lock.
00143       return ACE_OS::semop (this->internal_id_,
00144                             &ACE_SV_Semaphore_Complex::op_endcreate_[0],
00145                             2);
00146     }
00147   else
00148     {
00149       this->internal_id_ = ACE_OS::semget (this->key_, 2 + nsems, 0);
00150       if (this->internal_id_ == -1)
00151         return -1;                      // doesn't exist or tables full
00152 
00153       // Decrement the process counter. We don't need a lock to do this.
00154       if (ACE_OS::semop (this->internal_id_,
00155                          &ACE_SV_Semaphore_Complex::op_open_[0], 1) < 0)
00156         return this->init ();
00157       return 0;
00158     }
00159 }
 | 
  
      
  | 
  ||||||||||||||||||||||||
| 
 Open or create an array of SV_Semaphores. We return 0 if all is OK, else -1. Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 162 of file SV_Semaphore_Complex.cpp. References ACE_TRACE, and mode_t. Referenced by ACE_SV_Semaphore_Complex(). 
  | 
  
      
  | 
  ||||||||||||
| 
 Release the semaphore. 
 Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 50 of file SV_Semaphore_Complex.inl. References ACE_TRACE, and ACE_SV_Semaphore_Simple::release(). 
 00051 {
00052   ACE_TRACE ("ACE_SV_Semaphore_Complex::release");
00053   return ACE_SV_Semaphore_Simple::release ((u_short) n + 2, flags);
00054 }
 | 
  
      
  | 
  
| 
 Remove all SV_Semaphores associated with a particular key. This call is intended to be called from a server, for example, when it is being shut down, as we do an IPC_RMID on the ACE_SV_Semaphore, regardless of whether other processes may be using it or not. Most other processes should use below. Definition at line 229 of file SV_Semaphore_Simple.cpp. 
 00230 {
00231   ACE_TRACE ("ACE_SV_Semaphore_Simple::remove");
00232   int const result = this->control (IPC_RMID);
00233   ((ACE_SV_Semaphore_Simple *) this)->init ();
00234   return result;
00235 }
 | 
  
      
  | 
  ||||||||||||
| 
 Try to acquire the semaphore. 
 Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 29 of file SV_Semaphore_Complex.inl. References ACE_TRACE, and ACE_SV_Semaphore_Simple::tryacquire(). Referenced by tryacquire_read(), and tryacquire_write(). 
 00030 {
00031   ACE_TRACE ("ACE_SV_Semaphore_Complex::tryacquire");
00032   return ACE_SV_Semaphore_Simple::tryacquire ((u_short) n + 2, flags);
00033 }
 | 
  
      
  | 
  ||||||||||||
| 
 Try to acquire the semaphore for reading. 
 Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 36 of file SV_Semaphore_Complex.inl. References ACE_TRACE, and tryacquire(). 
 00037 {
00038   ACE_TRACE ("ACE_SV_Semaphore_Complex::tryacquire_read");
00039   return this->tryacquire (n, flags);
00040 }
 | 
  
      
  | 
  ||||||||||||
| 
 Try to acquire the semaphore for writing. 
 Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 43 of file SV_Semaphore_Complex.inl. References ACE_TRACE, and tryacquire(). 
 00044 {
00045   ACE_TRACE ("ACE_SV_Semaphore_Complex::tryacquire_write");
00046   return this->tryacquire (n, flags);
00047 }
 | 
  
      
  | 
  
| 
 Declare the dynamic allocation hooks. 
 Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 141 of file SV_Semaphore_Complex.h.  | 
  
      
  | 
  
| 
 
 Definition at line 27 of file SV_Semaphore_Complex.cpp.  | 
  
      
  | 
  
| 
 Initial value: Definition at line 52 of file SV_Semaphore_Complex.cpp. Referenced by close().  | 
  
      
  | 
  
| 
 Initial value: Definition at line 38 of file SV_Semaphore_Complex.cpp. Referenced by open().  | 
  
      
  | 
  
| 
 Initial value: 
{
  {0, 0, 0},                    
  {0, 1, SEM_UNDO},             
                                
                                
}
Definition at line 30 of file SV_Semaphore_Complex.cpp. Referenced by open().  | 
  
      
  | 
  
| 
 Initial value: 
{
  {1, -1, SEM_UNDO},            
                                
}
Definition at line 46 of file SV_Semaphore_Complex.cpp. Referenced by open().  | 
  
      
  | 
  
| 
 Initial value: 
{
  {0, -1, SEM_UNDO},            
}
Definition at line 59 of file SV_Semaphore_Complex.cpp. Referenced by close().  | 
  
 
1.3.6