KSquare Utilities
KKB::GoalKeeperSimple Class Reference

A simple/ light-weight implementation of critical section blocking. More...

#include <GoalKeeperSimple.h>

Public Types

typedef GoalKeeperSimpleGoalKeeperSimplePtr
 

Public Member Functions

bool Blocked ()
 Will return true if any thread lock on this instance of "GoalKeeperSimple". More...
 
bool BlockedByAnotherThread ()
 Returns true if a different thread has this instance of "GoalKeeperSimple" locked. More...
 
kkint32 BlockerThreadId ()
 ThreadId of thread that currently holds the Block -1 indicates no Block. More...
 
void EndBlock ()
 Ends the block and allows other threads to pass through StatBlock. More...
 
kkint32 MemoryConsumedEstimated () const
 
const KKStrName () const
 
void StartBlock ()
 Initiates a Block as long as another thread has not already locked this object. More...
 

Static Public Member Functions

static void Create (const KKStr &_name, volatile GoalKeeperSimplePtr &_newGoalKeeper)
 Create a GoalKeeperSimple object and avoid a race condition doing it. More...
 
static void CreateAndStartBlock (const KKStr &_name, volatile GoalKeeperSimplePtr &_newGoalKeeper, bool &_didNotExistYet)
 Create a GoalKeeperSimple object and avoid a race condition doing it. More...
 
static void Destroy (volatile GoalKeeperSimplePtr &_goalKeeperInstance)
 Destroys an existing instance of GoalKeeperSimple. More...
 
static void FinalCleanUp ()
 Will be registered with 'atexit' so that it will be called when program is unloaded from memory. More...
 

Friends

class KKQueue< GoalKeeperSimple >
 

Detailed Description

A simple/ light-weight implementation of critical section blocking.

Definition at line 29 of file GoalKeeperSimple.h.

Member Typedef Documentation

Member Function Documentation

bool GoalKeeperSimple::Blocked ( )

Will return true if any thread lock on this instance of "GoalKeeperSimple".

Definition at line 76 of file GoalKeeperSimple.cpp.

77 {
78  return blocked;
79 } /* Blocked */
bool GoalKeeperSimple::BlockedByAnotherThread ( )

Returns true if a different thread has this instance of "GoalKeeperSimple" locked.

GoalKeeperSimple keeps track of which thread has a lock on this instance of 'GoalKeeperSimple'. This way we know if the calling thread is not the one to have a lock on the thread.

Definition at line 83 of file GoalKeeperSimple.cpp.

References KKB::osGetThreadId().

84 {
85  if (!blocked)
86  return false;
87 
88  kkint32 curThreadId = KKB::osGetThreadId ();
89  return (blocked && (curThreadId != blockerThreadId));
90 }
__int32 kkint32
Definition: KKBaseTypes.h:88
kkint32 osGetThreadId()
kkint32 GoalKeeperSimple::BlockerThreadId ( )

ThreadId of thread that currently holds the Block -1 indicates no Block.

Definition at line 404 of file GoalKeeperSimple.cpp.

405 {
406  kkint32 x = 0;
407  x = blockerThreadId;
408  return x;
409 }
__int32 kkint32
Definition: KKBaseTypes.h:88
void GoalKeeperSimple::Create ( const KKStr _name,
volatile GoalKeeperSimplePtr _newGoalKeeper 
)
static

Create a GoalKeeperSimple object and avoid a race condition doing it.

In case two different threads try to create the same GoalKeeperSimple at the same time you only want one of them to succeed and the other to use same GaolKeeper object.

Parameters
[in]_nameName of Goal Keeper object that you want to create.
[in,out]_newGoalKeeperYou pass this in. Create will block out the critical region that creates the GoalKeeperSimple object. If it was already created, that is != NULL will just return not changing its value. If it is still NULL in the critical section it will create a new instance and set this parameter to its address.

< default security attributes

< initially not owned

Definition at line 160 of file GoalKeeperSimple.cpp.

References KKB::GoalKeeperSimpleList::GoalKeeperSimpleList().

Referenced by KKB::MsgQueue::MsgQueue().

163 {
164 #if defined(WIN32)
165  HANDLE mutexCreateHandle = CreateMutex (NULL, /**< default security attributes */
166  false, /**< initially not owned */
167  "GoalKeeperClass"
168  );
169  if (!mutexCreateHandle)
170  {
171  KKStr errMsg = "GoalKeeperSimple::Create ***ERROR*** CreateMutex failed; returned back NULL; _name:" + _name;
172  cerr << endl << errMsg << endl << endl;
173  throw KKException (errMsg);
174  }
175 
176  WaitForSingleObject (mutexCreateHandle, INFINITE);
177 
178  if (_newGoalKeeper == NULL)
179  {
180  _newGoalKeeper = new GoalKeeperSimple (_name);
181  if (existingGoalKeepers == NULL)
182  {
183  existingGoalKeepers = new GoalKeeperSimpleList (true);
185  }
186  existingGoalKeepers->PushOnBack (_newGoalKeeper);
187  }
188 
189  ReleaseMutex (mutexCreateHandle);
190  CloseHandle(mutexCreateHandle);
191 #else
192  sem_t* semHandle = sem_open ("GoalKeeperClass", O_CREAT, 0644, 1);
193  if (semHandle == SEM_FAILED)
194  {
195  cout << std::endl
196  << "GoalKeeperSimple::Create Error[" << errno << "] opening '/GoalKeeperSimple' Semaphore." << std::endl
197  << std::endl;
198 
199  perror("GoalKeeperSimple::Create Error Opening Semaphore 'GoalKeeperSimple'");
200 
201  throw "GoalKeeperSimple::Create Error opening 'GoalKeeperSimple'.";
202  }
203 
204  sem_wait (semHandle);
205 
206  if (_newGoalKeeper == NULL)
207  {
208  _newGoalKeeper = new GoalKeeperSimple (_name);
209  if (existingGoalKeepers == NULL)
210  {
211  existingGoalKeepers = new GoalKeeperSimpleList (true);
213  }
214  existingGoalKeepers->PushOnBack (_newGoalKeeper);
215  }
216 
217  sem_post (semHandle);
218  sem_close (semHandle);
219 #endif
220 } /* Create */
HTMLReport &__cdecl endl(HTMLReport &htmlReport)
Definition: HTMLReport.cpp:240
A simple/ light-weight implementation of critical section blocking.
virtual void PushOnBack(EntryPtr _entry)
Definition: KKQueue.h:398
static void FinalCleanUp()
Will be registered with &#39;atexit&#39; so that it will be called when program is unloaded from memory...
void GoalKeeperSimple::CreateAndStartBlock ( const KKStr _name,
volatile GoalKeeperSimplePtr _newGoalKeeper,
bool &  _didNotExistYet 
)
static

Create a GoalKeeperSimple object and avoid a race condition doing it.

Create a new instance of a GoalKeeperSimple object if it has not already been done and locks it if we create it.

Similar to 'Create' except it will also call the StartBlock method. There is also an additional parameter that will let you know if your call was responsible for creating it.

In case two different threads try to create the same GoalKeeperSimple at the same time you only want one of them to succeed and the other to use same GaolKeeper object.

Parameters
[in]_nameName of Goal Keeper object that you want to create.
[in,out]_newGoalKeeperYou pass this in. Create will block out the critical region that creates the GoalKeeperSimple object. If it was already created, that is != NULL will just return not changing its value. If it is still NULL in the critical section it will create a new instance and set this parameter to its address.
[out]_didNotExistYetIndicates if this call had to create the GoalKeeperSimple instance; if it already existed will return as false.
[in]_nameName to be assigned to GoalKeeperSimple object.
[in,out]_newGoalKeeperA pointer to the GoalKeeperSimple that already exists or to new one that got created.
[out]_didNotExistYetIndicates if the call to 'CreateAndStartBlock' had to create a new instance.

< default security attributes.

< initially not owned.

Definition at line 231 of file GoalKeeperSimple.cpp.

References KKB::GoalKeeperSimpleList::GoalKeeperSimpleList(), and StartBlock().

235 {
236 #if defined(WIN32)
237  HANDLE mutexCreateHandle = CreateMutex (NULL, /**< default security attributes. */
238  false, /**< initially not owned. */
239  "GoalKeeperClass"
240  );
241  if (!mutexCreateHandle)
242  {
243  KKStr errMsg = "GoalKeeperSimple::CreateAndStartBlock ***ERROR*** CreateMutex failed; returned back NULL; _name:" + _name;
244  cerr << endl << errMsg << endl << endl;
245  throw KKException(errMsg);
246  }
247 
248  WaitForSingleObject (mutexCreateHandle, INFINITE);
249 
250  if (_newGoalKeeper == NULL)
251  {
252  _didNotExistYet = true;
253  _newGoalKeeper = new GoalKeeperSimple (_name);
254 
255  if (existingGoalKeepers == NULL)
256  {
257  existingGoalKeepers = new GoalKeeperSimpleList (true);
259  }
260  existingGoalKeepers->PushOnBack (_newGoalKeeper);
261  }
262  else
263  {
264  _didNotExistYet = false;
265  }
266 
267  _newGoalKeeper->StartBlock ();
268 
269  ReleaseMutex (mutexCreateHandle);
270  CloseHandle(mutexCreateHandle);
271 #else
272  sem_t* semHandle = sem_open ("GoalKeeperClass", O_CREAT, 0644, 1);
273  if (semHandle == SEM_FAILED)
274  {
275  cout << std::endl
276  << "GoalKeeperSimple::Create Error[" << errno << "] opening '/GoalKeeperSimple' Semaphore." << std::endl
277  << std::endl;
278 
279  perror("GoalKeeperSimple::Create Error Opening Semaphore 'GoalKeeperSimple'");
280 
281  throw "GoalKeeperSimple::Create Error opening 'GoalKeeperSimple'.";
282  }
283 
284  sem_wait (semHandle);
285 
286  if (_newGoalKeeper == NULL)
287  {
288  _didNotExistYet = true;
289  _newGoalKeeper = new GoalKeeperSimple (_name);
290  if (existingGoalKeepers == NULL)
291  {
292  existingGoalKeepers = new GoalKeeperSimpleList (true);
294  }
295  existingGoalKeepers->PushOnBack (_newGoalKeeper);
296  }
297  else
298  {
299  _didNotExistYet = false;
300  }
301 
302  _newGoalKeeper->StartBlock ();
303 
304  sem_post (semHandle);
305  sem_close (semHandle);
306 #endif
307 } /* CreateAndStartBlock */
HTMLReport &__cdecl endl(HTMLReport &htmlReport)
Definition: HTMLReport.cpp:240
A simple/ light-weight implementation of critical section blocking.
virtual void PushOnBack(EntryPtr _entry)
Definition: KKQueue.h:398
static void FinalCleanUp()
Will be registered with &#39;atexit&#39; so that it will be called when program is unloaded from memory...
void GoalKeeperSimple::Destroy ( volatile GoalKeeperSimplePtr _goalKeeperInstance)
static

Destroys an existing instance of GoalKeeperSimple.

Use this method rather than calling the destructor directly. This way the 'existingGoalKeepers' data member can be kept up to date. If for some reason two different threads managed to call this method for the same GoalKeeperSimple instance only one of them will actually destroy the instance.

Parameters
[in,out]_goalKeeperInstanceInstance of GoalKeeperSimple that is to be destroyed. Upon return it will be set to NULL.

< default security attributes

< initially not owned

Definition at line 313 of file GoalKeeperSimple.cpp.

Referenced by KKB::MsgQueue::~MsgQueue().

314 {
315 #if defined(WIN32)
316  HANDLE mutexCreateHandle = CreateMutex (NULL, /**< default security attributes */
317  false, /**< initially not owned */
318  "GoalKeeperClass"
319  );
320  if (!mutexCreateHandle)
321  {
322  KKStr errMsg = "GoalKeeperSimple::Destroy ***ERROR*** CreateMutex failed; returned back NULL";
323  cerr << endl << errMsg << endl << endl;
324  throw KKException(errMsg);
325  }
326 
327  WaitForSingleObject (mutexCreateHandle, INFINITE);
328 
329  if (_goalKeeperInstance == NULL)
330  {
331  // Some other thread managed to destroy this instance.
332  }
333  else
334  {
335  kkint32 existingInstanceIdx = existingGoalKeepers->PtrToIdx (_goalKeeperInstance);
336  if (existingInstanceIdx < 0)
337  {
338  // If not in list then a different thread beat us to destroying this instance or it was never created to start with.
339  }
340  else
341  {
342  existingGoalKeepers->DeleteEntry (_goalKeeperInstance);
343  delete _goalKeeperInstance;
344  _goalKeeperInstance = NULL;
345  }
346  }
347 
348  ReleaseMutex (mutexCreateHandle);
349  CloseHandle(mutexCreateHandle);
350 #else
351  sem_t* semHandle = sem_open ("GoalKeeperClass", O_CREAT, 0644, 1);
352  if (semHandle == SEM_FAILED)
353  {
354  cout << std::endl
355  << "GoalKeeperSimple::Create Error[" << errno << "] opening '/GoalKeeperSimple' Semaphore." << std::endl
356  << std::endl;
357 
358  perror("GoalKeeperSimple::Create Error Opening Semaphore 'GoalKeeperSimple'");
359 
360  throw "GoalKeeperSimple::Create Error opening 'GoalKeeperSimple'.";
361  }
362 
363  sem_wait (semHandle);
364 
365  if (_goalKeeperInstance == NULL)
366  {
367  // Some other thread managed to destroy this instance.
368  }
369  else
370  {
371  kkint32 existingInstanceIdx = existingGoalKeepers->PtrToIdx (_goalKeeperInstance);
372  if (existingInstanceIdx >= 0)
373  {
374  // If not in list then a different thread beat us to destroying this instance or it was never created to start with.
375  }
376  else
377  {
378  existingGoalKeepers->DeleteEntry (_goalKeeperInstance);
379  delete _goalKeeperInstance;
380  _goalKeeperInstance = NULL;
381  }
382  }
383 
384  sem_post (semHandle);
385  sem_close (semHandle);
386 #endif
387 
388 } /* Destroy */
HTMLReport &__cdecl endl(HTMLReport &htmlReport)
Definition: HTMLReport.cpp:240
__int32 kkint32
Definition: KKBaseTypes.h:88
void DeleteEntry(EntryPtr _entry)
Definition: KKQueue.h:684
kkint32 PtrToIdx(EntryConstPtr _entry) const
Definition: KKQueue.h:761
void GoalKeeperSimple::EndBlock ( )

Ends the block and allows other threads to pass through StatBlock.

Decrements the variable 'blockerDepth' by one. Once 'blockerDepth' is equal zero the Block on this instance is removed. The idea is that for each time in a row a Thread calls StartBlock it has to call EndBlock the same number of times.

Definition at line 139 of file GoalKeeperSimple.cpp.

References KKB::KKException::KKException(), KKB::KKStr::operator+(), KKB::operator+(), and KKB::osGetThreadId().

Referenced by KKB::MsgQueue::AddMsg(), KKB::MsgQueue::AddMsgs(), KKB::MsgQueue::GetAllMsgs(), KKB::MsgQueue::GetCopyOfLastMsg(), KKB::MsgQueue::GetNextMsg(), and KKB::MsgQueue::MemoryConsumedEstimated().

140 {
141  kkint32 curThreadId = KKB::osGetThreadId ();
142  if (!blocked)
143  throw KKB::KKException ("GoalKeeperSimple::EndBlock Name[" + name + "] Is not currently blocked.");
144 
145  if (curThreadId != blockerThreadId)
146  throw KKB::KKException ("GoalKeeperSimple::EndBlock Name[" + name + "] ThreadId[" + blockerThreadId + "] Currently holds Block; our ThreadId[" + curThreadId + "]");
147 
148  --levels;
149  if (levels < 1)
150  {
151  blocked = false;
152  blockerThreadId = -1;
153  CriticalSectionEnd ();
154  }
155 } /* EndBlock */
__int32 kkint32
Definition: KKBaseTypes.h:88
kkint32 osGetThreadId()
void GoalKeeperSimple::FinalCleanUp ( )
static

Will be registered with 'atexit' so that it will be called when program is unloaded from memory.

Definition at line 392 of file GoalKeeperSimple.cpp.

393 {
394  if (existingGoalKeepers)
395  {
396  delete existingGoalKeepers;
397  existingGoalKeepers = NULL;
398  }
399 }
kkint32 GoalKeeperSimple::MemoryConsumedEstimated ( ) const

Definition at line 69 of file GoalKeeperSimple.cpp.

References KKB::KKStr::MemoryConsumedEstimated().

Referenced by KKB::MsgQueue::MsgQueue().

70 {
71  return (sizeof (GoalKeeperSimple) + name.MemoryConsumedEstimated ());
72 }
kkint32 MemoryConsumedEstimated() const
Definition: KKStr.cpp:766
A simple/ light-weight implementation of critical section blocking.
const KKStr& KKB::GoalKeeperSimple::Name ( ) const
inline

Definition at line 122 of file GoalKeeperSimple.h.

122 {return name;}
void GoalKeeperSimple::StartBlock ( )

Initiates a Block as long as another thread has not already locked this object.

If it is already blocked processor will sleep and then try again. As long as the variable 'blockerDepth'is greater than zero this instance will be considered blocked. Once a thread has the instance blocked it will increment 'blockerDepth' and return to caller.

Definition at line 117 of file GoalKeeperSimple.cpp.

References KKB::osGetThreadId().

Referenced by KKB::MsgQueue::AddMsg(), KKB::MsgQueue::AddMsgs(), CreateAndStartBlock(), KKB::MsgQueue::GetAllMsgs(), KKB::MsgQueue::GetCopyOfLastMsg(), KKB::MsgQueue::GetNextMsg(), and KKB::MsgQueue::MemoryConsumedEstimated().

118 {
119  kkint32 curThreadId = KKB::osGetThreadId ();
120 
121  if (blocked && (curThreadId == blockerThreadId))
122  {
123  ++levels;
124  }
125  else
126  {
127  CriticalSectionStart ();
128  levels = 1;
129  blockerThreadId = curThreadId;
130  blocked = true;
131  }
132 
133  return;
134 } /* StartBlock */
__int32 kkint32
Definition: KKBaseTypes.h:88
kkint32 osGetThreadId()

Friends And Related Function Documentation

friend class KKQueue< GoalKeeperSimple >
friend

Definition at line 41 of file GoalKeeperSimple.h.


The documentation for this class was generated from the following files: