ACE_SV_Semaphore_Complex Class Reference

This is a more complex semaphore wrapper that handles race conditions for initialization correctly... More...

#include <SV_Semaphore_Complex.h>

Inheritance diagram for ACE_SV_Semaphore_Complex:

Inheritance graph
[legend]
Collaboration diagram for ACE_SV_Semaphore_Complex:

Collaboration graph
[legend]
List of all members.

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]

Detailed Description

This is a more complex semaphore wrapper that handles race conditions for initialization correctly...

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.


Member Enumeration Documentation

anonymous enum
 

Enumeration values:
ACE_CREATE 
ACE_OPEN 

Definition at line 57 of file SV_Semaphore_Complex.h.

00058   {
00059     ACE_CREATE = IPC_CREAT,
00060     ACE_OPEN   = 0
00061   };


Constructor & Destructor Documentation

ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex void   ) 
 

Definition at line 253 of file SV_Semaphore_Complex.cpp.

References ACE_TRACE, and ACE_SV_Semaphore_Simple::init().

00254 {
00255   ACE_TRACE ("ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex");
00256   this->init ();
00257 }

ACE_SV_Semaphore_Complex::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
 

Definition at line 216 of file SV_Semaphore_Complex.cpp.

References ACE_ERROR, ACE_LIB_TEXT, ACE_TRACE, LM_ERROR, mode_t, and open().

00221 {
00222   ACE_TRACE ("ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex");
00223   if (this->open (k, flags, initial_value, nsems, perms) == -1)
00224     ACE_ERROR ((LM_ERROR,  ACE_LIB_TEXT ("%p\n"),  ACE_LIB_TEXT ("ACE_SV_Semaphore_Complex")));
00225 }

ACE_SV_Semaphore_Complex::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
 

Definition at line 227 of file SV_Semaphore_Complex.cpp.

References ACE_DEFAULT_SEM_KEY, ACE_ERROR, ACE_LIB_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_LIB_TEXT ("%p\n"),  ACE_LIB_TEXT ("ACE_SV_Semaphore_Complex")));
00244 }

ACE_SV_Semaphore_Complex::~ACE_SV_Semaphore_Complex void   ) 
 

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 }


Member Function Documentation

ACE_BEGIN_VERSIONED_NAMESPACE_DECL ACE_INLINE int ACE_SV_Semaphore_Complex::acquire u_short  n = 0,
short  flags = 0
const
 

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 }

ACE_INLINE int ACE_SV_Semaphore_Complex::acquire_read u_short  n = 0,
short  flags = 0
const
 

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().

00016 {
00017   ACE_TRACE ("ACE_SV_Semaphore_Complex::acquire_read");
00018   return this->acquire (n, flags);
00019 }

ACE_INLINE int ACE_SV_Semaphore_Complex::acquire_write u_short  n = 0,
short  flags = 0
const
 

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().

00023 {
00024   ACE_TRACE ("ACE_SV_Semaphore_Complex::acquire_write");
00025   return this->acquire (n, flags);
00026 }

int ACE_SV_Semaphore_Complex::close void   ) 
 

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 }

ACE_INLINE int ACE_SV_Semaphore_Complex::control int  cmd,
int  value = 0,
u_short  n = 0
const
 

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 }

ACE_INLINE int ACE_SV_Semaphore_Complex::control int  cmd,
semun  arg,
u_short  n = 0
const
 

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 }

ACE_BEGIN_VERSIONED_NAMESPACE_DECL void ACE_SV_Semaphore_Complex::dump void   )  const
 

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 }

ACE_INLINE int ACE_SV_Semaphore_Simple::get_id void   )  const
 

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 }

ACE_INLINE int ACE_SV_Semaphore_Complex::op sembuf  op_vec[],
u_short  n
const
 

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 }

ACE_INLINE int ACE_SV_Semaphore_Complex::op short  val,
u_short  n = 0,
short  flags = 0
const
 

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 }

int ACE_SV_Semaphore_Complex::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
 

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 }

int ACE_SV_Semaphore_Complex::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
 

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().

00167 {
00168   ACE_TRACE ("ACE_SV_Semaphore_Complex::open");
00169   return this->open (ACE_SV_Semaphore_Simple::name_2_key (name),
00170                      flags, initial_value, nsems, perms);
00171 }

ACE_INLINE int ACE_SV_Semaphore_Complex::release u_short  n = 0,
short  flags = 0
const
 

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 }

int ACE_SV_Semaphore_Simple::remove void   )  const
 

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 result = this->control (IPC_RMID);
00233   ((ACE_SV_Semaphore_Simple *) this)->init ();
00234   return result;
00235 }

ACE_INLINE int ACE_SV_Semaphore_Complex::tryacquire u_short  n = 0,
short  flags = 0
const
 

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 }

ACE_INLINE int ACE_SV_Semaphore_Complex::tryacquire_read u_short  n = 0,
short  flags = 0
const
 

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 }

ACE_INLINE int ACE_SV_Semaphore_Complex::tryacquire_write u_short  n = 0,
short  flags = 0
const
 

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 }


Member Data Documentation

ACE_SV_Semaphore_Complex::ACE_ALLOC_HOOK_DECLARE
 

Declare the dynamic allocation hooks.

Reimplemented from ACE_SV_Semaphore_Simple.

Definition at line 141 of file SV_Semaphore_Complex.h.

const int ACE_SV_Semaphore_Complex::BIGCOUNT_ = 10000 [static, private]
 

Definition at line 27 of file SV_Semaphore_Complex.cpp.

Referenced by close(), and open().

sembuf ACE_SV_Semaphore_Complex::op_close_ [static, private]
 

Initial value:

{
  {0, 0, 0},                    
  {0, 1, SEM_UNDO},             
  {1, 1, SEM_UNDO},             
}

Definition at line 52 of file SV_Semaphore_Complex.cpp.

Referenced by close().

sembuf ACE_SV_Semaphore_Complex::op_endcreate_ [static, private]
 

Initial value:

{
  {1, -1, SEM_UNDO},            
                                
                                
  {0, -1, SEM_UNDO},            
}

Definition at line 38 of file SV_Semaphore_Complex.cpp.

Referenced by open().

sembuf ACE_SV_Semaphore_Complex::op_lock_ [static, private]
 

Initial value:

{
  {0, 0, 0},                    
  {0, 1, SEM_UNDO},             
                                
                                
}

Definition at line 30 of file SV_Semaphore_Complex.cpp.

Referenced by open().

sembuf ACE_SV_Semaphore_Complex::op_open_ [static, private]
 

Initial value:

{
  {1, -1, SEM_UNDO},            
                                
}

Definition at line 46 of file SV_Semaphore_Complex.cpp.

Referenced by open().

sembuf ACE_SV_Semaphore_Complex::op_unlock_ [static, private]
 

Initial value:

{
  {0, -1, SEM_UNDO},            
}

Definition at line 59 of file SV_Semaphore_Complex.cpp.

Referenced by close().


The documentation for this class was generated from the following files:
Generated on Thu Nov 9 11:30:34 2006 for ACE by doxygen 1.3.6