#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 66 of file Semaphore.h.
|
Constructor.
Definition at line 190 of file Semaphore.h. References init(), ASSA::SEM, and trace_with_mask. 00191 { 00192 trace_with_mask("Semaphore::Semaphore", SEM); 00193 00194 init (); 00195 }
|
|
Destructor.
Definition at line 199 of file Semaphore.h. References close(), m_id, ASSA::SEM, and trace_with_mask. 00200 { 00201 trace_with_mask("Semaphore::~Semaphore", SEM); 00202 00203 if (m_id > 0) { 00204 this->close (); 00205 } 00206 }
|
|
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 221 of file Semaphore.cpp. References ASSA::ASSAERR, Assure_exit, BIGCOUNT, EL, init(), m_id, m_op_close, m_op_unlock, remove(), ASSA::SEM, and trace_with_mask. Referenced by ~Semaphore(). 00222 { 00223 trace_with_mask("Semaphore::close", SEM); 00224 00225 register int semval; 00226 00227 if (m_id < 0) return; 00228 00229 /* 00230 First get the lock on semaphore, then increment process counter. 00231 */ 00232 if (semop (m_id, &m_op_close[0], 3) < 0) { 00233 EL((ASSAERR,"Can't semop(2)\n")); 00234 Assure_exit(false); 00235 } 00236 /* 00237 Now that we have a lock, read the value of the process counter 00238 to see if this is the last reference to the semaphore. 00239 There is a race condition here (same as in Semaphore::create()). 00240 */ 00241 if ((semval = semctl (m_id, 1, GETVAL, 0)) < 0) { 00242 EL((ASSAERR,"Can't GETVAL\n")); 00243 Assure_exit(false); 00244 } 00245 00246 if (semval > BIGCOUNT) { 00247 EL((ASSAERR,"sem[1] > BIGCOUNT\n")); 00248 Assure_exit(false); 00249 } 00250 else if (semval == BIGCOUNT) { 00251 remove (); 00252 } 00253 else if (semop (m_id, &m_op_unlock[0], 1) < 0) { 00254 EL((ASSAERR,"Can't unlock\n")); 00255 Assure_exit(false); 00256 } 00257 /*--- Invalidate ---*/ 00258 init (); 00259 }
|
|
Create a semaphore with a specified initial value. If the semaphore already exists, we don't initialize it (of course).
Definition at line 77 of file Semaphore.cpp. References ASSA::ASSAERR, Assure_exit, BIGCOUNT, EL, m_id, m_key, m_op_endcreate, m_op_lock, ASSA::SEM, and trace_with_mask. 00078 { 00079 trace_with_mask("Semaphore::create", SEM); 00080 00081 register int semval; 00082 00083 union semnum { 00084 int val; 00085 struct semid_ds* buf; 00086 ushort* array; 00087 } semctrl_arg; 00088 00089 if (IPC_PRIVATE == key_) { 00090 EL((ASSAERR,"Not intended for private semaphores\n")); 00091 return (-1); 00092 } 00093 else if (key_ == (key_t) -1) { 00094 EL((ASSAERR,"Probably an ftok() error by caller\n")); 00095 return (-1); 00096 } 00097 m_key = key_; 00098 bool done = false; 00099 00100 while (!done) { 00101 if ( (m_id = semget (m_key, 3, 0666 | IPC_CREAT)) < 0) { 00102 EL((ASSAERR,"Permission problem or kernel tables full\n")); 00103 return (-1); 00104 } 00105 /* 00106 When the semaphore is created, we know that the value of 00107 all 3 set members is 0. 00108 00109 Get a lock on the semaphore by waiting for [2] to equal 0, 00110 then increment it. 00111 00112 There is a race condition here. There is a possibility 00113 that between the semget(2) and semop(2) below, another 00114 process can cal Semaphore:::close () member function 00115 which can remove a semaphore if that process is the last 00116 one using it. 00117 00118 Therefore, we handle the error condition of an invalid 00119 semaphore ID specially below, and if it does happen, we 00120 just go back and create it again. 00121 */ 00122 00123 if (semop (m_id, &m_op_lock[0], 2) < 0) { 00124 if (errno == EINVAL) { 00125 continue; 00126 } 00127 EL((ASSAERR,"Can't lock semaphore\n")); 00128 Assure_exit (false); 00129 } 00130 done = true; 00131 } // while (!done) 00132 00133 /* 00134 Get the value of the process counter. If it equals 0, 00135 then no one has initialized the semaphore yet. 00136 */ 00137 if ((semval = semctl (m_id, 1, GETVAL, 0)) < 0) { 00138 EL((ASSAERR,"Can't GETVAL\n")); 00139 Assure_exit (false); 00140 } 00141 00142 if (semval == 0) { 00143 /* 00144 We could initalize by doing a SETALL, but that 00145 would clear the adjust value that we set when 00146 we locked the semaphore above. Instead, we'll do 00147 two system calls to initialize semaphore value [0] 00148 and process counter [1]. 00149 */ 00150 semctrl_arg.val = initval_; 00151 00152 if (semctl (m_id, 0, SETVAL, semctrl_arg) < 0) { 00153 EL((ASSAERR,"Can't SETVAL[0]\n")); 00154 Assure_exit (false); 00155 } 00156 00157 semctrl_arg.val = BIGCOUNT; 00158 00159 if (semctl (m_id, 1, SETVAL, semctrl_arg) < 0) { 00160 EL((ASSAERR,"Can't SETVAL[1]\n")); 00161 Assure_exit (false); 00162 } 00163 } // if (semval == 0) 00164 00165 /*--- Decrement the process counter and then release the lock. ---*/ 00166 00167 if (semop (m_id, &m_op_endcreate[0], 2) < 0) { 00168 EL((ASSAERR,"Error on semop (ndcreate)\n")); 00169 Assure_exit (false); 00170 } 00171 return (m_id); 00172 }
|
|
Dump the objects state along with the state of the semaphore (if connected) to the log file.
Definition at line 294 of file Semaphore.cpp. References DL, ASSA::ends(), m_id, m_key, ASSA::SEM, and trace_with_mask. Referenced by op(). 00295 { 00296 trace_with_mask("Semaphore::dump", SEM); 00297 00298 std::ostringstream msg; 00299 msg << "\n\n\tKey.....: "; 00300 00301 if (m_key == (key_t) -1) { 00302 msg << m_key; 00303 } 00304 else { 00305 msg << "0x" << std::hex << m_key << std::dec; 00306 } 00307 00308 msg << "\n\tID......: " << m_id << "\n\n"; 00309 00310 if (m_id >= 0 && m_key >= (key_t) -1) { 00311 msg << "\tsemval [0]\tproc counter[1]\tlock [2]\n" 00312 << "\t----------\t---------------\t--------\n"; 00313 00314 /*--- Get value of element in semaphore set ---*/ 00315 msg << "\t " << semctl (m_id, 0, GETVAL) 00316 << "\t\t " << semctl (m_id, 1, GETVAL) 00317 << "\t\t " << semctl (m_id, 2, GETVAL); 00318 } 00319 else { 00320 msg << "Semaphore id = -1. No info is available."; 00321 } 00322 msg << std::ends; 00323 DL((SEM,"%s\n\n", msg.str ().c_str ())); 00324 }
|
|
Get id.
Definition at line 136 of file Semaphore.h. References m_id. 00136 { return m_id; }
|
|
Initalize by invalidating data members.
Definition at line 210 of file Semaphore.h. Referenced by close(), remove(), and Semaphore().
|
|
Get key.
Definition at line 133 of file Semaphore.h. References m_key. 00133 { 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 264 of file Semaphore.cpp. References ASSA::ASSAERR, Assure_exit, dump(), EL, m_id, m_op_op, ASSA::SEM, and trace_with_mask. Referenced by signal(), and wait(). 00265 { 00266 /* Test if m_id is still valid. If it fails, then 00267 * next operation is failing because of it. If not, 00268 * then something else happens here. 00269 */ 00270 trace_with_mask("Semaphore::op", SEM); 00271 00272 int semval = 0; 00273 dump (); 00274 00275 if ((semval = semctl (m_id, 1, GETVAL, 0)) < 0) { 00276 EL((ASSAERR,"Can't GETVAL\n")); 00277 Assure_exit (false); 00278 } 00279 /* This will fail on Solaris? */ 00280 00281 if ((m_op_op[0].sem_op = value_) == 0) { 00282 EL((ASSAERR,"Can't have value_ == 0\n")); 00283 Assure_exit(false); 00284 } 00285 00286 if (semop (m_id, &m_op_op[0], 1) < 0) { 00287 EL((ASSAERR,"sem_op error\n")); 00288 Assure_exit(false); 00289 } 00290 }
|
|
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 176 of file Semaphore.cpp. References ASSA::ASSAERR, Assure_exit, EL, m_id, m_key, m_op_open, ASSA::SEM, and trace_with_mask. 00177 { 00178 trace_with_mask("Semaphore::open", SEM); 00179 00180 if (IPC_PRIVATE == key_) { 00181 EL((ASSAERR,"Not intended for private semaphores\n")); 00182 return (-1); 00183 } 00184 else if (key_ == (key_t) -1) { 00185 EL((ASSAERR,"Probably an ftok() error by caller\n")); 00186 return (-1); 00187 } 00188 00189 m_key = key_; 00190 00191 if ((m_id = semget (m_key, 3, 0)) < 0) { 00192 EL((ASSAERR,"Error on semget(3)")); 00193 return (-1); 00194 } 00195 /*--- Decrement the process counter. No need for lock ---*/ 00196 00197 if (semop (m_id, &m_op_open[0], 1) < 0) { 00198 EL((ASSAERR,"Error on semget(open)\n")); 00199 Assure_exit(false); 00200 } 00201 return (m_id); 00202 }
|
|
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 206 of file Semaphore.cpp. References ASSA::ASSAERR, Assure_exit, EL, init(), m_id, m_key, ASSA::SEM, and trace_with_mask. Referenced by close(). 00207 { 00208 trace_with_mask("Semaphore::remove", SEM); 00209 00210 if (m_id < 0 || m_key == ((key_t) -1) ) return; 00211 00212 if (semctl (m_id, 0, IPC_RMID, 0) < 0) { 00213 EL((ASSAERR,"Can't IPC_RMID\n")); 00214 Assure_exit(false); 00215 } 00216 init (); 00217 }
|
|
Increment a semaphore by 1. Tanenbaum's UP operation. Definition at line 226 of file Semaphore.h. References op(), ASSA::SEM, and trace_with_mask. 00227 { 00228 trace_with_mask("Semaphore::signal", SEM); 00229 op (1); 00230 }
|
|
Wait until a semaphore's value is greater then 0, then decrement it by 1 and return. Tanenbaum's DOWN operation. Definition at line 218 of file Semaphore.h. References op(), ASSA::SEM, and trace_with_mask. 00219 { 00220 trace_with_mask("Semaphore::wait", SEM); 00221 op (-1); 00222 }
|
|
Definition at line 156 of file Semaphore.h. |
|
Semaphore's id.
Definition at line 153 of file Semaphore.h. Referenced by close(), create(), dump(), id(), init(), op(), open(), remove(), and ~Semaphore(). |
|
Semaphore's key.
Definition at line 150 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 175 of file Semaphore.h. Referenced by close(). |
|
Initial value: { {1, -1, SEM_UNDO}, {2, -1, SEM_UNDO} }
Definition at line 165 of file Semaphore.h. Referenced by create(). |
|
Initial value: { {2, 0, 0}, {2, 1, SEM_UNDO} }
Definition at line 160 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 185 of file Semaphore.h. Referenced by op(). |
|
Initial value: { {1, -1, SEM_UNDO}, }
Definition at line 170 of file Semaphore.h. Referenced by open(). |
|
Initial value: { {2, -1, SEM_UNDO} }
Definition at line 179 of file Semaphore.h. Referenced by close(). |