#include <SV_Semaphore_Complex.h>
Inheritance diagram for ACE_SV_Semaphore_Complex:


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. | |
| int | get_id (void) const |
| Get underlying internal id. | |
| int | remove (void) const |
Public Attributes | |
| ACE_ALLOC_HOOK_DECLARE | |
| Declare the dynamic allocation hooks. | |
Static Private Attributes | |
| const int | BIGCOUNT_ = 10000 |
| sembuf | op_lock_ [2] |
| sembuf | op_endcreate_ [2] |
| sembuf | op_open_ [1] |
| sembuf | op_close_ [3] |
| sembuf | op_unlock_ [1] |
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 . The first member, [0], is a counter used to know when all processes have finished with the . 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 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 ) 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 and 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.
|
|
Definition at line 57 of file SV_Semaphore_Complex.h.
00058 {
00059 ACE_CREATE = IPC_CREAT,
00060 ACE_OPEN = 0
00061 };
|
|
|
Definition at line 253 of file SV_Semaphore_Complex.cpp. References ACE_TRACE, and ACE_SV_Semaphore_Simple::init().
|
|
||||||||||||||||||||||||
|
Definition at line 216 of file SV_Semaphore_Complex.cpp. References ACE_ERROR, ACE_TEXT, ACE_TRACE, LM_ERROR, mode_t, and open().
|
|
||||||||||||||||||||||||
|
Definition at line 227 of file SV_Semaphore_Complex.cpp. References ACE_DEFAULT_SEM_KEY, ACE_ERROR, ACE_TEXT, ACE_TRACE, LM_ERROR, mode_t, ACE_SV_Semaphore_Simple::name_2_key(), and open().
00232 {
00233 ACE_TRACE ("ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex");
00234
00235 key_t key;
00236
00237 if (name == 0)
00238 key = ACE_DEFAULT_SEM_KEY;
00239 else
00240 key = this->name_2_key (name);
00241
00242 if (this->open (key, flags, initial_value, nsems, perms) == -1)
00243 ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("ACE_SV_Semaphore_Complex")));
00244 }
|
|
|
Definition at line 246 of file SV_Semaphore_Complex.cpp. References ACE_TRACE, and close().
00247 {
00248 ACE_TRACE ("ACE_SV_Semaphore_Complex::~ACE_SV_Semaphore_Complex");
00249 if (this->internal_id_ >= 0)
00250 this->close ();
00251 }
|
|
||||||||||||
|
Acquire the semaphore.
Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 8 of file SV_Semaphore_Complex.inl. References ACE_TRACE, and ACE_SV_Semaphore_Simple::acquire(). Referenced by acquire_read(), and acquire_write().
00009 {
00010 ACE_TRACE ("ACE_SV_Semaphore_Complex::acquire");
00011 return ACE_SV_Semaphore_Simple::acquire ((u_short) n + 2, flags);
00012 }
|
|
||||||||||||
|
Acquire a semaphore for reading.
Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 15 of file SV_Semaphore_Complex.inl. References ACE_TRACE, and acquire().
|
|
||||||||||||
|
Acquire a semaphore for writing.
Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 22 of file SV_Semaphore_Complex.inl. References ACE_TRACE, and acquire().
|
|
|
Close an ACE_SV_Semaphore. Unlike the 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. References ACE_TRACE, BIGCOUNT_, ACE_SV_Semaphore_Simple::control(), GETVAL, ACE_SV_Semaphore_Simple::init(), op_close_, op_unlock_, ACE_SV_Semaphore_Simple::remove(), and ACE_OS::semop(). Referenced by ~ACE_SV_Semaphore_Complex().
00181 {
00182 ACE_TRACE ("ACE_SV_Semaphore_Complex::close");
00183 int semval;
00184
00185 if (this->key_ == (key_t) - 1 || this->internal_id_ == -1)
00186 return -1;
00187
00188 // The following semop() first gets a lock on the ACE_SV_Semaphore,
00189 // then increments [1] - the process number.
00190
00191 if (ACE_OS::semop (this->internal_id_,
00192 &ACE_SV_Semaphore_Complex::op_close_[0],
00193 3) == -1)
00194 return -1;
00195
00196 // Now that we have a lock, read the value of the process counter to
00197 // see if this is the last reference to the ACE_SV_Semaphore. There
00198 // is a race condition here - see the comments in create ().
00199
00200 if ((semval = ACE_SV_Semaphore_Simple::control (GETVAL, 0, 1)) == -1)
00201 return -1;
00202
00203 if (semval > ACE_SV_Semaphore_Complex::BIGCOUNT_)
00204 return -1;
00205 else if (semval == ACE_SV_Semaphore_Complex::BIGCOUNT_)
00206 return this->remove ();
00207 else
00208 {
00209 int result = ACE_OS::semop (this->internal_id_,
00210 &ACE_SV_Semaphore_Complex::op_unlock_[0], 1);
00211 this->init ();
00212 return result;
00213 }
00214 }
|
|
||||||||||||||||
|
Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 78 of file SV_Semaphore_Complex.inl. References ACE_TRACE, and ACE_SV_Semaphore_Simple::control().
00079 {
00080 ACE_TRACE ("ACE_SV_Semaphore_Complex::control");
00081 return ACE_SV_Semaphore_Simple::control (cmd, value, (u_short) n + 2);
00082 }
|
|
||||||||||||||||
|
Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 71 of file SV_Semaphore_Complex.inl. References ACE_TRACE, and ACE_SV_Semaphore_Simple::control(). Referenced by open().
00072 {
00073 ACE_TRACE ("ACE_SV_Semaphore_Complex::control");
00074 return ACE_SV_Semaphore_Simple::control (cmd, arg, (u_short) n + 2);
00075 }
|
|
|
Dump the state of an object.
Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 19 of file SV_Semaphore_Complex.cpp. References ACE_TRACE.
00020 {
00021 #if defined (ACE_HAS_DUMP)
00022 ACE_TRACE ("ACE_SV_Semaphore_Complex::dump");
00023 #endif /* ACE_HAS_DUMP */
00024 }
|
|
|
Get underlying internal id.
Definition at line 122 of file SV_Semaphore_Simple.inl.
00123 {
00124 ACE_TRACE ("ACE_SV_Semaphore_Simple::get_id");
00125 return this->internal_id_;
00126 }
|
|
||||||||||||
|
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. References ACE_TRACE, and ACE_SV_Semaphore_Simple::op().
00065 {
00066 ACE_TRACE ("ACE_SV_Semaphore_Complex::op");
00067 return ACE_SV_Semaphore_Simple::op (op_vec, (u_short) n + 2);
00068 }
|
|
||||||||||||||||
|
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. References ACE_TRACE, and ACE_SV_Semaphore_Simple::op().
00058 {
00059 ACE_TRACE ("ACE_SV_Semaphore_Complex::op");
00060 return ACE_SV_Semaphore_Simple::op (val, (u_short) n + 2, flags);
00061 }
|
|
||||||||||||||||||||||||
|
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. References ACE_CREATE, ACE_TRACE, BIGCOUNT_, control(), ACE_SV_Semaphore_Simple::control(), EIDRM, GETVAL, ACE_SV_Semaphore_Simple::init(), IPC_PRIVATE, mode_t, op_endcreate_, op_lock_, op_open_, ACE_OS::semget(), ACE_OS::semop(), and SETVAL.
00072 {
00073 ACE_TRACE ("ACE_SV_Semaphore_Complex::open");
00074 if (k == IPC_PRIVATE)
00075 return -1;
00076
00077 this->key_ = k;
00078
00079 // Must include a count for the 2 additional semaphores we use
00080 // internally.
00081 this->sem_number_ = nsems + 2;
00082
00083 if (create == ACE_SV_Semaphore_Complex::ACE_CREATE)
00084 {
00085 int result;
00086
00087 do
00088 {
00089 this->internal_id_ = ACE_OS::semget
00090 (this->key_,
00091 (u_short) 2 + nsems,
00092 perms | ACE_SV_Semaphore_Complex::ACE_CREATE);
00093
00094 if (this->internal_id_ == -1)
00095 return -1; // permission problem or tables full
00096
00097 // When the <ACE_SV_Semaphore_Complex> is created, we know
00098 // that the value of all 3 members is 0. Get a lock on the
00099 // <ACE_SV_Semaphore_Complex> by waiting for [0] to equal 0,
00100 // then increment it.
00101
00102 // There is a race condition here. There is the possibility
00103 // that between the <semget> above and the <semop> below,
00104 // another process can call out <close> function which can
00105 // remove the <ACE_SV_Semaphore> if that process is the last
00106 // one using it. Therefor we handle the error condition of
00107 // an invalid <ACE_SV_Semaphore> ID specifically below, and
00108 // if it does happen, we just go back and create it again.
00109 result = ACE_OS::semop (this->internal_id_,
00110 &ACE_SV_Semaphore_Complex::op_lock_[0],
00111 2);
00112 }
00113 while (result == -1 && (errno == EINVAL || errno == EIDRM));
00114
00115 if (result == -1)
00116 return -1;
00117
00118 // Get the value of the process counter. If it equals 0, then no
00119 // one has initialized the ACE_SV_Semaphore yet.
00120
00121 int semval = ACE_SV_Semaphore_Simple::control (GETVAL, 0, 1);
00122
00123 if (semval == -1)
00124 return this->init ();
00125 else if (semval == 0)
00126 {
00127 // We should initialize by doing a SETALL, but that would
00128 // clear the adjust value that we set when we locked the
00129 // ACE_SV_Semaphore above. Instead we do system calls to
00130 // initialize [1], as well as all the nsems SV_Semaphores.
00131
00132 if (ACE_SV_Semaphore_Simple::control (SETVAL,
00133 ACE_SV_Semaphore_Complex::BIGCOUNT_,
00134 1) == -1)
00135 return -1;
00136 else
00137 for (u_short i = 0; i < nsems; i++)
00138 if (this->control (SETVAL, initial_value, i) == -1)
00139 return -1;
00140 }
00141
00142 // Decrement the process counter and then release the lock.
00143 return ACE_OS::semop (this->internal_id_,
00144 &ACE_SV_Semaphore_Complex::op_endcreate_[0],
00145 2);
00146 }
00147 else
00148 {
00149 this->internal_id_ = ACE_OS::semget (this->key_, 2 + nsems, 0);
00150 if (this->internal_id_ == -1)
00151 return -1; // doesn't exist or tables full
00152
00153 // Decrement the process counter. We don't need a lock to do this.
00154 if (ACE_OS::semop (this->internal_id_,
00155 &ACE_SV_Semaphore_Complex::op_open_[0], 1) < 0)
00156 return this->init ();
00157 return 0;
00158 }
00159 }
|
|
||||||||||||||||||||||||
|
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. References ACE_TRACE, and mode_t. Referenced by ACE_SV_Semaphore_Complex().
|
|
||||||||||||
|
Release the semaphore.
Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 50 of file SV_Semaphore_Complex.inl. References ACE_TRACE, and ACE_SV_Semaphore_Simple::release().
00051 {
00052 ACE_TRACE ("ACE_SV_Semaphore_Complex::release");
00053 return ACE_SV_Semaphore_Simple::release ((u_short) n + 2, flags);
00054 }
|
|
|
Remove all SV_Semaphores associated with a particular key. This call is intended to be called from a server, for example, when it is being shut down, as we do an IPC_RMID on the ACE_SV_Semaphore, regardless of whether other processes may be using it or not. Most other processes should use below. Definition at line 229 of file SV_Semaphore_Simple.cpp.
00230 {
00231 ACE_TRACE ("ACE_SV_Semaphore_Simple::remove");
00232 int const result = this->control (IPC_RMID);
00233 ((ACE_SV_Semaphore_Simple *) this)->init ();
00234 return result;
00235 }
|
|
||||||||||||
|
Try to acquire the semaphore.
Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 29 of file SV_Semaphore_Complex.inl. References ACE_TRACE, and ACE_SV_Semaphore_Simple::tryacquire(). Referenced by tryacquire_read(), and tryacquire_write().
00030 {
00031 ACE_TRACE ("ACE_SV_Semaphore_Complex::tryacquire");
00032 return ACE_SV_Semaphore_Simple::tryacquire ((u_short) n + 2, flags);
00033 }
|
|
||||||||||||
|
Try to acquire the semaphore for reading.
Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 36 of file SV_Semaphore_Complex.inl. References ACE_TRACE, and tryacquire().
00037 {
00038 ACE_TRACE ("ACE_SV_Semaphore_Complex::tryacquire_read");
00039 return this->tryacquire (n, flags);
00040 }
|
|
||||||||||||
|
Try to acquire the semaphore for writing.
Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 43 of file SV_Semaphore_Complex.inl. References ACE_TRACE, and tryacquire().
00044 {
00045 ACE_TRACE ("ACE_SV_Semaphore_Complex::tryacquire_write");
00046 return this->tryacquire (n, flags);
00047 }
|
|
|
Declare the dynamic allocation hooks.
Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 141 of file SV_Semaphore_Complex.h. |
|
|
Definition at line 27 of file SV_Semaphore_Complex.cpp. |
|
|
Initial value: Definition at line 52 of file SV_Semaphore_Complex.cpp. Referenced by close(). |
|
|
Initial value: Definition at line 38 of file SV_Semaphore_Complex.cpp. Referenced by open(). |
|
|
Initial value:
{
{0, 0, 0},
{0, 1, SEM_UNDO},
}
Definition at line 30 of file SV_Semaphore_Complex.cpp. Referenced by open(). |
|
|
Initial value:
{
{1, -1, SEM_UNDO},
}
Definition at line 46 of file SV_Semaphore_Complex.cpp. Referenced by open(). |
|
|
Initial value:
{
{0, -1, SEM_UNDO},
}
Definition at line 59 of file SV_Semaphore_Complex.cpp. Referenced by close(). |
1.3.6