libassa  3.5.1
Public Member Functions | Protected Member Functions | Protected Attributes | Static Protected Attributes | List of all members
ASSA::Semaphore Class Reference

#include <Semaphore.h>

Public Member Functions

 Semaphore ()
 Constructor. More...
 
virtual ~Semaphore ()
 Destructor. More...
 
int create (key_t key_, int initval_=1)
 Create a semaphore with a specified initial value. More...
 
int open (key_t key_)
 Open a semaphore that must already exist. More...
 
void close ()
 Close a semaphore. More...
 
void remove ()
 Remove a semaphore. More...
 
void wait ()
 Wait until a semaphore's value is greater then 0, then decrement it by 1 and return. More...
 
void signal ()
 Increment a semaphore by 1. More...
 
void op (int val_)
 General semaphore operation. More...
 
key_t key () const
 Get key. More...
 
int id () const
 Get id. More...
 
void dump (void) const
 Dump the objects state along with the state of the semaphore (if connected) to the log file. More...
 

Protected Member Functions

void init ()
 Initalize by invalidating data members. More...
 

Protected Attributes

key_t m_key
 Semaphore's key. More...
 
int m_id
 Semaphore's id. More...
 

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. More...
 
static sembuf m_op_endcreate [2]
 Decrement process counter with undo on exit, then decrement lock back to 0. More...
 
static sembuf m_op_open [2]
 Decrement process counter with undo on exit. More...
 
static sembuf m_op_close [3]
 Wait for lock to equal 0, then increment lock to 1 (lock it), then increment process counter. More...
 
static sembuf m_op_unlock [1]
 Decremetn lock back to 0. More...
 
static sembuf m_op_op [1]
 Decrement or increment semaphore with undo on exit. More...
 

Detailed Description

Definition at line 67 of file Semaphore.h.

Constructor & Destructor Documentation

◆ Semaphore()

ASSA::Semaphore::Semaphore ( )
inline

Constructor.

Definition at line 190 of file Semaphore.h.

192 {
193  trace_with_mask("Semaphore::Semaphore", SEM);
194 
195  init ();
196 }
#define trace_with_mask(s, m)
trace_with_mask() is used to trace function call chain in C++ program.
Definition: Logger.h:437
void init()
Initalize by invalidating data members.
Definition: Semaphore.h:211
@ SEM
Class Semaphore messages
Definition: LogMask.h:37

References init(), ASSA::SEM, and trace_with_mask.

◆ ~Semaphore()

ASSA::Semaphore::~Semaphore ( )
inlinevirtual

Destructor.

Definition at line 199 of file Semaphore.h.

201 {
202  trace_with_mask("Semaphore::~Semaphore", SEM);
203 
204  if (m_id > 0) {
205  this->close ();
206  }
207 }
int m_id
Semaphore's id.
Definition: Semaphore.h:154
void close()
Close a semaphore.
Definition: Semaphore.cpp:219

References close(), m_id, ASSA::SEM, and trace_with_mask.

Member Function Documentation

◆ close()

void Semaphore::close ( void  )

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 218 of file Semaphore.cpp.

220 {
221  trace_with_mask("Semaphore::close", SEM);
222 
223  register int semval;
224 
225  if (m_id < 0) return;
226 
227  /*
228  First get the lock on semaphore, then increment process counter.
229  */
230  if (semop (m_id, &m_op_close[0], 3) < 0) {
231  EL((ASSAERR,"Can't semop(2)\n"));
232  Assure_exit(false);
233  }
234  /*
235  Now that we have a lock, read the value of the process counter
236  to see if this is the last reference to the semaphore.
237  There is a race condition here (same as in Semaphore::create()).
238  */
239  if ((semval = semctl (m_id, 1, GETVAL, 0)) < 0) {
240  EL((ASSAERR,"Can't GETVAL\n"));
241  Assure_exit(false);
242  }
243 
244  if (semval > BIGCOUNT) {
245  EL((ASSAERR,"sem[1] > BIGCOUNT\n"));
246  Assure_exit(false);
247  }
248  else if (semval == BIGCOUNT) {
249  remove ();
250  }
251  else if (semop (m_id, &m_op_unlock[0], 1) < 0) {
252  EL((ASSAERR,"Can't unlock\n"));
253  Assure_exit(false);
254  }
255  /*--- Invalidate ---*/
256  init ();
257 }
#define Assure_exit(exp_)
Macro that makes program exit if assert fails.
Definition: Assure.h:39
#define EL(X)
A macro for writing error message to the Logger.
Definition: Logger.h:285
void remove()
Remove a semaphore.
Definition: Semaphore.cpp:204
static sembuf m_op_unlock[1]
Decremetn lock back to 0.
Definition: Semaphore.h:180
static sembuf m_op_close[3]
Wait for lock to equal 0, then increment lock to 1 (lock it), then increment process counter.
Definition: Semaphore.h:176
static const int BIGCOUNT
Definition: Semaphore.h:157
@ ASSAERR
ASSA and system errors
Definition: LogMask.h:34

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

◆ create()

int Semaphore::create ( key_t  key_,
int  initval_ = 1 
)

Create a semaphore with a specified initial value.

If the semaphore already exists, we don't initialize it (of course).

Parameters
key_Semaphore's key
initval_Initiali value (default : 1)
Returns
The semaphore ID if all OK, else -1

Definition at line 73 of file Semaphore.cpp.

75 {
76  trace_with_mask("Semaphore::create", SEM);
77 
78  register int semval;
79 
80  union semnum {
81  int val;
82  struct semid_ds* buf;
83  ushort* array;
84  } semctrl_arg;
85 
86  if (IPC_PRIVATE == key_) {
87  EL((ASSAERR,"Not intended for private semaphores\n"));
88  return (-1);
89  }
90  else if (key_ == (key_t) -1) {
91  EL((ASSAERR,"Probably an ftok() error by caller\n"));
92  return (-1);
93  }
94 
95  m_key = key_;
96  bool done = false;
97 
98  while (!done) {
99  if ( (m_id = semget (m_key, 3, 0666 | IPC_CREAT)) < 0) {
100  EL((ASSAERR,"Permission problem or kernel tables full\n"));
101  return (-1);
102  }
103  /*
104  When the semaphore is created, we know that the value of
105  all 3 set members is 0.
106 
107  Get a lock on the semaphore by waiting for [2] to equal 0,
108  then increment it.
109 
110  There is a race condition here. There is a possibility
111  that between the semget(2) and semop(2) below, another
112  process can cal Semaphore:::close () member function
113  which can remove a semaphore if that process is the last
114  one using it.
115 
116  Therefore, we handle the error condition of an invalid
117  semaphore ID specially below, and if it does happen, we
118  just go back and create it again.
119  */
120 
121  if (semop (m_id, &m_op_lock[0], 2) < 0) {
122  if (errno == EINVAL) {
123  continue;
124  }
125  EL((ASSAERR,"Can't lock semaphore\n"));
126  Assure_exit (false);
127  }
128  done = true;
129  } // while (!done)
130 
131  /*
132  Get the value of the process counter. If it equals 0,
133  then no one has initialized the semaphore yet.
134  */
135  if ((semval = semctl (m_id, 1, GETVAL, 0)) < 0) {
136  EL((ASSAERR,"Can't GETVAL\n"));
137  Assure_exit (false);
138  }
139 
140  if (semval == 0) {
141  /*
142  We could initalize by doing a SETALL, but that
143  would clear the adjust value that we set when
144  we locked the semaphore above. Instead, we'll do
145  two system calls to initialize semaphore value [0]
146  and process counter [1].
147  */
148  semctrl_arg.val = initval_;
149 
150  if (semctl (m_id, 0, SETVAL, semctrl_arg) < 0) {
151  EL((ASSAERR,"Can't SETVAL[0]\n"));
152  Assure_exit (false);
153  }
154 
155  semctrl_arg.val = BIGCOUNT;
156 
157  if (semctl (m_id, 1, SETVAL, semctrl_arg) < 0) {
158  EL((ASSAERR,"Can't SETVAL[1]\n"));
159  Assure_exit (false);
160  }
161  } // if (semval == 0)
162 
163  /*--- Decrement the process counter and then release the lock. ---*/
164 
165  if (semop (m_id, &m_op_endcreate[0], 2) < 0) {
166  EL((ASSAERR,"Error on semop (ndcreate)\n"));
167  Assure_exit (false);
168  }
169  return (m_id);
170 }
key_t m_key
Semaphore's key.
Definition: Semaphore.h:151
static sembuf m_op_lock[2]
Wait for lock to equal 0, then increment lock to 1 - this locks it.
Definition: Semaphore.h:161
static sembuf m_op_endcreate[2]
Decrement process counter with undo on exit, then decrement lock back to 0.
Definition: Semaphore.h:166

References ASSA::ASSAERR, Assure_exit, BIGCOUNT, EL, m_id, m_key, m_op_endcreate, m_op_lock, ASSA::SEM, and trace_with_mask.

◆ dump()

void Semaphore::dump ( void  ) const

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.

294 {
295  trace_with_mask("Semaphore::dump", SEM);
296 
297  std::ostringstream msg;
298  msg << "\n\n\tKey.....: ";
299 
300  if (m_key == (key_t) -1) {
301  msg << m_key;
302  }
303  else {
304  msg << "0x" << std::hex << m_key << std::dec;
305  }
306 
307  msg << "\n\tID......: " << m_id << "\n\n";
308 
309  if (m_id >= 0 && m_key >= (key_t) -1) {
310  msg << "\tsemval [0]\tproc counter[1]\tlock [2]\n"
311  << "\t----------\t---------------\t--------\n";
312 
313  /*--- Get value of element in semaphore set ---*/
314  msg << "\t " << semctl (m_id, 0, GETVAL)
315  << "\t\t " << semctl (m_id, 1, GETVAL)
316  << "\t\t " << semctl (m_id, 2, GETVAL);
317  }
318  else {
319  msg << "Semaphore id = -1. No info is available.";
320  }
321  msg << std::ends;
322  DL((SEM,"%s\n\n", msg.str ().c_str ()));
323 }
#define DL(X)
A macro for writing debug message to the Logger.
Definition: Logger.h:273
Socket & ends(Socket &os_)
ends manipulator.
Definition: Socket.h:622

References DL, ASSA::ends(), m_id, m_key, ASSA::SEM, and trace_with_mask.

Referenced by op().

◆ id()

int ASSA::Semaphore::id ( ) const
inline

Get id.

Definition at line 137 of file Semaphore.h.

137 { return m_id; }

References m_id.

◆ init()

void ASSA::Semaphore::init ( )
inlineprotected

Initalize by invalidating data members.

Definition at line 210 of file Semaphore.h.

212 {
213  m_key = (key_t) -1;
214  m_id = -1;
215 }

References m_id, and m_key.

Referenced by close(), remove(), and Semaphore().

◆ key()

key_t ASSA::Semaphore::key ( ) const
inline

Get key.

Definition at line 134 of file Semaphore.h.

134 { return m_key; }

References m_key.

◆ op()

void Semaphore::op ( int  val_)

General semaphore operation.

Increment or decrement by a user-specified amount (positive or negative; amount can't be zero!).

Definition at line 261 of file Semaphore.cpp.

263 {
264  /* Test if m_id is still valid. If it fails, then
265  * next operation is failing because of it. If not,
266  * then something else happens here.
267  */
268  trace_with_mask("Semaphore::op", SEM);
269 
270  int semval = 0;
271  dump ();
272 
273  if ((semval = semctl (m_id, 1, GETVAL, 0)) < 0) {
274  EL((ASSAERR,"Can't GETVAL\n"));
275  Assure_exit (false);
276  }
277 
278  /* This will fail on Solaris? */
279 
280  if ((m_op_op[0].sem_op = value_) == 0) {
281  EL((ASSAERR,"Can't have value_ == 0\n"));
282  Assure_exit(false);
283  }
284 
285  if (semop (m_id, &m_op_op[0], 1) < 0) {
286  EL((ASSAERR,"sem_op error\n"));
287  Assure_exit(false);
288  }
289 }
static sembuf m_op_op[1]
Decrement or increment semaphore with undo on exit.
Definition: Semaphore.h:186
void dump(void) const
Dump the objects state along with the state of the semaphore (if connected) to the log file.
Definition: Semaphore.cpp:293

References ASSA::ASSAERR, Assure_exit, dump(), EL, m_id, m_op_op, ASSA::SEM, and trace_with_mask.

Referenced by signal(), and wait().

◆ open()

int Semaphore::open ( key_t  key_)

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.

Parameters
key_Semaphore's key
Returns
The semaphore id if OK, else -1.

Definition at line 173 of file Semaphore.cpp.

175 {
176  trace_with_mask("Semaphore::open", SEM);
177 
178  if (IPC_PRIVATE == key_) {
179  EL((ASSAERR,"Not intended for private semaphores\n"));
180  return (-1);
181  }
182  else if (key_ == (key_t) -1) {
183  EL((ASSAERR,"Probably an ftok() error by caller\n"));
184  return (-1);
185  }
186 
187  m_key = key_;
188 
189  if ((m_id = semget (m_key, 3, 0)) < 0) {
190  EL((ASSAERR,"Error on semget(3)"));
191  return (-1);
192  }
193  /*--- Decrement the process counter. No need for lock ---*/
194 
195  if (semop (m_id, &m_op_open[0], 1) < 0) {
196  EL((ASSAERR,"Error on semget(open)\n"));
197  Assure_exit(false);
198  }
199  return (m_id);
200 }
static sembuf m_op_open[2]
Decrement process counter with undo on exit.
Definition: Semaphore.h:171

References ASSA::ASSAERR, Assure_exit, EL, m_id, m_key, m_op_open, ASSA::SEM, and trace_with_mask.

◆ remove()

void Semaphore::remove ( )

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 203 of file Semaphore.cpp.

205 {
206  trace_with_mask("Semaphore::remove", SEM);
207 
208  if (m_id < 0 || m_key == ((key_t) -1) ) return;
209 
210  if (semctl (m_id, 0, IPC_RMID, 0) < 0) {
211  EL((ASSAERR,"Can't IPC_RMID\n"));
212  Assure_exit(false);
213  }
214  init ();
215 }

References ASSA::ASSAERR, Assure_exit, EL, init(), m_id, m_key, ASSA::SEM, and trace_with_mask.

Referenced by close().

◆ signal()

void ASSA::Semaphore::signal ( )
inline

Increment a semaphore by 1.

Tanenbaum's UP operation.

Definition at line 226 of file Semaphore.h.

228 {
229  trace_with_mask("Semaphore::signal", SEM);
230  op (1);
231 }
void op(int val_)
General semaphore operation.
Definition: Semaphore.cpp:262

References op(), ASSA::SEM, and trace_with_mask.

◆ wait()

void ASSA::Semaphore::wait ( )
inline

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.

220 {
221  trace_with_mask("Semaphore::wait", SEM);
222  op (-1);
223 }

References op(), ASSA::SEM, and trace_with_mask.

Member Data Documentation

◆ BIGCOUNT

const int ASSA::Semaphore::BIGCOUNT = 10000
staticprotected

Definition at line 157 of file Semaphore.h.

Referenced by close(), and create().

◆ m_id

int ASSA::Semaphore::m_id
protected

Semaphore's id.

Definition at line 154 of file Semaphore.h.

Referenced by close(), create(), dump(), id(), init(), op(), open(), remove(), and ~Semaphore().

◆ m_key

key_t ASSA::Semaphore::m_key
protected

Semaphore's key.

Definition at line 151 of file Semaphore.h.

Referenced by create(), dump(), init(), key(), open(), and remove().

◆ m_op_close

sembuf Semaphore::m_op_close
staticprotected
Initial value:
=
{
{2, 0, 0},
{2, 1, SEM_UNDO},
{1, 1, SEM_UNDO}
}

Wait for lock to equal 0, then increment lock to 1 (lock it), then increment process counter.

Definition at line 176 of file Semaphore.h.

Referenced by close().

◆ m_op_endcreate

sembuf Semaphore::m_op_endcreate
staticprotected
Initial value:
=
{
{1, -1, SEM_UNDO},
{2, -1, SEM_UNDO}
}

Decrement process counter with undo on exit, then decrement lock back to 0.

Definition at line 166 of file Semaphore.h.

Referenced by create().

◆ m_op_lock

sembuf Semaphore::m_op_lock
staticprotected
Initial value:
=
{
{2, 0, 0},
{2, 1, SEM_UNDO}
}

Wait for lock to equal 0, then increment lock to 1 - this locks it.

Definition at line 161 of file Semaphore.h.

Referenced by create().

◆ m_op_op

sembuf Semaphore::m_op_op
staticprotected
Initial value:
=
{
{0, 99, SEM_UNDO}
}

Decrement or increment semaphore with undo on exit.

The 99 is set to the actual amount to add or substract (positive or negative).

Definition at line 186 of file Semaphore.h.

Referenced by op().

◆ m_op_open

sembuf Semaphore::m_op_open
staticprotected
Initial value:
=
{
{1, -1, SEM_UNDO},
}

Decrement process counter with undo on exit.

Definition at line 171 of file Semaphore.h.

Referenced by open().

◆ m_op_unlock

sembuf Semaphore::m_op_unlock
staticprotected
Initial value:
=
{
{2, -1, SEM_UNDO}
}

Decremetn lock back to 0.

Definition at line 180 of file Semaphore.h.

Referenced by close().


The documentation for this class was generated from the following files: