#include <SV_Semaphore_Complex.h>
Inheritance diagram for ACE_SV_Semaphore_Complex:
Public Types | |
ACE_CREATE = IPC_CREAT | |
ACE_OPEN = 0 | |
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 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.
00058 { 00059 ACE_CREATE = IPC_CREAT, 00060 ACE_OPEN = 0 00061 };
ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex | ( | void | ) |
Definition at line 253 of file SV_Semaphore_Complex.cpp.
References ACE_TRACE, and ACE_SV_Semaphore_Simple::init().
00254 { 00255 ACE_TRACE ("ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex"); 00256 this->init (); 00257 }
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 | |||
) |
Definition at line 216 of file SV_Semaphore_Complex.cpp.
References ACE_ERROR, ACE_TEXT, ACE_TRACE, and LM_ERROR.
00221 { 00222 ACE_TRACE ("ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex"); 00223 if (this->open (k, flags, initial_value, nsems, perms) == -1) 00224 ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("ACE_SV_Semaphore_Complex"))); 00225 }
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.
References ACE_DEFAULT_SEM_KEY, ACE_ERROR, ACE_TEXT, ACE_TRACE, LM_ERROR, and ACE_SV_Semaphore_Simple::name_2_key().
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 }
ACE_SV_Semaphore_Complex::~ACE_SV_Semaphore_Complex | ( | void | ) |
ACE_BEGIN_VERSIONED_NAMESPACE_DECL ACE_INLINE 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.
References ACE_TRACE, and ACE_SV_Semaphore_Simple::acquire().
Referenced by ACE_Process_Semaphore::acquire(), 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 }
ACE_INLINE 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.
References ACE_TRACE, and acquire().
00016 { 00017 ACE_TRACE ("ACE_SV_Semaphore_Complex::acquire_read"); 00018 return this->acquire (n, flags); 00019 }
ACE_INLINE 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.
References ACE_TRACE, and acquire().
00023 { 00024 ACE_TRACE ("ACE_SV_Semaphore_Complex::acquire_write"); 00025 return this->acquire (n, flags); 00026 }
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.
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 }
ACE_INLINE 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.
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 }
ACE_INLINE 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.
References ACE_TRACE, and ACE_SV_Semaphore_Simple::control().
00072 { 00073 ACE_TRACE ("ACE_SV_Semaphore_Complex::control"); 00074 return ACE_SV_Semaphore_Simple::control (cmd, arg, (u_short) n + 2); 00075 }
ACE_BEGIN_VERSIONED_NAMESPACE_DECL 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.
References ACE_TRACE.
00020 { 00021 #if defined (ACE_HAS_DUMP) 00022 ACE_TRACE ("ACE_SV_Semaphore_Complex::dump"); 00023 #endif /* ACE_HAS_DUMP */ 00024 }
ACE_INLINE int ACE_SV_Semaphore_Complex::op | ( | sembuf | op_vec[], | |
u_short | n | |||
) | 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.
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 }
ACE_INLINE int ACE_SV_Semaphore_Complex::op | ( | short | val, | |
u_short | n = 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.
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 }
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.
References ACE_CREATE, ACE_TRACE, BIGCOUNT_, 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.
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 }
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.
References ACE_TRACE, and ACE_SV_Semaphore_Simple::name_2_key().
00167 { 00168 ACE_TRACE ("ACE_SV_Semaphore_Complex::open"); 00169 return this->open (ACE_SV_Semaphore_Simple::name_2_key (name), 00170 flags, initial_value, nsems, perms); 00171 }
ACE_INLINE 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.
References ACE_TRACE, and ACE_SV_Semaphore_Simple::release().
Referenced by ACE_Process_Semaphore::release().
00051 { 00052 ACE_TRACE ("ACE_SV_Semaphore_Complex::release"); 00053 return ACE_SV_Semaphore_Simple::release ((u_short) n + 2, flags); 00054 }
ACE_INLINE 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.
References ACE_TRACE, and ACE_SV_Semaphore_Simple::tryacquire().
Referenced by ACE_Process_Semaphore::tryacquire(), 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 }
ACE_INLINE 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.
References ACE_TRACE, and tryacquire().
00037 { 00038 ACE_TRACE ("ACE_SV_Semaphore_Complex::tryacquire_read"); 00039 return this->tryacquire (n, flags); 00040 }
ACE_INLINE 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.
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.
const int ACE_SV_Semaphore_Complex::BIGCOUNT_ = 10000 [static, private] |
sembuf ACE_SV_Semaphore_Complex::op_close_ [static, private] |
sembuf ACE_SV_Semaphore_Complex::op_endcreate_ [static, private] |
sembuf ACE_SV_Semaphore_Complex::op_lock_ [static, private] |
Initial value:
{ {0, 0, 0}, {0, 1, SEM_UNDO}, }
Definition at line 145 of file SV_Semaphore_Complex.h.
Referenced by open().
sembuf ACE_SV_Semaphore_Complex::op_open_ [static, private] |
Initial value:
{ {1, -1, SEM_UNDO}, }
Definition at line 147 of file SV_Semaphore_Complex.h.
Referenced by open().
sembuf ACE_SV_Semaphore_Complex::op_unlock_ [static, private] |
Initial value:
{ {0, -1, SEM_UNDO}, }
Definition at line 149 of file SV_Semaphore_Complex.h.
Referenced by close().