This is a more complex semaphore wrapper that handles race conditions for initialization correctly... More...
#include <SV_Semaphore_Complex.h>


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. | |
Public Attributes | |
| ACE_ALLOC_HOOK_DECLARE | |
| Declare the dynamic allocation hooks. | |
Static Private Attributes | |
| static const int | BIGCOUNT_ = 10000 |
| static sembuf | op_lock_ [2] |
| static sembuf | op_endcreate_ [2] |
| static sembuf | op_open_ [1] |
| static sembuf | op_close_ [3] |
| static sembuf | op_unlock_ [1] |
This is a more complex semaphore wrapper that handles race conditions for initialization correctly...
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 <ACE_SV_Semaphore_Complex>. The first member, [0], is a counter used to know when all processes have finished with the <ACE_SV_Semaphore_Complex>. 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 <close> 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 <ACE_SV_Semaphore_Complex>) 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 <create> and <close> 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.
| anonymous enum |
Definition at line 57 of file SV_Semaphore_Complex.h.
{
ACE_CREATE = IPC_CREAT,
ACE_OPEN = 0
};
| ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex | ( | void | ) |
Definition at line 253 of file SV_Semaphore_Complex.cpp.
| ACE_SV_Semaphore_Complex::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::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 | |||
| ) |
Definition at line 227 of file SV_Semaphore_Complex.cpp.
{
ACE_TRACE ("ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex");
key_t key;
if (name == 0)
key = ACE_DEFAULT_SEM_KEY;
else
key = this->name_2_key (name);
if (this->open (key, flags, initial_value, nsems, perms) == -1)
ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("ACE_SV_Semaphore_Complex")));
}
| ACE_SV_Semaphore_Complex::~ACE_SV_Semaphore_Complex | ( | void | ) |
Definition at line 246 of file SV_Semaphore_Complex.cpp.
{
ACE_TRACE ("ACE_SV_Semaphore_Complex::~ACE_SV_Semaphore_Complex");
if (this->internal_id_ >= 0)
this->close ();
}
| int ACE_SV_Semaphore_Complex::acquire | ( | u_short | n = 0, |
|
| short | flags = 0 | |||
| ) | const |
Acquire the semaphore.
Reimplemented from ACE_SV_Semaphore_Simple.
Definition at line 8 of file SV_Semaphore_Complex.inl.
{
ACE_TRACE ("ACE_SV_Semaphore_Complex::acquire");
return ACE_SV_Semaphore_Simple::acquire ((u_short) n + 2, flags);
}
| int ACE_SV_Semaphore_Complex::acquire_read | ( | u_short | n = 0, |
|
| short | flags = 0 | |||
| ) | const |
Acquire a semaphore for reading.
Reimplemented from ACE_SV_Semaphore_Simple.
Definition at line 15 of file SV_Semaphore_Complex.inl.
| int ACE_SV_Semaphore_Complex::acquire_write | ( | u_short | n = 0, |
|
| short | flags = 0 | |||
| ) | const |
Acquire a semaphore for writing.
Reimplemented from ACE_SV_Semaphore_Simple.
Definition at line 22 of file SV_Semaphore_Complex.inl.
| int ACE_SV_Semaphore_Complex::close | ( | void | ) |
Close an ACE_SV_Semaphore. Unlike the <remove> 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.
{
ACE_TRACE ("ACE_SV_Semaphore_Complex::close");
int semval;
if (this->key_ == (key_t) - 1 || this->internal_id_ == -1)
return -1;
// The following semop() first gets a lock on the ACE_SV_Semaphore,
// then increments [1] - the process number.
if (ACE_OS::semop (this->internal_id_,
&ACE_SV_Semaphore_Complex::op_close_[0],
3) == -1)
return -1;
// Now that we have a lock, read the value of the process counter to
// see if this is the last reference to the ACE_SV_Semaphore. There
// is a race condition here - see the comments in create ().
if ((semval = ACE_SV_Semaphore_Simple::control (GETVAL, 0, 1)) == -1)
return -1;
if (semval > ACE_SV_Semaphore_Complex::BIGCOUNT_)
return -1;
else if (semval == ACE_SV_Semaphore_Complex::BIGCOUNT_)
return this->remove ();
else
{
int result = ACE_OS::semop (this->internal_id_,
&ACE_SV_Semaphore_Complex::op_unlock_[0], 1);
this->init ();
return result;
}
}
| int ACE_SV_Semaphore_Complex::control | ( | int | cmd, | |
| semun | arg, | |||
| u_short | n = 0 | |||
| ) | const |
Reimplemented from ACE_SV_Semaphore_Simple.
Definition at line 71 of file SV_Semaphore_Complex.inl.
{
ACE_TRACE ("ACE_SV_Semaphore_Complex::control");
return ACE_SV_Semaphore_Simple::control (cmd, arg, (u_short) n + 2);
}
| int ACE_SV_Semaphore_Complex::control | ( | int | cmd, | |
| int | value = 0, |
|||
| u_short | n = 0 | |||
| ) | const |
Reimplemented from ACE_SV_Semaphore_Simple.
Definition at line 78 of file SV_Semaphore_Complex.inl.
{
ACE_TRACE ("ACE_SV_Semaphore_Complex::control");
return ACE_SV_Semaphore_Simple::control (cmd, value, (u_short) n + 2);
}
| void ACE_SV_Semaphore_Complex::dump | ( | void | ) | const |
Dump the state of an object.
Reimplemented from ACE_SV_Semaphore_Simple.
Definition at line 19 of file SV_Semaphore_Complex.cpp.
{
#if defined (ACE_HAS_DUMP)
ACE_TRACE ("ACE_SV_Semaphore_Complex::dump");
#endif /* ACE_HAS_DUMP */
}
| int ACE_SV_Semaphore_Complex::op | ( | short | val, | |
| u_short | semnum = 0, |
|||
| short | flags = 0 | |||
| ) | const |
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.
{
ACE_TRACE ("ACE_SV_Semaphore_Complex::op");
return ACE_SV_Semaphore_Simple::op (val, (u_short) n + 2, flags);
}
| int ACE_SV_Semaphore_Complex::op | ( | sembuf | op_vec[], | |
| u_short | nsems | |||
| ) | const |
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.
{
ACE_TRACE ("ACE_SV_Semaphore_Complex::op");
return ACE_SV_Semaphore_Simple::op (op_vec, (u_short) n + 2);
}
| int ACE_SV_Semaphore_Complex::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 | |||
| ) |
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.
{
ACE_TRACE ("ACE_SV_Semaphore_Complex::open");
if (k == IPC_PRIVATE)
return -1;
this->key_ = k;
// Must include a count for the 2 additional semaphores we use
// internally.
this->sem_number_ = nsems + 2;
if (create == ACE_SV_Semaphore_Complex::ACE_CREATE)
{
int result;
do
{
this->internal_id_ = ACE_OS::semget
(this->key_,
(u_short) 2 + nsems,
perms | ACE_SV_Semaphore_Complex::ACE_CREATE);
if (this->internal_id_ == -1)
return -1; // permission problem or tables full
// When the <ACE_SV_Semaphore_Complex> is created, we know
// that the value of all 3 members is 0. Get a lock on the
// <ACE_SV_Semaphore_Complex> by waiting for [0] to equal 0,
// then increment it.
// There is a race condition here. There is the possibility
// that between the <semget> above and the <semop> below,
// another process can call out <close> function which can
// remove the <ACE_SV_Semaphore> if that process is the last
// one using it. Therefor we handle the error condition of
// an invalid <ACE_SV_Semaphore> ID specifically below, and
// if it does happen, we just go back and create it again.
result = ACE_OS::semop (this->internal_id_,
&ACE_SV_Semaphore_Complex::op_lock_[0],
2);
}
while (result == -1 && (errno == EINVAL || errno == EIDRM));
if (result == -1)
return -1;
// Get the value of the process counter. If it equals 0, then no
// one has initialized the ACE_SV_Semaphore yet.
int semval = ACE_SV_Semaphore_Simple::control (GETVAL, 0, 1);
if (semval == -1)
return this->init ();
else if (semval == 0)
{
// We should initialize by doing a SETALL, but that would
// clear the adjust value that we set when we locked the
// ACE_SV_Semaphore above. Instead we do system calls to
// initialize [1], as well as all the nsems SV_Semaphores.
if (ACE_SV_Semaphore_Simple::control (SETVAL,
ACE_SV_Semaphore_Complex::BIGCOUNT_,
1) == -1)
return -1;
else
for (u_short i = 0; i < nsems; i++)
if (this->control (SETVAL, initial_value, i) == -1)
return -1;
}
// Decrement the process counter and then release the lock.
return ACE_OS::semop (this->internal_id_,
&ACE_SV_Semaphore_Complex::op_endcreate_[0],
2);
}
else
{
this->internal_id_ = ACE_OS::semget (this->key_, 2 + nsems, 0);
if (this->internal_id_ == -1)
return -1; // doesn't exist or tables full
// Decrement the process counter. We don't need a lock to do this.
if (ACE_OS::semop (this->internal_id_,
&ACE_SV_Semaphore_Complex::op_open_[0], 1) < 0)
return this->init ();
return 0;
}
}
| int ACE_SV_Semaphore_Complex::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 | |||
| ) |
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.
{
ACE_TRACE ("ACE_SV_Semaphore_Complex::open");
return this->open (ACE_SV_Semaphore_Simple::name_2_key (name),
flags, initial_value, nsems, perms);
}
| int ACE_SV_Semaphore_Complex::release | ( | u_short | n = 0, |
|
| short | flags = 0 | |||
| ) | const |
Release the semaphore.
Reimplemented from ACE_SV_Semaphore_Simple.
Definition at line 50 of file SV_Semaphore_Complex.inl.
{
ACE_TRACE ("ACE_SV_Semaphore_Complex::release");
return ACE_SV_Semaphore_Simple::release ((u_short) n + 2, flags);
}
| int ACE_SV_Semaphore_Complex::tryacquire | ( | u_short | n = 0, |
|
| short | flags = 0 | |||
| ) | const |
Try to acquire the semaphore.
Reimplemented from ACE_SV_Semaphore_Simple.
Definition at line 29 of file SV_Semaphore_Complex.inl.
{
ACE_TRACE ("ACE_SV_Semaphore_Complex::tryacquire");
return ACE_SV_Semaphore_Simple::tryacquire ((u_short) n + 2, flags);
}
| int ACE_SV_Semaphore_Complex::tryacquire_read | ( | u_short | n = 0, |
|
| short | flags = 0 | |||
| ) | const |
Try to acquire the semaphore for reading.
Reimplemented from ACE_SV_Semaphore_Simple.
Definition at line 36 of file SV_Semaphore_Complex.inl.
{
ACE_TRACE ("ACE_SV_Semaphore_Complex::tryacquire_read");
return this->tryacquire (n, flags);
}
| int ACE_SV_Semaphore_Complex::tryacquire_write | ( | u_short | n = 0, |
|
| short | flags = 0 | |||
| ) | const |
Try to acquire the semaphore for writing.
Reimplemented from ACE_SV_Semaphore_Simple.
Definition at line 43 of file SV_Semaphore_Complex.inl.
{
ACE_TRACE ("ACE_SV_Semaphore_Complex::tryacquire_write");
return this->tryacquire (n, flags);
}
Declare the dynamic allocation hooks.
Reimplemented from ACE_SV_Semaphore_Simple.
Definition at line 141 of file SV_Semaphore_Complex.h.
const int ACE_SV_Semaphore_Complex::BIGCOUNT_ = 10000 [static, private] |
Definition at line 144 of file SV_Semaphore_Complex.h.
sembuf ACE_SV_Semaphore_Complex::op_close_ [static, private] |
Definition at line 148 of file SV_Semaphore_Complex.h.
sembuf ACE_SV_Semaphore_Complex::op_endcreate_ [static, private] |
Definition at line 146 of file SV_Semaphore_Complex.h.
sembuf ACE_SV_Semaphore_Complex::op_lock_ [static, private] |
{
{0, 0, 0},
{0, 1, SEM_UNDO},
}
Definition at line 145 of file SV_Semaphore_Complex.h.
sembuf ACE_SV_Semaphore_Complex::op_open_ [static, private] |
{
{1, -1, SEM_UNDO},
}
Definition at line 147 of file SV_Semaphore_Complex.h.
sembuf ACE_SV_Semaphore_Complex::op_unlock_ [static, private] |
{
{0, -1, SEM_UNDO},
}
Definition at line 149 of file SV_Semaphore_Complex.h.
1.7.0