Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

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 Methods

 ACE_SV_Semaphore_Complex (void)
 ACE_SV_Semaphore_Complex (key_t key, int create=ACE_SV_Semaphore_Complex::ACE_CREATE, int initial_value=1, u_short nsems=1, int perms=ACE_DEFAULT_FILE_PERMS)
 ACE_SV_Semaphore_Complex (const char *name, int create=ACE_SV_Semaphore_Complex::ACE_CREATE, int initial_value=1, u_short nsems=1, int perms=ACE_DEFAULT_FILE_PERMS)
 ~ACE_SV_Semaphore_Complex (void)
int open (const char *name, int flags=ACE_SV_Semaphore_Simple::ACE_CREATE, int initial_value=1, u_short nsems=1, int perms=ACE_DEFAULT_FILE_PERMS)
 Open or create an array of SV_Semaphores. We return 0 if all is OK, else -1. More...

int open (key_t key, int flags=ACE_SV_Semaphore_Simple::ACE_CREATE, int initial_value=1, u_short nsems=1, int perms=ACE_DEFAULT_FILE_PERMS)
 Open or create an array of SV_Semaphores. We return 0 if all is OK, else -1. More...

int close (void)
int acquire (u_short n=0, int flags=0) const
 Acquire the semaphore. More...

int acquire_read (u_short n=0, int flags=0) const
 Acquire a semaphore for reading. More...

int acquire_write (u_short n=0, int flags=0) const
 Acquire a semaphore for writing. More...

int tryacquire (u_short n=0, int flags=0) const
 Try to acquire the semaphore. More...

int tryacquire_read (u_short n=0, int flags=0) const
 Try to acquire the semaphore for reading. More...

int tryacquire_write (u_short n=0, int flags=0) const
 Try to acquire the semaphore for writing. More...

int release (u_short n=0, int flags=0) const
 Release the semaphore. More...

int op (int val, u_short n=0, int flags=0) const
 General ACE_SV_Semaphore operation. Increment or decrement by a specific amount (positive or negative; amount can`t be zero). More...

int op (sembuf op_vec[], u_short n) const
 General ACE_SV_Semaphore operation on an array of SV_Semaphores. More...

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. More...


Public Attributes

 ACE_ALLOC_HOOK_DECLARE
 Declare the dynamic allocation hooks. More...


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 <ACE_SV_Semaphore_Complex>. The first member, [0], is a counter used to know when all processes have finished with the <ACE_SV_Semaphore_Complex>. 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 <close> 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 <ACE_SV_Semaphore_Complex>) 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 <create> and <close> 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 52 of file SV_Semaphore_Complex.h.


Member Enumeration Documentation

anonymous enum
 

Enumeration values:
ACE_CREATE 
ACE_OPEN 

Definition at line 55 of file SV_Semaphore_Complex.h.

00056   {
00057     ACE_CREATE = IPC_CREAT,
00058     ACE_OPEN   = 0
00059   };


Constructor & Destructor Documentation

ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex void   
 

Definition at line 249 of file SV_Semaphore_Complex.cpp.

References ACE_TRACE, and ACE_SV_Semaphore_Simple::init.

00250 {
00251   ACE_TRACE ("ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex");
00252   this->init ();
00253 }

ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex key_t    key,
int    create = ACE_SV_Semaphore_Complex::ACE_CREATE,
int    initial_value = 1,
u_short    nsems = 1,
int    perms = ACE_DEFAULT_FILE_PERMS
 

Definition at line 212 of file SV_Semaphore_Complex.cpp.

References ACE_ERROR, ACE_LIB_TEXT, ACE_TRACE, LM_ERROR, and open.

00217 {
00218   ACE_TRACE ("ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex");
00219   if (this->open (k, flags, initial_value, nsems, perms) == -1)
00220     ACE_ERROR ((LM_ERROR,  ACE_LIB_TEXT ("%p\n"),  ACE_LIB_TEXT ("ACE_SV_Semaphore_Complex")));
00221 }

ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex const char *    name,
int    create = ACE_SV_Semaphore_Complex::ACE_CREATE,
int    initial_value = 1,
u_short    nsems = 1,
int    perms = ACE_DEFAULT_FILE_PERMS
 

Definition at line 223 of file SV_Semaphore_Complex.cpp.

References ACE_DEFAULT_SEM_KEY, ACE_ERROR, ACE_LIB_TEXT, ACE_TRACE, LM_ERROR, ACE_SV_Semaphore_Simple::name_2_key, and open.

00228 {
00229   ACE_TRACE ("ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex");
00230 
00231   key_t key;
00232 
00233   if (name == 0)
00234     key = ACE_DEFAULT_SEM_KEY;
00235   else
00236     key = this->name_2_key (name);
00237 
00238   if (this->open (key, flags, initial_value, nsems, perms) == -1)
00239     ACE_ERROR ((LM_ERROR,  ACE_LIB_TEXT ("%p\n"),  ACE_LIB_TEXT ("ACE_SV_Semaphore_Complex")));
00240 }

ACE_SV_Semaphore_Complex::~ACE_SV_Semaphore_Complex void   
 

Definition at line 242 of file SV_Semaphore_Complex.cpp.

References ACE_TRACE, close, and ACE_SV_Semaphore_Simple::internal_id_.

00243 {
00244   ACE_TRACE ("ACE_SV_Semaphore_Complex::~ACE_SV_Semaphore_Complex");
00245   if (this->internal_id_ >= 0)
00246     this->close ();
00247 }


Member Function Documentation

ASYS_INLINE int ACE_SV_Semaphore_Complex::acquire u_short    n = 0,
int    flags = 0
const
 

Acquire the semaphore.

Reimplemented from ACE_SV_Semaphore_Simple.

Definition at line 9 of file SV_Semaphore_Complex.i.

References ACE_TRACE, and ACE_SV_Semaphore_Simple::acquire.

Referenced by acquire_read, and acquire_write.

00010 {
00011   ACE_TRACE ("ACE_SV_Semaphore_Complex::acquire");
00012   return ACE_SV_Semaphore_Simple::acquire ((u_short) n + 2, flags);
00013 }

ASYS_INLINE int ACE_SV_Semaphore_Complex::acquire_read u_short    n = 0,
int    flags = 0
const
 

Acquire a semaphore for reading.

Reimplemented from ACE_SV_Semaphore_Simple.

Definition at line 16 of file SV_Semaphore_Complex.i.

References ACE_TRACE, and acquire.

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

ASYS_INLINE int ACE_SV_Semaphore_Complex::acquire_write u_short    n = 0,
int    flags = 0
const
 

Acquire a semaphore for writing.

Reimplemented from ACE_SV_Semaphore_Simple.

Definition at line 23 of file SV_Semaphore_Complex.i.

References ACE_TRACE, and acquire.

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

int ACE_SV_Semaphore_Complex::close void   
 

Close an ACE_SV_Semaphore. Unlike the <remove> 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 176 of file SV_Semaphore_Complex.cpp.

References ACE_TRACE, BIGCOUNT_, ACE_SV_Semaphore_Simple::control, GETVAL, ACE_SV_Semaphore_Simple::init, ACE_SV_Semaphore_Simple::internal_id_, ACE_SV_Semaphore_Simple::key_, op_close_, op_unlock_, ACE_SV_Semaphore_Simple::remove, and ACE_OS::semop.

Referenced by ~ACE_SV_Semaphore_Complex.

00177 {
00178   ACE_TRACE ("ACE_SV_Semaphore_Complex::close");
00179   int semval;
00180 
00181   if (this->key_ == (key_t) - 1 || this->internal_id_ == -1)
00182     return -1;
00183 
00184   // The following semop() first gets a lock on the ACE_SV_Semaphore,
00185   // then increments [1] - the process number.
00186 
00187   if (ACE_OS::semop (this->internal_id_,
00188                      &ACE_SV_Semaphore_Complex::op_close_[0],
00189                      3) == -1)
00190     return -1;
00191 
00192   // Now that we have a lock, read the value of the process counter to
00193   // see if this is the last reference to the ACE_SV_Semaphore. There
00194   // is a race condition here - see the comments in create ().
00195 
00196   if ((semval = ACE_SV_Semaphore_Simple::control (GETVAL, 0, 1)) == -1)
00197     return -1;
00198 
00199   if (semval > ACE_SV_Semaphore_Complex::BIGCOUNT_)
00200     return -1;
00201   else if (semval == ACE_SV_Semaphore_Complex::BIGCOUNT_)
00202     return this->remove ();
00203   else
00204     {
00205       int result = ACE_OS::semop (this->internal_id_,
00206                                   &ACE_SV_Semaphore_Complex::op_unlock_[0], 1);
00207       this->init ();
00208       return result;
00209     }
00210 }

ASYS_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 79 of file SV_Semaphore_Complex.i.

References ACE_TRACE, and ACE_SV_Semaphore_Simple::control.

00080 {
00081   ACE_TRACE ("ACE_SV_Semaphore_Complex::control");
00082   return ACE_SV_Semaphore_Simple::control (cmd, value, (u_short) n + 2);
00083 }

ASYS_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 72 of file SV_Semaphore_Complex.i.

References ACE_TRACE, and ACE_SV_Semaphore_Simple::control.

Referenced by open.

00073 {
00074   ACE_TRACE ("ACE_SV_Semaphore_Complex::control");
00075   return ACE_SV_Semaphore_Simple::control (cmd, arg, (u_short) n + 2);
00076 }

void ACE_SV_Semaphore_Complex::dump void    const
 

Dump the state of an object.

Reimplemented from ACE_SV_Semaphore_Simple.

Definition at line 17 of file SV_Semaphore_Complex.cpp.

References ACE_TRACE.

00018 {
00019   ACE_TRACE ("ACE_SV_Semaphore_Complex::dump");
00020 }

ASYS_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 65 of file SV_Semaphore_Complex.i.

References ACE_TRACE, and ACE_SV_Semaphore_Simple::op.

00066 {
00067   ACE_TRACE ("ACE_SV_Semaphore_Complex::op");
00068   return ACE_SV_Semaphore_Simple::op (op_vec, (u_short) n + 2);
00069 }

ASYS_INLINE int ACE_SV_Semaphore_Complex::op int    val,
u_short    n = 0,
int    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 58 of file SV_Semaphore_Complex.i.

References ACE_TRACE, and ACE_SV_Semaphore_Simple::op.

00059 {
00060   ACE_TRACE ("ACE_SV_Semaphore_Complex::op");
00061   return ACE_SV_Semaphore_Simple::op (val, (u_short) n + 2, flags);
00062 }

int ACE_SV_Semaphore_Complex::open key_t    key,
int    flags = ACE_SV_Semaphore_Simple::ACE_CREATE,
int    initial_value = 1,
u_short    nsems = 1,
int    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 63 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, ACE_SV_Semaphore_Simple::internal_id_, IPC_PRIVATE, ACE_SV_Semaphore_Simple::key_, op_endcreate_, op_lock_, op_open_, ACE_SV_Semaphore_Simple::sem_number_, ACE_OS::semget, ACE_OS::semop, and SETVAL.

00068 {
00069   ACE_TRACE ("ACE_SV_Semaphore_Complex::open");
00070   if (k == IPC_PRIVATE)
00071     return -1;
00072 
00073   this->key_ = k;
00074 
00075   // Must include a count for the 2 additional semaphores we use
00076   // internally.
00077   this->sem_number_ = nsems + 2; 
00078 
00079   if (create == ACE_SV_Semaphore_Complex::ACE_CREATE)
00080     {
00081       int result;
00082 
00083       do
00084         {
00085           this->internal_id_ = ACE_OS::semget
00086             (this->key_,
00087              (u_short) 2 + nsems, 
00088              perms | ACE_SV_Semaphore_Complex::ACE_CREATE);
00089 
00090           if (this->internal_id_ == -1)
00091             return -1; // permission problem or tables full
00092 
00093           // When the <ACE_SV_Semaphore_Complex> is created, we know
00094           // that the value of all 3 members is 0.  Get a lock on the
00095           // <ACE_SV_Semaphore_Complex> by waiting for [0] to equal 0,
00096           // then increment it.
00097 
00098           // There is a race condition here. There is the possibility
00099           // that between the <semget> above and the <semop> below,
00100           // another process can call out <close> function which can
00101           // remove the <ACE_SV_Semaphore> if that process is the last
00102           // one using it.  Therefor we handle the error condition of
00103           // an invalid <ACE_SV_Semaphore> ID specifically below, and
00104           // if it does happen, we just go back and create it again.
00105           result = ACE_OS::semop (this->internal_id_,
00106                                   &ACE_SV_Semaphore_Complex::op_lock_[0],
00107                                   2);
00108         }
00109       while (result == -1 && (errno == EINVAL || errno == EIDRM));
00110 
00111       if (result == -1)
00112         return -1;
00113 
00114       // Get the value of the process counter. If it equals 0, then no
00115       // one has initialized the ACE_SV_Semaphore yet.
00116 
00117       int semval = ACE_SV_Semaphore_Simple::control (GETVAL, 0, 1);
00118 
00119       if (semval == -1)
00120         return this->init ();
00121       else if (semval == 0)
00122         {
00123           // We should initialize by doing a SETALL, but that would
00124           // clear the adjust value that we set when we locked the
00125           // ACE_SV_Semaphore above. Instead we do system calls to
00126           // initialize [1], as well as all the nsems SV_Semaphores.
00127 
00128           if (ACE_SV_Semaphore_Simple::control (SETVAL,
00129                                                 ACE_SV_Semaphore_Complex::BIGCOUNT_,
00130                                                 1) == -1)
00131             return -1;
00132           else
00133             for (int i = 0; i < nsems; i++)
00134               if (this->control (SETVAL, initial_value, i) == -1)
00135                 return -1;
00136         }
00137 
00138       // Decrement the process counter and then release the lock.
00139       return ACE_OS::semop (this->internal_id_,
00140                             &ACE_SV_Semaphore_Complex::op_endcreate_[0],
00141                             2);
00142     }
00143   else
00144     {
00145       this->internal_id_ = ACE_OS::semget (this->key_, 2 + nsems, 0);
00146       if (this->internal_id_ == -1)
00147         return -1;                      // doesn't exist or tables full
00148 
00149       // Decrement the process counter. We don't need a lock to do this.
00150       if (ACE_OS::semop (this->internal_id_,
00151                          &ACE_SV_Semaphore_Complex::op_open_[0], 1) < 0)
00152         return this->init ();
00153       return 0;
00154     }
00155 }

int ACE_SV_Semaphore_Complex::open const char *    name,
int    flags = ACE_SV_Semaphore_Simple::ACE_CREATE,
int    initial_value = 1,
u_short    nsems = 1,
int    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 158 of file SV_Semaphore_Complex.cpp.

References ACE_TRACE, and ACE_SV_Semaphore_Simple::name_2_key.

Referenced by ACE_SV_Semaphore_Complex.

00163 {
00164   ACE_TRACE ("ACE_SV_Semaphore_Complex::open");
00165   return this->open (ACE_SV_Semaphore_Simple::name_2_key (name),
00166                      flags, initial_value, nsems, perms);
00167 }

ASYS_INLINE int ACE_SV_Semaphore_Complex::release u_short    n = 0,
int    flags = 0
const
 

Release the semaphore.

Reimplemented from ACE_SV_Semaphore_Simple.

Definition at line 51 of file SV_Semaphore_Complex.i.

References ACE_TRACE, and ACE_SV_Semaphore_Simple::release.

00052 {
00053   ACE_TRACE ("ACE_SV_Semaphore_Complex::release");
00054   return ACE_SV_Semaphore_Simple::release ((u_short) n + 2, flags);
00055 }

ASYS_INLINE int ACE_SV_Semaphore_Complex::tryacquire u_short    n = 0,
int    flags = 0
const
 

Try to acquire the semaphore.

Reimplemented from ACE_SV_Semaphore_Simple.

Definition at line 30 of file SV_Semaphore_Complex.i.

References ACE_TRACE, and ACE_SV_Semaphore_Simple::tryacquire.

Referenced by tryacquire_read, and tryacquire_write.

00031 {
00032   ACE_TRACE ("ACE_SV_Semaphore_Complex::tryacquire");
00033   return ACE_SV_Semaphore_Simple::tryacquire ((u_short) n + 2, flags);
00034 }

ASYS_INLINE int ACE_SV_Semaphore_Complex::tryacquire_read u_short    n = 0,
int    flags = 0
const
 

Try to acquire the semaphore for reading.

Reimplemented from ACE_SV_Semaphore_Simple.

Definition at line 37 of file SV_Semaphore_Complex.i.

References ACE_TRACE, and tryacquire.

00038 {
00039   ACE_TRACE ("ACE_SV_Semaphore_Complex::tryacquire_read");
00040   return this->tryacquire (n, flags);
00041 }

ASYS_INLINE int ACE_SV_Semaphore_Complex::tryacquire_write u_short    n = 0,
int    flags = 0
const
 

Try to acquire the semaphore for writing.

Reimplemented from ACE_SV_Semaphore_Simple.

Definition at line 44 of file SV_Semaphore_Complex.i.

References ACE_TRACE, and tryacquire.

00045 {
00046   ACE_TRACE ("ACE_SV_Semaphore_Complex::tryacquire_write");
00047   return this->tryacquire (n, flags);
00048 }


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 139 of file SV_Semaphore_Complex.h.

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

Definition at line 23 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 48 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 34 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 26 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 42 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 55 of file SV_Semaphore_Complex.cpp.

Referenced by close.


The documentation for this class was generated from the following files:
Generated on Mon Jun 16 12:57:06 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002