OOFILE  1.9
oofmsg.cpp
Go to the documentation of this file.
1 // COPYRIGHT 1996 A.D. Software, All rights reserved
2 
3 // messaging layer of OOFILE database
4 
5 #include "oofpch_c.h" // for precompilation of core files
6 
7 #ifndef H_OOFMSG
8  #include "oofmsg.h"
9 #endif
10 #ifndef H_OOFARRAY
11  #include "oofarray.h"
12 #endif
13 
14 #ifndef H_OOFIOS
15  #include "oofios.h"
16 #endif
17 #ifdef OOF_DEBUG
18 // only required to get RAISE_EXCEPTION macro as dbConnect::raise
19 // when no exceptions available
20 // so if you don't define OOF_DEBUG you can use oofmsg.cpp by itself
21 // in non-database project, provided it has exceptions available.
22  #ifndef H_OOF2
23  #include "oof2.h"
24  #endif
25 #endif
26 
27 #ifdef OOF_MEM_DEBUG_LAST_INCLUDE
28  #include OOF_MEM_DEBUG_LAST_INCLUDE
29 #endif
30 
31 #ifndef OOF_NO_STDLIB
32  #ifndef std
33  using namespace std;
34  #endif
35 #endif
36 
37 
38 // -------------------------------------------------------
39 // o o f B r o a d c a s t e r
40 // -------------------------------------------------------
42  mReceivers(0),
43  mNestedBroadcastingDepth(0),
44  mLostReceiversWhileBroadcasting(false)
45 {}
46 
47 
49  mReceivers(0),
50  mNestedBroadcastingDepth(0),
51  mLostReceiversWhileBroadcasting(false)
52 {}
53 
54 
56 {
58 }
59 
60 
61 void
63 {
64  assert(sizeof(oofReceiver*)==sizeof(long)); // guard against our abuse of array causing pointer munge
65 
66  if (mReceivers) {
68  delete mReceivers;
69  mReceivers = 0;
70  }
71 }
72 
73 
81 void
82 oofBroadcaster::broadcast(OOFmsgT msg, unsigned long senderDefined, const oofReceiver* skipping)
83 {
84  if (!mReceivers)
85  return;
86 
87  mNestedBroadcastingDepth++; // in case of receivers removing themselves - see removeReceiver
88  const unsigned short numReceivers = mReceivers->count();
89  if (skipping) {
90  for (unsigned short i=0; i<numReceivers; i++) {
91  oofReceiver* rcvr = (oofReceiver*) (mReceivers->value(i)); // safe downcast
92  if (rcvr!=skipping) // implies check rcvr!=NULL
93  rcvr->receiveMsg(msg, senderDefined);
94  }
95  }
96  else { // copy of loop logic to avoid repeated if (skipping) inside loop
97  for (unsigned short i=0; i<numReceivers; i++) {
98  oofReceiver* rcvr = (oofReceiver*) (mReceivers->value(i)); // safe downcast
99  if (rcvr)
100  rcvr->receiveMsg(msg, senderDefined);
101  }
102  }
103 
104  mNestedBroadcastingDepth--; // but may be in nested broadcasts so
105  // don't compact receivers until it hits 0
109  }
110 }
111 
112 
113 oofReceiver*
114 oofBroadcaster::askAllStoppingAtFirst(bool stopOn, OOFmsgT msg, unsigned long senderDefined, const oofReceiver* skipping)
115 {
116  if (!mReceivers)
117  return 0;
118 
119  const unsigned short numReceivers = mReceivers->count();
120  if (skipping) {
121  for (unsigned short i = 0; i < numReceivers; i++) {
122  oofReceiver* rcvr = (oofReceiver*) (mReceivers->value(i)); // safe downcast
123  if (rcvr!=skipping) { // implies check rcvr!=NULL
124  const bool reaction = rcvr->receiveMsg(msg, senderDefined);
125  if (reaction == stopOn)
126  return rcvr;
127  }
128  }
129  }
130  else {// copy of loop logic to avoid repeated if (skipping) inside loop
131  for (unsigned short i = 0; i < numReceivers; i++) {
132  oofReceiver* rcvr = (oofReceiver*) (mReceivers->value(i)); // safe downcast
133  if (rcvr) {// nested broadcast may have removed
134  const bool reaction = rcvr->receiveMsg(msg, senderDefined);
135  if (reaction == stopOn)
136  return rcvr;
137  }
138  }
139  }
140  return 0;
141 }
142 
143 
144 bool
145 oofBroadcaster::askAllReturningAny(bool returnAny, OOFmsgT msg, unsigned long senderDefined, const oofReceiver* skipping)
146 {
147  if (!mReceivers)
148  return false;
149 
150  bool foundAny = false;
151  const unsigned short numReceivers = mReceivers->count();
152  if (skipping) {
153  for (unsigned short i=0; i<numReceivers; i++) {
154  oofReceiver* rcvr = (oofReceiver*) (mReceivers->value(i)); // safe downcast
155  if (rcvr!=skipping) {// implies check rcvr!=NULL
156  const bool ret = rcvr->receiveMsg(msg, senderDefined);
157  if (ret==returnAny)
158  foundAny = true;
159  }
160  }
161  }
162  else {// copy of loop logic to avoid repeated if (skipping) inside loop
163  for (unsigned short i=0; i<numReceivers; i++) {
164  oofReceiver* rcvr = (oofReceiver*) (mReceivers->value(i)); // safe downcast
165  if (rcvr) {// nested broadcast may have removed
166  const bool ret = rcvr->receiveMsg(msg, senderDefined);
167  if (ret==returnAny)
168  foundAny = true;
169  }
170  }
171  }
172  return foundAny;
173 }
174 
175 
180 void
182 {
183  if (!mReceivers) {
185  assert(mReceivers);
186  }
187  unsigned long foundIndex;
188  assert( !(mReceivers->find((unsigned long) addingReceiver, foundIndex)) );
189  mReceivers->append((unsigned long) addingReceiver);
190 }
191 
192 
193 void
195 {
196  assert(mReceivers); // very weird for someone to think they are subscribed in this case
199  unsigned long foundIndex;
200  if (mReceivers->find((unsigned long) rcvrPtr, foundIndex)) {
201  mReceivers->item(foundIndex) = 0;
202  }
203  else {
204 #ifdef OOF_DEBUG
205  dbConnect::raise("Attempt to remove non-existent receiver", false);
206 #endif
207  }
208  }
209  else
210  mReceivers->deleteFirstMatching((unsigned long) rcvrPtr);
211 }
212 
213 
214 // -------------------------------------------------------
215 // d b R e c e i v e r
216 // -------------------------------------------------------
218 {
219 }
220 
221 
222 void
224 {
225  assert(broad);
226  broad->addReceiver(this);
227 }
228 
229 
230 void
232 {
233  broad->removeReceiver(this);
234 }
235 
236 
237 
238 
239 // -------------------------------------------------------
240 // d b S i n g l e L i s t e n e r
241 // -------------------------------------------------------
243  mListensTo(listensTo),
244  mSuspendedListensTo(0),
245  mSuspendCount(0)
246 {
247  if (listensTo)
248  listensTo->addReceiver(this);
249 }
250 
251 
253  mListensTo(rhs.mListensTo),
254  mSuspendedListensTo(rhs.mSuspendedListensTo),
255  mSuspendCount(rhs.mSuspendCount)
256 {
257  if (mListensTo)
258  mListensTo->addReceiver(this);
259 }
260 
261 
274 bool
275 oofSingleListener::receiveMsg(OOFmsgT msg, unsigned long senderDefined)
276 {
277  if (msg==OOFmsg_BroadcasterClosing) {
278  assert(senderDefined==(long)mListensTo);
279  mListensTo = 0; // *** EITHER CLEAR mListensTo or call THIS BASE METHOD ***
280  delete this;
281  }
282  return true;
283 }
284 
285 
287 {
288  unsubscribe();
289 }
290 
291 
292 void
294 {
295  assert(broad);
296  if (mListensTo)
298  mListensTo = broad;
299  broad->addReceiver(this);
300 }
301 
302 
303 void
305 {
306  if (broad) {
307  assert(broad==mListensTo);
308  ;
309  }
310  if (mListensTo)
312  mListensTo = 0;
313 }
314 
315 
316 void
318 {
319  mSuspendCount++;
320  if (mSuspendCount==1) {
322  unsubscribe();
323  }
324  else {
325  assert(mSuspendedListensTo);
326 #ifdef OOF_DEBUG
327 // sanity check on nested suspends
328  if (mSuspendCount > 1000){
329  dbConnect::raise("You've nested more than 1000 suspend listenings");
330  }
331 #endif
332  ;
333  }
334 }
335 
336 
337 void
339 {
340  if (mSuspendedListensTo==0)
341  return; // let them get away with being sloppy about extra resumes
342  assert(mSuspendCount>0);
343  mSuspendCount--;
344  if (mSuspendCount==0) {
347  }
348 }
349 
messaging layer of OOFILE application development framework.
void suspendListening()
Definition: oofmsg.cpp:317
static void raise(std::ostream &, bool terminateAfterMsg=true)
precompilation header.
Tries to hide the different platforms and version issues with standard IO.
bool find(unsigned long value, unsigned long &foundAt) const
Definition: oofarray.cpp:187
virtual ~oofBroadcaster()
Definition: oofmsg.cpp:55
unsigned long count() const
Definition: oofarray.h:126
Special limited oofReceiver which will only ever listen to one oofBroadcaster at a time...
Definition: oofmsg.h:133
virtual bool receiveMsg(OOFmsgT msg, unsigned long senderDefined)
The default receiveMsg behaviour is to delete yourself when the broadcaster closes.
Definition: oofmsg.cpp:275
unsigned long mNestedBroadcastingDepth
aid to debugging and removeReceiver
Definition: oofmsg.h:97
oofBroadcaster * mSuspendedListensTo
Definition: oofmsg.h:150
oofSingleListener(oofBroadcaster *listensTo=0)
Definition: oofmsg.cpp:242
const OOFmsgT OOFmsg_BroadcasterClosing
Definition: oofmsg.h:40
void removeReceiver(const oofReceiver *)
Definition: oofmsg.cpp:194
void addReceiver(oofReceiver *)
Append receiver to end of list.
Definition: oofmsg.cpp:181
unsigned long & item(unsigned long index)
Definition: oofarray.h:168
virtual void unsubscribe(oofBroadcaster *from=0)
Definition: oofmsg.cpp:304
unsigned short mSuspendCount
Definition: oofmsg.h:151
bool askAllReturningAny(bool returnAny, OOFmsgT msg, unsigned long senderDefined=0, const oofReceiver *skipping=0)
Definition: oofmsg.cpp:145
void resumeListening()
Definition: oofmsg.cpp:338
virtual ~oofReceiver()
Definition: oofmsg.cpp:217
virtual bool receiveMsg(OOFmsgT msg, unsigned long senderDefined)=0
virtual ~oofSingleListener()
Definition: oofmsg.cpp:286
Array of longs which expands automatically as you write to cells.
Definition: oofarray.h:21
oofBroadcaster * mListensTo
Definition: oofmsg.h:149
Generic receiver for messaging.
Definition: oofmsg.h:112
void append(unsigned long)
Definition: oofarray.cpp:131
oofReceiver * askAllStoppingAtFirst(bool stopOn, OOFmsgT msg, unsigned long senderDefined=0, const oofReceiver *skipping=0)
Definition: oofmsg.cpp:114
Generic broadcaster for messaging.
Definition: oofmsg.h:76
virtual void subscribeTo(oofBroadcaster *)
Definition: oofmsg.cpp:223
unsigned long OOFmsgT
Definition: oofmsg.h:31
OOF_ExpandableLongArray * mReceivers
owned
Definition: oofmsg.h:96
void deleteFirstMatching(unsigned long value)
Definition: oofarray.cpp:152
virtual void unsubscribe(oofBroadcaster *)
Definition: oofmsg.cpp:231
void deleteAllMatching(unsigned long value)
Definition: oofarray.cpp:161
bool mLostReceiversWhileBroadcasting
simple flag that removeReceiver was called during nested broadcast
Definition: oofmsg.h:98
void broadcast(OOFmsgT msg, unsigned long senderDefined=0, const oofReceiver *skipping=0)
Broadcast a message to all anonymous subscribers.
Definition: oofmsg.cpp:82
unsigned long value(unsigned long index) const
Definition: oofarray.cpp:243
void BroadcastShutdown()
Definition: oofmsg.cpp:62
virtual void subscribeTo(oofBroadcaster *)
Definition: oofmsg.cpp:293