#include <Semaphore.h>
Public Member Functions | |
Semaphore () | |
Constructor. | |
virtual | ~Semaphore () |
Destructor. | |
int | create (key_t key_, int initval_=1) |
Create a semaphore with a specified initial value. | |
int | open (key_t key_) |
Open a semaphore that must already exist. | |
void | close () |
Close a semaphore. | |
void | remove () |
Remove a semaphore. | |
void | wait () |
Wait until a semaphore's value is greater then 0, then decrement it by 1 and return. | |
void | signal () |
Increment a semaphore by 1. | |
void | op (int val_) |
General semaphore operation. | |
key_t | key () const |
Get key. | |
int | id () const |
Get id. | |
void | dump (void) const |
Dump the objects state along with the state of the semaphore (if connected) to the log file. | |
Protected Member Functions | |
void | init () |
Initalize by invalidating data members. | |
Protected Attributes | |
key_t | m_key |
Semaphore's key. | |
int | m_id |
Semaphore's id. | |
Static Protected Attributes | |
static const int | BIGCOUNT = 10000 |
static sembuf | m_op_lock [2] |
Wait for lock to equal 0, then increment lock to 1 - this locks it. | |
static sembuf | m_op_endcreate [2] |
Decrement process counter with undo on exit, then decrement lock back to 0. | |
static sembuf | m_op_open [2] |
Decrement process counter with undo on exit. | |
static sembuf | m_op_close [3] |
Wait for lock to equal 0, then increment lock to 1 (lock it), then increment process counter. | |
static sembuf | m_op_unlock [1] |
Decremetn lock back to 0. | |
static sembuf | m_op_op [1] |
Decrement or increment semaphore with undo on exit. |
Definition at line 64 of file Semaphore.h.
|
Constructor.
Definition at line 188 of file Semaphore.h. References init(), ASSA::SEM, and trace_with_mask. 00189 { 00190 trace_with_mask("Semaphore::Semaphore", SEM); 00191 00192 init (); 00193 }
|
|
Destructor.
Definition at line 197 of file Semaphore.h. References close(), m_id, ASSA::SEM, and trace_with_mask. 00198 { 00199 trace_with_mask("Semaphore::~Semaphore", SEM); 00200 00201 if (m_id > 0) { 00202 this->close (); 00203 } 00204 }
|
|
Close a semaphore. Unlike the Semaphore::remove () function, this function is for a process to call before it exits, when it is done with the semaphore. We decrement the counter of processes using the semaphore, and if this was the last one, Semaphore::remove () is called to remove the semaphore. Calling this method also invalidates object for subsequent operations. Definition at line 219 of file Semaphore.cpp. References Assure_exit, BIGCOUNT, EL, ASSA::ERROR, init(), m_id, m_op_close, m_op_unlock, remove(), ASSA::SEM, and trace_with_mask. Referenced by ~Semaphore(). 00220 { 00221 trace_with_mask("Semaphore::close", SEM); 00222 00223 register int semval; 00224 00225 if (m_id < 0) return; 00226 00227 /* 00228 First get the lock on semaphore, then increment process counter. 00229 */ 00230 if (semop (m_id, &m_op_close[0], 3) < 0) { 00231 EL((ERROR,"Can't semop(2)\n")); 00232 Assure_exit(false); 00233 } 00234 /* 00235 Now that we have a lock, read the value of the process counter 00236 to see if this is the last reference to the semaphore. 00237 There is a race condition here (same as in Semaphore::create()). 00238 */ 00239 if ((semval = semctl (m_id, 1, GETVAL, 0)) < 0) { 00240 EL((ERROR,"Can't GETVAL\n")); 00241 Assure_exit(false); 00242 } 00243 00244 if (semval > BIGCOUNT) { 00245 EL((ERROR,"sem[1] > BIGCOUNT\n")); 00246 Assure_exit(false); 00247 } 00248 else if (semval == BIGCOUNT) { 00249 remove (); 00250 } 00251 else if (semop (m_id, &m_op_unlock[0], 1) < 0) { 00252 EL((ERROR,"Can't unlock\n")); 00253 Assure_exit(false); 00254 } 00255 /*--- Invalidate ---*/ 00256 init (); 00257 }
|
|
Create a semaphore with a specified initial value. If the semaphore already exists, we don't initialize it (of course).
Definition at line 75 of file Semaphore.cpp. References Assure_exit, BIGCOUNT, EL, ASSA::ERROR, m_id, m_key, m_op_endcreate, m_op_lock, ASSA::SEM, and trace_with_mask. 00076 { 00077 trace_with_mask("Semaphore::create", SEM); 00078 00079 register int semval; 00080 00081 union semnum { 00082 int val; 00083 struct semid_ds* buf; 00084 ushort* array; 00085 } semctrl_arg; 00086 00087 if (IPC_PRIVATE == key_) { 00088 EL((ERROR,"Not intended for private semaphores\n")); 00089 return (-1); 00090 } 00091 else if (key_ == (key_t) -1) { 00092 EL((ERROR,"Probably an ftok() error by caller\n")); 00093 return (-1); 00094 } 00095 m_key = key_; 00096 bool done = false; 00097 00098 while (!done) { 00099 if ( (m_id = semget (m_key, 3, 0666 | IPC_CREAT)) < 0) { 00100 EL((ERROR,"Permission problem or kernel tables full\n")); 00101 return (-1); 00102 } 00103 /* 00104 When the semaphore is created, we know that the value of 00105 all 3 set members is 0. 00106 00107 Get a lock on the semaphore by waiting for [2] to equal 0, 00108 then increment it. 00109 00110 There is a race condition here. There is a possibility 00111 that between the semget(2) and semop(2) below, another 00112 process can cal Semaphore:::close () member function 00113 which can remove a semaphore if that process is the last 00114 one using it. 00115 00116 Therefore, we handle the error condition of an invalid 00117 semaphore ID specially below, and if it does happen, we 00118 just go back and create it again. 00119 */ 00120 00121 if (semop (m_id, &m_op_lock[0], 2) < 0) { 00122 if (errno == EINVAL) { 00123 continue; 00124 } 00125 EL((ERROR,"Can't lock semaphore\n")); 00126 Assure_exit (false); 00127 } 00128 done = true; 00129 } // while (!done) 00130 00131 /* 00132 Get the value of the process counter. If it equals 0, 00133 then no one has initialized the semaphore yet. 00134 */ 00135 if ((semval = semctl (m_id, 1, GETVAL, 0)) < 0) { 00136 EL((ERROR,"Can't GETVAL\n")); 00137 Assure_exit (false); 00138 } 00139 00140 if (semval == 0) { 00141 /* 00142 We could initalize by doing a SETALL, but that 00143 would clear the adjust value that we set when 00144 we locked the semaphore above. Instead, we'll do 00145 two system calls to initialize semaphore value [0] 00146 and process counter [1]. 00147 */ 00148 semctrl_arg.val = initval_; 00149 00150 if (semctl (m_id, 0, SETVAL, semctrl_arg) < 0) { 00151 EL((ERROR,"Can't SETVAL[0]\n")); 00152 Assure_exit (false); 00153 } 00154 00155 semctrl_arg.val = BIGCOUNT; 00156 00157 if (semctl (m_id, 1, SETVAL, semctrl_arg) < 0) { 00158 EL((ERROR,"Can't SETVAL[1]\n")); 00159 Assure_exit (false); 00160 } 00161 } // if (semval == 0) 00162 00163 /*--- Decrement the process counter and then release the lock. ---*/ 00164 00165 if (semop (m_id, &m_op_endcreate[0], 2) < 0) { 00166 EL((ERROR,"Error on semop (ndcreate)\n")); 00167 Assure_exit (false); 00168 } 00169 return (m_id); 00170 }
|
|
Dump the objects state along with the state of the semaphore (if connected) to the log file.
Definition at line 292 of file Semaphore.cpp. References DL, ASSA::ends(), m_id, m_key, ASSA::SEM, and trace_with_mask. Referenced by op(). 00293 { 00294 trace_with_mask("Semaphore::dump", SEM); 00295 00296 std::ostringstream msg; 00297 msg << "\n\n\tKey.....: "; 00298 00299 if (m_key == (key_t) -1) { 00300 msg << m_key; 00301 } 00302 else { 00303 msg << "0x" << std::hex << m_key << std::dec; 00304 } 00305 00306 msg << "\n\tID......: " << m_id << "\n\n"; 00307 00308 if (m_id >= 0 && m_key >= (key_t) -1) { 00309 msg << "\tsemval [0]\tproc counter[1]\tlock [2]\n" 00310 << "\t----------\t---------------\t--------\n"; 00311 00312 /*--- Get value of element in semaphore set ---*/ 00313 msg << "\t " << semctl (m_id, 0, GETVAL) 00314 << "\t\t " << semctl (m_id, 1, GETVAL) 00315 << "\t\t " << semctl (m_id, 2, GETVAL); 00316 } 00317 else { 00318 msg << "Semaphore id = -1. No info is available."; 00319 } 00320 msg << std::ends; 00321 DL((SEM,"%s\n\n", msg.str ().c_str ())); 00322 }
|
|
Get id.
Definition at line 134 of file Semaphore.h. References m_id. 00134 { return m_id; }
|
|
Initalize by invalidating data members.
Definition at line 208 of file Semaphore.h. Referenced by close(), remove(), and Semaphore().
|
|
Get key.
Definition at line 131 of file Semaphore.h. References m_key. 00131 { return m_key; }
|
|
General semaphore operation. Increment or decrement by a user-specified amount (positive or negative; amount can't be zero!). Definition at line 262 of file Semaphore.cpp. References Assure_exit, dump(), EL, ASSA::ERROR, m_id, m_op_op, ASSA::SEM, and trace_with_mask. Referenced by signal(), and wait(). 00263 { 00264 /* Test if m_id is still valid. If it fails, then 00265 * next operation is failing because of it. If not, 00266 * then something else happens here. 00267 */ 00268 trace_with_mask("Semaphore::op", SEM); 00269 00270 int semval = 0; 00271 dump (); 00272 00273 if ((semval = semctl (m_id, 1, GETVAL, 0)) < 0) { 00274 EL((ERROR,"Can't GETVAL\n")); 00275 Assure_exit (false); 00276 } 00277 /* This will fail on Solaris? */ 00278 00279 if ((m_op_op[0].sem_op = value_) == 0) { 00280 EL((ERROR,"Can't have value_ == 0\n")); 00281 Assure_exit(false); 00282 } 00283 00284 if (semop (m_id, &m_op_op[0], 1) < 0) { 00285 EL((ERROR,"sem_op error\n")); 00286 Assure_exit(false); 00287 } 00288 }
|
|
Open a semaphore that must already exist. This function should be used, instead of Semaphore::create (), if the caller knows that the semaphore must already exist. For example, a client from a client-server pair would use this, if its server's responsibility to create the semaphore.
Definition at line 174 of file Semaphore.cpp. References Assure_exit, EL, ASSA::ERROR, m_id, m_key, m_op_open, ASSA::SEM, and trace_with_mask. 00175 { 00176 trace_with_mask("Semaphore::open", SEM); 00177 00178 if (IPC_PRIVATE == key_) { 00179 EL((ERROR,"Not intended for private semaphores\n")); 00180 return (-1); 00181 } 00182 else if (key_ == (key_t) -1) { 00183 EL((ERROR,"Probably an ftok() error by caller\n")); 00184 return (-1); 00185 } 00186 00187 m_key = key_; 00188 00189 if ((m_id = semget (m_key, 3, 0)) < 0) { 00190 EL((ERROR,"Error on semget(3)")); 00191 return (-1); 00192 } 00193 /*--- Decrement the process counter. No need for lock ---*/ 00194 00195 if (semop (m_id, &m_op_open[0], 1) < 0) { 00196 EL((ERROR,"Error on semget(open)\n")); 00197 Assure_exit(false); 00198 } 00199 return (m_id); 00200 }
|
|
Remove a semaphore. This call is intended to be called by a server, for example, when it is being shut down, as we do an IPC_RMID on the semaphore, regardless whether other processes may be using it or not. Most other processes should use Semaphore::close () instead. Calling this method also invalidates object for subsequent operations. Definition at line 204 of file Semaphore.cpp. References Assure_exit, EL, ASSA::ERROR, init(), m_id, m_key, ASSA::SEM, and trace_with_mask. Referenced by close(). 00205 { 00206 trace_with_mask("Semaphore::remove", SEM); 00207 00208 if (m_id < 0 || m_key == ((key_t) -1) ) return; 00209 00210 if (semctl (m_id, 0, IPC_RMID, 0) < 0) { 00211 EL((ERROR,"Can't IPC_RMID\n")); 00212 Assure_exit(false); 00213 } 00214 init (); 00215 }
|
|
Increment a semaphore by 1. Tanenbaum's UP operation. Definition at line 224 of file Semaphore.h. References op(), ASSA::SEM, and trace_with_mask. 00225 { 00226 trace_with_mask("Semaphore::signal", SEM); 00227 op (1); 00228 }
|
|
Wait until a semaphore's value is greater then 0, then decrement it by 1 and return. Tanenbaum's DOWN operation. Definition at line 216 of file Semaphore.h. References op(), ASSA::SEM, and trace_with_mask. 00217 { 00218 trace_with_mask("Semaphore::wait", SEM); 00219 op (-1); 00220 }
|
|
Definition at line 154 of file Semaphore.h. |
|
Semaphore's id.
Definition at line 151 of file Semaphore.h. Referenced by close(), create(), dump(), id(), init(), op(), open(), remove(), and ~Semaphore(). |
|
Semaphore's key.
Definition at line 148 of file Semaphore.h. Referenced by create(), dump(), init(), key(), open(), and remove(). |
|
Initial value: { {2, 0, 0}, {2, 1, SEM_UNDO}, {1, 1, SEM_UNDO} }
Definition at line 173 of file Semaphore.h. Referenced by close(). |
|
Initial value: { {1, -1, SEM_UNDO}, {2, -1, SEM_UNDO} }
Definition at line 163 of file Semaphore.h. Referenced by create(). |
|
Initial value: { {2, 0, 0}, {2, 1, SEM_UNDO} }
Definition at line 158 of file Semaphore.h. Referenced by create(). |
|
Initial value: { {0, 99, SEM_UNDO} } The 99 is set to the actual amount to add or substract (positive or negative). Definition at line 183 of file Semaphore.h. Referenced by op(). |
|
Initial value: { {1, -1, SEM_UNDO}, }
Definition at line 168 of file Semaphore.h. Referenced by open(). |
|
Initial value: { {2, -1, SEM_UNDO} }
Definition at line 177 of file Semaphore.h. Referenced by close(). |