00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
#ifndef ROOMSYNCHRONIZER_H
00017
#define ROOMSYNCHRONIZER_H
00018
00019
#include <exception>
00020
#include <vector>
00021
00022
#include <PtMutex.h>
00023
#include <BinarySem.h>
00024
#include <LockHolder.h>
00025
00026
using namespace std;
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
template
00038 class RoomSynchronizer<typename TRoomEnum>
00039 {
00040
public:
00041 RoomSynchronizer()
00042
throw (exception);
00043
00044
00045
00046
virtual ~RoomSynchronizer();
00047
00048
00049
00050
00051
00052
void enterRoom(TRoomEnum desiredRoom)
00053
throw (exception);
00054
00055
void exitRoom()
00056
throw (exception);
00057
00058
private:
00059
00060
PtMutex _mtx;
00061
00062
00063
00064 size_t _threadsInCurrentRoom;
00065 TRoomEnum _currentRoom;
00066
00067
00068
struct WaiterInfo
00069 {
00070 WaiterInfo(TRoomEnum desiredRoom,
BinarySem * pEnterRoomSignal) :
00071 _desiredRoom(desiredRoom),
00072 _pEnterRoomSignal(pEnterRoomSignal)
00073 {
00074 }
00075
00076 TRoomEnum _desiredRoom;
00077
BinarySem * _pEnterRoomSignal;
00078 };
00079
00080
00081
00082
00083
00084 vector<WaiterInfo> _waiters;
00085 };
00086
00087
00088
00089
template
00090 RoomSynchronizer<typename TRoomEnum>::RoomSynchronizer()
00091 throw (exception)
00092 {
00093 _threadsInCurrentRoom = 0;
00094 }
00095
00096
00097
00098
template
00099 RoomSynchronizer<typename TRoomEnum>::~RoomSynchronizer()
00100 {
00101 assert(_waiters.size() == 0);
00102 }
00103
00104
00105
00106
template
00107 void RoomSynchronizer<typename TRoomEnum>::enterRoom(TRoomEnum desiredRoom)
00108
throw (exception)
00109 {
00110
BinarySem * pWaitSem = NULL;
00111
00112
LockHolder lh(_mtx);
00113
00114
if (_threadsInCurrentRoom == 0)
00115 {
00116 _threadsInCurrentRoom = 1;
00117 _currentRoom = desiredRoom;
00118 }
00119
else if (_waiters.size() == 0)
00120 {
00121
00122
if (_currentRoom == desiredRoom)
00123 {
00124 ++ _threadsInCurrentRoom;
00125 }
00126
else
00127 {
00128 pWaitSem =
new BinarySem;
00129 _waiters.push_back(WaiterInfo(desiredRoom, pWaitSem));
00130 }
00131 }
00132
00133
00134
if (pWaitSem != NULL)
00135 {
00136 lh.
release();
00137 pWaitSem->
awaitPost();
00138
delete pWaitSem;
00139 lh.
reacquire();
00140
00141
00142 TODO!!! Need to remove myself from _waiters, because I'm no longe a waiter!
00143 This problably means we need to use a list, not a vector,
for _waiters. -cjc
00144
00145
00146 assert((_currentRoom == desiredRoom) || (_threadsInCurrentRoom == 0));
00147
00148 ++ _threadsInCurrentRoom;
00149
00150
00151
00152
00153 _currentRoom = desiredRoom;
00154 }
00155 }
00156
00157
00158
00159
00160
template
00161 void RoomSynchronizer<typename TRoomEnum>::exitRoom()
00162 throw (exception)
00163 {
00164
LockHolder lh(_mtx);
00165
00166 -- _threadsInCurrentRoom;
00167
00168
00169
if ((_threadsInCurrentRoom == 0) && (! _waiters.empty()))
00170 {
00171 _currentRoom = _waiters[0]._desiredRoom;
00172
00173 size_t numWaiters = _waiters.size();
00174
for (size_t i = 0;
00175 (i < numWaiters) && (_waiters[i]._desiredRoom == _currentRoom);
00176 ++ i)
00177 {
00178 ++ _threadsInCurrentRoom;
00179 _waiters[i]._pEnterRoomSignal->post();
00180 }
00181 }
00182 }
00183
00184
00185
00186
#endif