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

SV_Semaphore_Complex.cpp

Go to the documentation of this file.
00001 #include "ace_pch.h"
00002 // SV_Semaphore_Complex.cpp
00003 // $Id: SV_Semaphore_Complex.cpp,v 1.1.1.3.40.1 2003/03/13 19:44:22 chad Exp $
00004 
00005 #include "ace/SV_Semaphore_Complex.h"
00006 #include "ace/Log_Msg.h"
00007 
00008 #if defined (ACE_LACKS_INLINE_FUNCTIONS)
00009 #include "ace/SV_Semaphore_Complex.i"
00010 #endif
00011 
00012 ACE_RCSID(ace, SV_Semaphore_Complex, "$Id: SV_Semaphore_Complex.cpp,v 1.1.1.3.40.1 2003/03/13 19:44:22 chad Exp $")
00013 
00014 ACE_ALLOC_HOOK_DEFINE(ACE_SV_Semaphore_Complex)
00015 
00016 void
00017 ACE_SV_Semaphore_Complex::dump (void) const
00018 {
00019   ACE_TRACE ("ACE_SV_Semaphore_Complex::dump");
00020 }
00021 
00022 // initial value of process
00023 const int ACE_SV_Semaphore_Complex::BIGCOUNT_ = 10000;
00024 
00025 // Define the ACE_SV_Semaphore operation arrays for the semop() calls.
00026 sembuf ACE_SV_Semaphore_Complex::op_lock_[2] =
00027 {
00028   {0, 0, 0},                    // Wait for [0] (lock) to equal 0
00029   {0, 1, SEM_UNDO},             // then increment [0] to 1 - this locks it.
00030                                 // UNDO to release the lock if processes exit
00031                                 // before explicitly unlocking.
00032 };
00033 
00034 sembuf ACE_SV_Semaphore_Complex::op_endcreate_[2] =
00035 {
00036   {1, -1, SEM_UNDO},            // Decrement [1] (proc counter) with undo on
00037                                 // exit, UNDO to adjust proc counter if
00038                                 // process exits before explicitly calling close()
00039   {0, -1, SEM_UNDO},            // the decrement [0] (lock) back to 0
00040 };
00041 
00042 sembuf ACE_SV_Semaphore_Complex::op_open_[1] =
00043 {
00044   {1, -1, SEM_UNDO},            // Decrement [1] (proc counter) with undo on
00045                                 // exit.
00046 };
00047 
00048 sembuf ACE_SV_Semaphore_Complex::op_close_[3] =
00049 {
00050   {0, 0, 0},                    // Wait for [0] (lock) to equal 0
00051   {0, 1, SEM_UNDO},             // then increment [0] to 1 - this lock it
00052   {1, 1, SEM_UNDO},             // then increment [1] (proc counter)
00053 };
00054 
00055 sembuf ACE_SV_Semaphore_Complex::op_unlock_[1] =
00056 {
00057   {0, -1, SEM_UNDO},            // Decrement [0] (lock) back to 0
00058 };
00059 
00060 // Open or create an array of SV_Semaphores.  We return 0 if all is OK, else -1.
00061 
00062 int
00063 ACE_SV_Semaphore_Complex::open (key_t k,
00064                                 int create,
00065                                 int initial_value,
00066                                 u_short nsems,
00067                                 int perms)
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 }
00156 
00157 int
00158 ACE_SV_Semaphore_Complex::open (const char *name,
00159                                 int flags,
00160                                 int initial_value,
00161                                 u_short nsems,
00162                                 int perms)
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 }
00168 
00169 // Close a ACE_SV_Semaphore.  Unlike the remove above, this function
00170 // is for a process to call before it exits, when it is done with the
00171 // ACE_SV_Semaphore.  We "decrement" the counter of processes using
00172 // the ACE_SV_Semaphore, and if this was the last one, we can remove
00173 // the ACE_SV_Semaphore.
00174 
00175 int
00176 ACE_SV_Semaphore_Complex::close (void)
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 }
00211 
00212 ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex (key_t k,
00213                                                     int flags,
00214                                                     int initial_value,
00215                                                     u_short nsems,
00216                                                     int perms)
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 }
00222 
00223 ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex (const char *name,
00224                                                     int flags,
00225                                                     int initial_value,
00226                                                     u_short nsems,
00227                                                     int perms)
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 }
00241 
00242 ACE_SV_Semaphore_Complex::~ACE_SV_Semaphore_Complex (void)
00243 {
00244   ACE_TRACE ("ACE_SV_Semaphore_Complex::~ACE_SV_Semaphore_Complex");
00245   if (this->internal_id_ >= 0)
00246     this->close ();
00247 }
00248 
00249 ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex (void)
00250 {
00251   ACE_TRACE ("ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex");
00252   this->init ();
00253 }

Generated on Mon Jun 16 11:21:32 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002