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


Public Types | |
| enum | { ACE_CREATE = IPC_CREAT, ACE_OPEN = 0 } |
Public Methods | |
| ACE_SV_Semaphore_Complex (void) | |
| ACE_SV_Semaphore_Complex (key_t key, int create=ACE_SV_Semaphore_Complex::ACE_CREATE, int initial_value=1, u_short nsems=1, int perms=ACE_DEFAULT_FILE_PERMS) | |
| ACE_SV_Semaphore_Complex (const char *name, int create=ACE_SV_Semaphore_Complex::ACE_CREATE, int initial_value=1, u_short nsems=1, int perms=ACE_DEFAULT_FILE_PERMS) | |
| ~ACE_SV_Semaphore_Complex (void) | |
| int | open (const char *name, int flags=ACE_SV_Semaphore_Simple::ACE_CREATE, int initial_value=1, u_short nsems=1, int perms=ACE_DEFAULT_FILE_PERMS) |
| Open or create an array of SV_Semaphores. We return 0 if all is OK, else -1. More... | |
| int | open (key_t key, int flags=ACE_SV_Semaphore_Simple::ACE_CREATE, int initial_value=1, u_short nsems=1, int perms=ACE_DEFAULT_FILE_PERMS) |
| Open or create an array of SV_Semaphores. We return 0 if all is OK, else -1. More... | |
| int | close (void) |
| int | acquire (u_short n=0, int flags=0) const |
| Acquire the semaphore. More... | |
| int | acquire_read (u_short n=0, int flags=0) const |
| Acquire a semaphore for reading. More... | |
| int | acquire_write (u_short n=0, int flags=0) const |
| Acquire a semaphore for writing. More... | |
| int | tryacquire (u_short n=0, int flags=0) const |
| Try to acquire the semaphore. More... | |
| int | tryacquire_read (u_short n=0, int flags=0) const |
| Try to acquire the semaphore for reading. More... | |
| int | tryacquire_write (u_short n=0, int flags=0) const |
| Try to acquire the semaphore for writing. More... | |
| int | release (u_short n=0, int flags=0) const |
| Release the semaphore. More... | |
| int | op (int val, u_short n=0, int flags=0) const |
| General ACE_SV_Semaphore operation. Increment or decrement by a specific amount (positive or negative; amount can`t be zero). More... | |
| int | op (sembuf op_vec[], u_short n) const |
| General ACE_SV_Semaphore operation on an array of SV_Semaphores. More... | |
| 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. More... | |
Public Attributes | |
| ACE_ALLOC_HOOK_DECLARE | |
| Declare the dynamic allocation hooks. More... | |
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 <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 52 of file SV_Semaphore_Complex.h.
|
|
Definition at line 55 of file SV_Semaphore_Complex.h.
00056 {
00057 ACE_CREATE = IPC_CREAT,
00058 ACE_OPEN = 0
00059 };
|
|
|
Definition at line 249 of file SV_Semaphore_Complex.cpp. References ACE_TRACE, and ACE_SV_Semaphore_Simple::init.
|
|
||||||||||||||||||||||||
|
Definition at line 212 of file SV_Semaphore_Complex.cpp. References ACE_ERROR, ACE_LIB_TEXT, ACE_TRACE, LM_ERROR, and open.
00217 {
00218 ACE_TRACE ("ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex");
00219 if (this->open (k, flags, initial_value, nsems, perms) == -1)
00220 ACE_ERROR ((LM_ERROR, ACE_LIB_TEXT ("%p\n"), ACE_LIB_TEXT ("ACE_SV_Semaphore_Complex")));
00221 }
|
|
||||||||||||||||||||||||
|
Definition at line 223 of file SV_Semaphore_Complex.cpp. References ACE_DEFAULT_SEM_KEY, ACE_ERROR, ACE_LIB_TEXT, ACE_TRACE, LM_ERROR, ACE_SV_Semaphore_Simple::name_2_key, and open.
00228 {
00229 ACE_TRACE ("ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex");
00230
00231 key_t key;
00232
00233 if (name == 0)
00234 key = ACE_DEFAULT_SEM_KEY;
00235 else
00236 key = this->name_2_key (name);
00237
00238 if (this->open (key, flags, initial_value, nsems, perms) == -1)
00239 ACE_ERROR ((LM_ERROR, ACE_LIB_TEXT ("%p\n"), ACE_LIB_TEXT ("ACE_SV_Semaphore_Complex")));
00240 }
|
|
|
Definition at line 242 of file SV_Semaphore_Complex.cpp. References ACE_TRACE, close, and ACE_SV_Semaphore_Simple::internal_id_.
00243 {
00244 ACE_TRACE ("ACE_SV_Semaphore_Complex::~ACE_SV_Semaphore_Complex");
00245 if (this->internal_id_ >= 0)
00246 this->close ();
00247 }
|
|
||||||||||||
|
Acquire the semaphore.
Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 9 of file SV_Semaphore_Complex.i. References ACE_TRACE, and ACE_SV_Semaphore_Simple::acquire. Referenced by acquire_read, and acquire_write.
00010 {
00011 ACE_TRACE ("ACE_SV_Semaphore_Complex::acquire");
00012 return ACE_SV_Semaphore_Simple::acquire ((u_short) n + 2, flags);
00013 }
|
|
||||||||||||
|
Acquire a semaphore for reading.
Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 16 of file SV_Semaphore_Complex.i. References ACE_TRACE, and acquire.
|
|
||||||||||||
|
Acquire a semaphore for writing.
Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 23 of file SV_Semaphore_Complex.i. References ACE_TRACE, and acquire.
|
|
|
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 176 of file SV_Semaphore_Complex.cpp. References ACE_TRACE, BIGCOUNT_, ACE_SV_Semaphore_Simple::control, GETVAL, ACE_SV_Semaphore_Simple::init, ACE_SV_Semaphore_Simple::internal_id_, ACE_SV_Semaphore_Simple::key_, op_close_, op_unlock_, ACE_SV_Semaphore_Simple::remove, and ACE_OS::semop. Referenced by ~ACE_SV_Semaphore_Complex.
00177 {
00178 ACE_TRACE ("ACE_SV_Semaphore_Complex::close");
00179 int semval;
00180
00181 if (this->key_ == (key_t) - 1 || this->internal_id_ == -1)
00182 return -1;
00183
00184 // The following semop() first gets a lock on the ACE_SV_Semaphore,
00185 // then increments [1] - the process number.
00186
00187 if (ACE_OS::semop (this->internal_id_,
00188 &ACE_SV_Semaphore_Complex::op_close_[0],
00189 3) == -1)
00190 return -1;
00191
00192 // Now that we have a lock, read the value of the process counter to
00193 // see if this is the last reference to the ACE_SV_Semaphore. There
00194 // is a race condition here - see the comments in create ().
00195
00196 if ((semval = ACE_SV_Semaphore_Simple::control (GETVAL, 0, 1)) == -1)
00197 return -1;
00198
00199 if (semval > ACE_SV_Semaphore_Complex::BIGCOUNT_)
00200 return -1;
00201 else if (semval == ACE_SV_Semaphore_Complex::BIGCOUNT_)
00202 return this->remove ();
00203 else
00204 {
00205 int result = ACE_OS::semop (this->internal_id_,
00206 &ACE_SV_Semaphore_Complex::op_unlock_[0], 1);
00207 this->init ();
00208 return result;
00209 }
00210 }
|
|
||||||||||||||||
|
Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 79 of file SV_Semaphore_Complex.i. References ACE_TRACE, and ACE_SV_Semaphore_Simple::control.
00080 {
00081 ACE_TRACE ("ACE_SV_Semaphore_Complex::control");
00082 return ACE_SV_Semaphore_Simple::control (cmd, value, (u_short) n + 2);
00083 }
|
|
||||||||||||||||
|
Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 72 of file SV_Semaphore_Complex.i. References ACE_TRACE, and ACE_SV_Semaphore_Simple::control. Referenced by open.
00073 {
00074 ACE_TRACE ("ACE_SV_Semaphore_Complex::control");
00075 return ACE_SV_Semaphore_Simple::control (cmd, arg, (u_short) n + 2);
00076 }
|
|
|
Dump the state of an object.
Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 17 of file SV_Semaphore_Complex.cpp. References ACE_TRACE.
00018 {
00019 ACE_TRACE ("ACE_SV_Semaphore_Complex::dump");
00020 }
|
|
||||||||||||
|
General ACE_SV_Semaphore operation on an array of SV_Semaphores.
Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 65 of file SV_Semaphore_Complex.i. References ACE_TRACE, and ACE_SV_Semaphore_Simple::op.
00066 {
00067 ACE_TRACE ("ACE_SV_Semaphore_Complex::op");
00068 return ACE_SV_Semaphore_Simple::op (op_vec, (u_short) n + 2);
00069 }
|
|
||||||||||||||||
|
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 58 of file SV_Semaphore_Complex.i. References ACE_TRACE, and ACE_SV_Semaphore_Simple::op.
00059 {
00060 ACE_TRACE ("ACE_SV_Semaphore_Complex::op");
00061 return ACE_SV_Semaphore_Simple::op (val, (u_short) n + 2, flags);
00062 }
|
|
||||||||||||||||||||||||
|
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 63 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, ACE_SV_Semaphore_Simple::internal_id_, IPC_PRIVATE, ACE_SV_Semaphore_Simple::key_, op_endcreate_, op_lock_, op_open_, ACE_SV_Semaphore_Simple::sem_number_, ACE_OS::semget, ACE_OS::semop, and SETVAL.
00068 {
00069 ACE_TRACE ("ACE_SV_Semaphore_Complex::open");
00070 if (k == IPC_PRIVATE)
00071 return -1;
00072
00073 this->key_ = k;
00074
00075 // Must include a count for the 2 additional semaphores we use
00076 // internally.
00077 this->sem_number_ = nsems + 2;
00078
00079 if (create == ACE_SV_Semaphore_Complex::ACE_CREATE)
00080 {
00081 int result;
00082
00083 do
00084 {
00085 this->internal_id_ = ACE_OS::semget
00086 (this->key_,
00087 (u_short) 2 + nsems,
00088 perms | ACE_SV_Semaphore_Complex::ACE_CREATE);
00089
00090 if (this->internal_id_ == -1)
00091 return -1; // permission problem or tables full
00092
00093 // When the <ACE_SV_Semaphore_Complex> is created, we know
00094 // that the value of all 3 members is 0. Get a lock on the
00095 // <ACE_SV_Semaphore_Complex> by waiting for [0] to equal 0,
00096 // then increment it.
00097
00098 // There is a race condition here. There is the possibility
00099 // that between the <semget> above and the <semop> below,
00100 // another process can call out <close> function which can
00101 // remove the <ACE_SV_Semaphore> if that process is the last
00102 // one using it. Therefor we handle the error condition of
00103 // an invalid <ACE_SV_Semaphore> ID specifically below, and
00104 // if it does happen, we just go back and create it again.
00105 result = ACE_OS::semop (this->internal_id_,
00106 &ACE_SV_Semaphore_Complex::op_lock_[0],
00107 2);
00108 }
00109 while (result == -1 && (errno == EINVAL || errno == EIDRM));
00110
00111 if (result == -1)
00112 return -1;
00113
00114 // Get the value of the process counter. If it equals 0, then no
00115 // one has initialized the ACE_SV_Semaphore yet.
00116
00117 int semval = ACE_SV_Semaphore_Simple::control (GETVAL, 0, 1);
00118
00119 if (semval == -1)
00120 return this->init ();
00121 else if (semval == 0)
00122 {
00123 // We should initialize by doing a SETALL, but that would
00124 // clear the adjust value that we set when we locked the
00125 // ACE_SV_Semaphore above. Instead we do system calls to
00126 // initialize [1], as well as all the nsems SV_Semaphores.
00127
00128 if (ACE_SV_Semaphore_Simple::control (SETVAL,
00129 ACE_SV_Semaphore_Complex::BIGCOUNT_,
00130 1) == -1)
00131 return -1;
00132 else
00133 for (int i = 0; i < nsems; i++)
00134 if (this->control (SETVAL, initial_value, i) == -1)
00135 return -1;
00136 }
00137
00138 // Decrement the process counter and then release the lock.
00139 return ACE_OS::semop (this->internal_id_,
00140 &ACE_SV_Semaphore_Complex::op_endcreate_[0],
00141 2);
00142 }
00143 else
00144 {
00145 this->internal_id_ = ACE_OS::semget (this->key_, 2 + nsems, 0);
00146 if (this->internal_id_ == -1)
00147 return -1; // doesn't exist or tables full
00148
00149 // Decrement the process counter. We don't need a lock to do this.
00150 if (ACE_OS::semop (this->internal_id_,
00151 &ACE_SV_Semaphore_Complex::op_open_[0], 1) < 0)
00152 return this->init ();
00153 return 0;
00154 }
00155 }
|
|
||||||||||||||||||||||||
|
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 158 of file SV_Semaphore_Complex.cpp. References ACE_TRACE, and ACE_SV_Semaphore_Simple::name_2_key. Referenced by ACE_SV_Semaphore_Complex.
00163 {
00164 ACE_TRACE ("ACE_SV_Semaphore_Complex::open");
00165 return this->open (ACE_SV_Semaphore_Simple::name_2_key (name),
00166 flags, initial_value, nsems, perms);
00167 }
|
|
||||||||||||
|
Release the semaphore.
Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 51 of file SV_Semaphore_Complex.i. References ACE_TRACE, and ACE_SV_Semaphore_Simple::release.
00052 {
00053 ACE_TRACE ("ACE_SV_Semaphore_Complex::release");
00054 return ACE_SV_Semaphore_Simple::release ((u_short) n + 2, flags);
00055 }
|
|
||||||||||||
|
Try to acquire the semaphore.
Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 30 of file SV_Semaphore_Complex.i. References ACE_TRACE, and ACE_SV_Semaphore_Simple::tryacquire. Referenced by tryacquire_read, and tryacquire_write.
00031 {
00032 ACE_TRACE ("ACE_SV_Semaphore_Complex::tryacquire");
00033 return ACE_SV_Semaphore_Simple::tryacquire ((u_short) n + 2, flags);
00034 }
|
|
||||||||||||
|
Try to acquire the semaphore for reading.
Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 37 of file SV_Semaphore_Complex.i. References ACE_TRACE, and tryacquire.
00038 {
00039 ACE_TRACE ("ACE_SV_Semaphore_Complex::tryacquire_read");
00040 return this->tryacquire (n, flags);
00041 }
|
|
||||||||||||
|
Try to acquire the semaphore for writing.
Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 44 of file SV_Semaphore_Complex.i. References ACE_TRACE, and tryacquire.
00045 {
00046 ACE_TRACE ("ACE_SV_Semaphore_Complex::tryacquire_write");
00047 return this->tryacquire (n, flags);
00048 }
|
|
|
Declare the dynamic allocation hooks.
Reimplemented from ACE_SV_Semaphore_Simple. Definition at line 139 of file SV_Semaphore_Complex.h. |
|
|
Definition at line 23 of file SV_Semaphore_Complex.cpp. |
|
|
Initial value: Definition at line 48 of file SV_Semaphore_Complex.cpp. Referenced by close. |
|
|
Initial value: Definition at line 34 of file SV_Semaphore_Complex.cpp. Referenced by open. |
|
|
Initial value:
{
{0, 0, 0},
{0, 1, SEM_UNDO},
}Definition at line 26 of file SV_Semaphore_Complex.cpp. Referenced by open. |
|
|
Initial value:
{
{1, -1, SEM_UNDO},
}Definition at line 42 of file SV_Semaphore_Complex.cpp. Referenced by open. |
|
|
Initial value:
{
{0, -1, SEM_UNDO},
}Definition at line 55 of file SV_Semaphore_Complex.cpp. Referenced by close. |
1.2.14 written by Dimitri van Heesch,
© 1997-2002