KSquare Utilities
GoalKeeperSimple.h
Go to the documentation of this file.
1 /* GoalKeeperSimple.h -- Implements blocking routines to support thread synchronization.
2  * Copyright (C) 1994-2011 Kurt Kramer
3  * For conditions of distribution and use, see copyright notice in KKB.h
4  */
5 #if !defined(_KKU_GOALKEEPERSIMPLE_)
6 #define _KKU_GOALKEEPERSIMPLE_
7 
8 #define GOALKEEPER_DEBUG
9 
10 
11 #if defined(WIN32)
12 #include <windows.h>
13 #else
14 #include <fcntl.h>
15 #include <semaphore.h>
16 #endif
17 
18 #include "DateTime.h"
19 #include "KKStr.h"
20 
21 namespace KKB
22 {
25 
26  /**
27  * @brief A simple/ light-weight implementation of critical section blocking.
28  */
30  {
31  public:
33 
34  private:
35  /** @brief Constructs a GoalKeeperSimple object; best to do this via the GoalKeeperSimple::Create method. */
36  GoalKeeperSimple (const KKStr& _name);
37 
38  ~GoalKeeperSimple ();
39 
40  public:
41  friend class KKQueue<GoalKeeperSimple>;
42 
43 
44  /**
45  *@brief Create a GoalKeeperSimple object and avoid a race condition doing it.
46  *@details In case two different threads try to create the same GoalKeeperSimple at the same time you only
47  * want one of them to succeed and the other to use same GaolKeeper object.
48  *@param[in] _name Name of Goal Keeper object that you want to create.
49  *@param[in,out] _newGoalKeeper You pass this in. Create will block out the critical region that
50  * creates the GoalKeeperSimple object. If it was already created, that
51  * is != NULL will just return not changing its value. If it is
52  * still NULL in the critical section it will create a new instance
53  * and set this parameter to its address.
54  */
55  static void Create (const KKStr& _name,
56  volatile GoalKeeperSimplePtr& _newGoalKeeper
57  );
58 
59 
60  /**
61  *@brief Create a GoalKeeperSimple object and avoid a race condition doing it.
62  *@details Similar to 'Create' except it will also call the StartBlock method. There is also
63  * an additional parameter that will let you know if your call was responsible for
64  * creating it.
65  *
66  * In case two different threads try to create the same GoalKeeperSimple at the same time
67  * you only want one of them to succeed and the other to use same GaolKeeper object.
68  *@param[in] _name Name of Goal Keeper object that you want to create.
69  *
70  *@param[in,out] _newGoalKeeper You pass this in. Create will block out the critical region that
71  * creates the GoalKeeperSimple object. If it was already created, that
72  * is != NULL will just return not changing its value. If it is
73  * still NULL in the critical section it will create a new instance
74  * and set this parameter to its address.
75  *
76  *@param[out] _didNotExistYet Indicates if this call had to create the GoalKeeperSimple instance; if it
77  * already existed will return as false.
78  */
79  static void CreateAndStartBlock (const KKStr& _name,
80  volatile GoalKeeperSimplePtr& _newGoalKeeper,
81  bool& _didNotExistYet
82  );
83 
84  /**
85  *@brief Destroys an existing instance of GoalKeeperSimple.
86  *@details Use this method rather than calling the destructor directly. This way the
87  * 'existingGoalKeepers' data member can be kept up to date. If for some reason two
88  * different threads managed to call this method for the same GoalKeeperSimple instance only
89  * one of them will actually destroy the instance.
90  *@param[in,out] _goalKeeperInstance Instance of GoalKeeperSimple that is to be destroyed. Upon return
91  * it will be set to NULL.
92  */
93  static void Destroy (volatile GoalKeeperSimplePtr& _goalKeeperInstance);
94 
95 
96  /**
97  *@brief Will return true if any thread lock on this instance of "GoalKeeperSimple".
98  */
99  bool Blocked ();
100 
101 
102  /**
103  *@brief Returns true if a different thread has this instance of "GoalKeeperSimple" locked.
104  *@details GoalKeeperSimple keeps track of which thread has a lock on this instance of 'GoalKeeperSimple'.
105  * This way we know if the calling thread is not the one to have a lock on the thread.
106  */
107  bool BlockedByAnotherThread ();
108 
109 
110  kkint32 BlockerThreadId (); /**< @brief ThreadId of thread that currently holds the Block -1 indicates no Block */
111 
112  /**
113  *@brief Ends the block and allows other threads to pass through StatBlock.
114  *@details Decrements the variable 'blockerDepth' by one. Once 'blockerDepth' is equal zero
115  * the Block on this instance is removed. The idea is that for each time in a row a Thread
116  * calls StartBlock it has to call EndBlock the same number of times.
117  */
118  void EndBlock ();
119 
121 
122  const KKStr& Name () const {return name;}
123 
124 
125  /**
126  *@brief Initiates a Block as long as another thread has not already locked this object.
127  *@details If it is already blocked processor will sleep and then try again. As long as the variable
128  * 'blockerDepth'is greater than zero this instance will be considered blocked. Once a thread has the
129  * instance blocked it will increment 'blockerDepth' and return to caller.
130  */
131  void StartBlock ();
132 
133  /**
134  *@brief Will be registered with 'atexit' so that it will be called when program is unloaded from memory
135  */
136  static void FinalCleanUp ();
137 
138  private:
139  void CriticalSectionStart ();
140 
141  void CriticalSectionEnd ();
142 
143  static volatile GoalKeeperSimpleListPtr existingGoalKeepers;
144 
145 
146  volatile bool blocked; /**< @brief 'true' = Currently Blocked. */
147 
148  volatile kkint32 blockerThreadId; /**< @brief ThreadId of thread that currently holds the Block -1 indicates no Block */
149 
150  volatile kkuint32 levels; /**< Number of levels deep that a thread blocked; this is the number of times "EndBlock" must be called
151  * to release this block.
152  */
153 
154  KKStr name;
155 
156 
157 #if defined(WIN32)
158  CRITICAL_SECTION cs;
159 #else
161 #endif
162 
163  }; /* GoalKeeperSimple */
164 
165  typedef GoalKeeperSimple::GoalKeeperSimplePtr GoalKeeperSimplePtr;
166 
167 
168 
170  {
171  public:
173 
175  {}
176  };
177 
178 
179 }
180 
181 #endif
bool BlockedByAnotherThread()
Returns true if a different thread has this instance of "GoalKeeperSimple" locked.
GoalKeeperSimpleList * GoalKeeperSimpleListPtr
__int32 kkint32
Definition: KKBaseTypes.h:88
static void Destroy(volatile GoalKeeperSimplePtr &_goalKeeperInstance)
Destroys an existing instance of GoalKeeperSimple.
kkint32 BlockerThreadId()
ThreadId of thread that currently holds the Block -1 indicates no Block.
A simple/ light-weight implementation of critical section blocking.
void EndBlock()
Ends the block and allows other threads to pass through StatBlock.
unsigned __int32 kkuint32
Definition: KKBaseTypes.h:89
KKTHread * KKTHreadPtr
static KKStr Concat(const std::vector< std::string > &values)
Concatenates the list of &#39;std::string&#39; strings.
Definition: KKStr.cpp:1082
static void CreateAndStartBlock(const KKStr &_name, volatile GoalKeeperSimplePtr &_newGoalKeeper, bool &_didNotExistYet)
Create a GoalKeeperSimple object and avoid a race condition doing it.
static void Create(const KKStr &_name, volatile GoalKeeperSimplePtr &_newGoalKeeper)
Create a GoalKeeperSimple object and avoid a race condition doing it.
void StartBlock()
Initiates a Block as long as another thread has not already locked this object.
static void FinalCleanUp()
Will be registered with &#39;atexit&#39; so that it will be called when program is unloaded from memory...
const KKStr & Name() const
friend std::ostream & operator<<(std::ostream &os, const Matrix &matrix)
bool Blocked()
Will return true if any thread lock on this instance of "GoalKeeperSimple".
GoalKeeperSimple * GoalKeeperSimplePtr
kkint32 MemoryConsumedEstimated() const