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