libassa  3.5.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Public Member Functions | Protected Member Functions | Protected Attributes | Static Protected Attributes
ASSA::Semaphore Class Reference

#include <Semaphore.h>

List of all members.

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.

Detailed Description

Definition at line 66 of file Semaphore.h.


Constructor & Destructor Documentation

Constructor.

Definition at line 190 of file Semaphore.h.

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

{
    trace_with_mask("Semaphore::Semaphore", SEM);

    init ();
}
ASSA::Semaphore::~Semaphore ( ) [inline, virtual]

Destructor.

Definition at line 199 of file Semaphore.h.

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

{
    trace_with_mask("Semaphore::~Semaphore", SEM);
    
    if (m_id > 0) {
        this->close ();
    }
}

Member Function Documentation

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

References ASSA::ASSAERR, Assure_exit, BIGCOUNT, EL, init(), m_id, m_op_close, m_op_unlock, ASSA::SEM, and trace_with_mask.

Referenced by ~Semaphore().

{
    trace_with_mask("Semaphore::close", SEM);

    register int semval;

    if (m_id < 0) return;

    /*
      First get the lock on semaphore, then increment process  counter.
    */
    if (semop (m_id, &m_op_close[0], 3) < 0) {
        EL((ASSAERR,"Can't semop(2)\n"));
        Assure_exit(false);
    }
    /*
      Now that we have a lock, read the value of the process counter
      to see if this is the last reference to the semaphore.
      There is a race condition here (same as in Semaphore::create()).
    */
    if ((semval = semctl (m_id, 1, GETVAL, 0)) < 0) {
        EL((ASSAERR,"Can't GETVAL\n"));
        Assure_exit(false);
    }
    
    if (semval > BIGCOUNT) {
        EL((ASSAERR,"sem[1] > BIGCOUNT\n"));
        Assure_exit(false);
    }
    else if (semval == BIGCOUNT) {
        remove ();
    }
    else if (semop (m_id, &m_op_unlock[0], 1) < 0) {
        EL((ASSAERR,"Can't unlock\n"));
        Assure_exit(false);
    }
    /*--- Invalidate ---*/
    init ();
}
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 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.

{
    trace_with_mask("Semaphore::create", SEM);

    register int semval;

    union semnum {
        int              val;
        struct semid_ds* buf;
        ushort*          array;
    } semctrl_arg;

    if (IPC_PRIVATE == key_) {
        EL((ASSAERR,"Not intended for private semaphores\n"));
        return (-1);
    }
    else if (key_ == (key_t) -1) {
        EL((ASSAERR,"Probably an ftok() error by caller\n"));
        return (-1);
    }
    m_key = key_;
    bool done = false;

    while (!done) {
        if ( (m_id = semget (m_key, 3, 0666 | IPC_CREAT)) < 0) {
            EL((ASSAERR,"Permission problem or kernel tables full\n"));
            return (-1);
        }
        /*
          When the semaphore is created, we know that the value of
          all 3 set members is 0.

          Get a lock on the semaphore by waiting for [2] to equal 0,
          then increment it.

          There is a race condition here. There is a possibility 
          that between the semget(2) and semop(2) below, another
          process can cal Semaphore:::close () member function
          which can remove a semaphore if that process is the last
          one using it.

          Therefore, we handle the error condition of an invalid
          semaphore ID specially below, and if it does happen, we
          just go back and create it again.
        */
        
        if (semop (m_id, &m_op_lock[0], 2) < 0) {
            if (errno == EINVAL) {
                continue;
            }
            EL((ASSAERR,"Can't lock semaphore\n"));
            Assure_exit (false);
        }
        done = true;
    } // while (!done)

    /*
      Get the value of the process counter. If it equals 0,
      then no one has initialized the semaphore yet.
    */
    if ((semval = semctl (m_id, 1, GETVAL, 0)) < 0) {
        EL((ASSAERR,"Can't GETVAL\n"));
        Assure_exit (false);
    }           
    
    if (semval == 0) {
        /*
          We could initalize by doing a SETALL, but that
          would clear the adjust value that we set when
          we locked the semaphore above. Instead, we'll do
          two system calls to initialize semaphore value [0]
          and process counter [1].
        */
        semctrl_arg.val = initval_;
        
        if (semctl (m_id, 0, SETVAL, semctrl_arg) < 0) {
            EL((ASSAERR,"Can't SETVAL[0]\n"));
            Assure_exit (false);
        }
        
        semctrl_arg.val = BIGCOUNT;
        
        if (semctl (m_id, 1, SETVAL, semctrl_arg) < 0) {
            EL((ASSAERR,"Can't SETVAL[1]\n"));
            Assure_exit (false);
        }
    } // if (semval == 0)

    /*--- Decrement the process counter and then release the lock. ---*/

    if (semop (m_id, &m_op_endcreate[0], 2) < 0) {
        EL((ASSAERR,"Error on semop (ndcreate)\n"));
        Assure_exit (false);
    }
    return (m_id);
}
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 294 of file Semaphore.cpp.

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

Referenced by op().

{
    trace_with_mask("Semaphore::dump", SEM);
    
    std::ostringstream msg;
    msg << "\n\n\tKey.....: ";

    if (m_key == (key_t) -1) {
        msg  << m_key;
    }
    else {
        msg << "0x" << std::hex << m_key << std::dec;
    }

    msg << "\n\tID......: " << m_id << "\n\n";

    if (m_id >= 0 && m_key >= (key_t) -1) {
        msg << "\tsemval [0]\tproc counter[1]\tlock [2]\n"
            << "\t----------\t---------------\t--------\n";
            
        /*--- Get value of element in semaphore set ---*/
        msg << "\t   "   << semctl (m_id, 0, GETVAL)
            << "\t\t   " << semctl (m_id, 1, GETVAL)
            << "\t\t   " << semctl (m_id, 2, GETVAL);
    }
    else { 
        msg << "Semaphore id = -1. No info is available."; 
    }
    msg << std::ends;
    DL((SEM,"%s\n\n", msg.str ().c_str ()));
}
int ASSA::Semaphore::id ( ) const [inline]

Get id.

Definition at line 136 of file Semaphore.h.

References m_id.

{ return m_id; }
void ASSA::Semaphore::init ( ) [inline, protected]

Initalize by invalidating data members.

Definition at line 210 of file Semaphore.h.

References m_id, and m_key.

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

{
    m_key = (key_t) -1;
    m_id  = -1;
}   
key_t ASSA::Semaphore::key ( ) const [inline]

Get key.

Definition at line 133 of file Semaphore.h.

References m_key.

{ return m_key; }
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 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().

{
        /* Test if m_id is still valid. If it fails, then
     * next operation is failing because of it. If not,
     * then something else happens here.
     */
    trace_with_mask("Semaphore::op", SEM);

    int semval = 0;
    dump ();

    if ((semval = semctl (m_id, 1, GETVAL, 0)) < 0) {
        EL((ASSAERR,"Can't GETVAL\n"));
        Assure_exit (false);
    }
        /* This will fail on Solaris? */

    if ((m_op_op[0].sem_op = value_) == 0) {
        EL((ASSAERR,"Can't have value_ == 0\n"));
        Assure_exit(false);
    }
    
    if (semop (m_id, &m_op_op[0], 1) < 0) {
        EL((ASSAERR,"sem_op error\n"));
        Assure_exit(false);
    }
}
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 176 of file Semaphore.cpp.

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

{
    trace_with_mask("Semaphore::open", SEM);

    if (IPC_PRIVATE == key_) {
        EL((ASSAERR,"Not intended for private semaphores\n"));
        return (-1);
    }
    else if (key_ == (key_t) -1) {
        EL((ASSAERR,"Probably an ftok() error by caller\n"));
        return (-1);
    }

    m_key = key_;
    
    if ((m_id = semget (m_key, 3, 0)) < 0) {
        EL((ASSAERR,"Error on semget(3)"));
        return (-1);
    }
    /*--- Decrement the process counter. No need for lock ---*/
    
    if (semop (m_id, &m_op_open[0], 1) < 0) {
        EL((ASSAERR,"Error on semget(open)\n"));
        Assure_exit(false);
    }       
    return (m_id);
}

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.

{
    trace_with_mask("Semaphore::remove", SEM);

    if (m_id < 0 || m_key == ((key_t) -1) ) return;

    if (semctl (m_id, 0, IPC_RMID, 0) < 0) {
        EL((ASSAERR,"Can't IPC_RMID\n"));
        Assure_exit(false);
    }
    init ();
}
void ASSA::Semaphore::signal ( ) [inline]

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.

{
    trace_with_mask("Semaphore::signal", SEM);
    op (1);
}
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.

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

{
    trace_with_mask("Semaphore::wait", SEM);
    op (-1);
}

Member Data Documentation

const int ASSA::Semaphore::BIGCOUNT = 10000 [static, protected]

Definition at line 156 of file Semaphore.h.

Referenced by close(), and create().

int ASSA::Semaphore::m_id [protected]

Semaphore's id.

Definition at line 153 of file Semaphore.h.

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

key_t ASSA::Semaphore::m_key [protected]

Semaphore's key.

Definition at line 150 of file Semaphore.h.

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

sembuf Semaphore::m_op_close [static, protected]
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 175 of file Semaphore.h.

Referenced by close().

sembuf Semaphore::m_op_endcreate [static, protected]
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 165 of file Semaphore.h.

Referenced by create().

sembuf Semaphore::m_op_lock [static, protected]
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 160 of file Semaphore.h.

Referenced by create().

sembuf Semaphore::m_op_op [static, protected]
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 185 of file Semaphore.h.

Referenced by op().

sembuf Semaphore::m_op_open [static, protected]
Initial value:
{
    {1, -1, SEM_UNDO},          
                                
}

Decrement process counter with undo on exit.

Definition at line 170 of file Semaphore.h.

Referenced by open().

sembuf Semaphore::m_op_unlock [static, protected]
Initial value:
{
    {2, -1, SEM_UNDO}           
}

Decremetn lock back to 0.

Definition at line 179 of file Semaphore.h.

Referenced by close().


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines