This is Unofficial EPICS BASE Doxygen Site
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
CASG.cpp
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
3 * National Laboratory.
4 * Copyright (c) 2002 The Regents of the University of California, as
5 * Operator of Los Alamos National Laboratory.
6 * EPICS BASE is distributed subject to a Software License Agreement found
7 * in file LICENSE that is included with this distribution.
8 \*************************************************************************/
9 
10 /*
11  * Author: Jeffrey O. Hill
12  */
13 
14 #include <string>
15 #include <stdexcept>
16 
17 #define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
18 
19 #include "errlog.h"
20 
21 #include "iocinf.h"
22 #include "syncGroup.h"
23 #include "oldAccess.h"
24 #include "cac.h"
25 #include "sgAutoPtr.h"
26 
28  client ( cacIn ), magic ( CASG_MAGIC )
29 {
30  client.installCASG ( guard, *this );
31 }
32 
34 {
35 }
36 
38  CallbackGuard & cbGuard,
40 {
41  guard.assertIdenticalMutex ( this->client.mutexRef() );
42 
43  if ( this->verify ( guard ) ) {
44  this->reset ( cbGuard, guard );
45  this->client.uninstallCASG ( guard, *this );
46  this->magic = 0;
47  }
48  else {
49  this->printFormated ( "cac: attempt to destroy invalid sync group ignored\n" );
50  }
51  this->~CASG ();
52 }
53 
55 {
56  return ( this->magic == CASG_MAGIC );
57 }
58 
59 /*
60  * CASG::block ()
61  */
63  epicsGuard < epicsMutex > * pcbGuard,
65  double timeout )
66 {
67  epicsTime cur_time;
68  epicsTime beg_time;
69  double delay;
70  double remaining;
71  int status;
72 
73  guard.assertIdenticalMutex ( this->client.mutexRef() );
74 
75  // prevent recursion nightmares by disabling blocking
76  // for IO from within a CA callback.
78  return ECA_EVDISALLOW;
79  }
80 
81  if ( timeout < 0.0 ) {
82  return ECA_TIMEOUT;
83  }
84 
85  cur_time = epicsTime::getCurrent ();
86 
87  this->client.flush ( guard );
88 
89  beg_time = cur_time;
90  delay = 0.0;
91 
92  while ( 1 ) {
93  if ( this->ioPendingList.count() == 0u ) {
94  status = ECA_NORMAL;
95  break;
96  }
97 
98  remaining = timeout - delay;
99  if ( remaining <= CAC_SIGNIFICANT_DELAY ) {
100  /*
101  * Make sure that we take care of
102  * recv backlog at least once
103  */
104  status = ECA_TIMEOUT;
105  break;
106  }
107 
108  if ( pcbGuard ) {
109  epicsGuardRelease < epicsMutex > unguard ( guard );
110  {
111  epicsGuardRelease < epicsMutex > uncbGuard ( *pcbGuard );
112  this->sem.wait ( remaining );
113  }
114  }
115  else {
116  epicsGuardRelease < epicsMutex > unguard ( guard );
117  this->sem.wait ( remaining );
118  }
119 
120  /*
121  * force a time update
122  */
123  cur_time = epicsTime::getCurrent ();
124 
125  delay = cur_time - beg_time;
126  }
127 
128  return status;
129 }
130 
132  CallbackGuard & cbGuard,
133  epicsGuard < epicsMutex > & guard )
134 {
135  guard.assertIdenticalMutex ( this->client.mutexRef() );
136  this->destroyCompletedIO ( cbGuard, guard );
137  this->destroyPendingIO ( cbGuard, guard );
138 }
139 
140 // lock must be applied
142  CallbackGuard & cbGuard,
143  epicsGuard < epicsMutex > & guard )
144 {
145  guard.assertIdenticalMutex ( this->client.mutexRef() );
146  syncGroupNotify * pNotify;
147  while ( ( pNotify = this->ioCompletedList.get () ) ) {
148  pNotify->destroy ( cbGuard, guard );
149  }
150 }
151 
153  CallbackGuard & cbGuard,
154  epicsGuard < epicsMutex > & guard )
155 {
156  guard.assertIdenticalMutex ( this->client.mutexRef() );
157  while ( syncGroupNotify * pNotify = this->ioPendingList.first () ) {
158  pNotify->cancel ( cbGuard, guard );
159  // cancel must release the guard while
160  // canceling put callbacks so we
161  // must double check list membership
162  if ( pNotify->ioPending ( guard ) ) {
163  this->ioPendingList.remove ( *pNotify );
164  }
165  else {
166  this->ioCompletedList.remove ( *pNotify );
167  }
168  pNotify->destroy ( cbGuard, guard );
169  }
170 }
171 
172 void CASG::show ( unsigned level ) const
173 {
174  epicsGuard < epicsMutex > guard ( this->client.mutexRef () );
175  this->show ( guard, level );
176 }
177 
179  epicsGuard < epicsMutex > & guard, unsigned level ) const
180 {
181  guard.assertIdenticalMutex ( this->client.mutexRef() );
182  ::printf ( "Sync Group: id=%u, magic=%u, opPend=%u\n",
183  this->getId (), this->magic, this->ioPendingList.count () );
184  if ( level ) {
185  ::printf ( "\tPending" );
186  tsDLIterConst < syncGroupNotify > notifyPending =
187  this->ioPendingList.firstIter ();
188  while ( notifyPending.valid () ) {
189  notifyPending->show ( guard, level - 1u );
190  notifyPending++;
191  }
192  ::printf ( "\tCompleted" );
193  tsDLIterConst < syncGroupNotify > notifyCompleted =
194  this->ioCompletedList.firstIter ();
195  while ( notifyCompleted.valid () ) {
196  notifyCompleted->show ( guard, level - 1u );
197  notifyCompleted++;
198  }
199  }
200 }
201 
203  CallbackGuard & cbGuard,
204  epicsGuard < epicsMutex > & guard )
205 {
206  guard.assertIdenticalMutex ( this->client.mutexRef() );
207  this->destroyCompletedIO ( cbGuard, guard );
208  return this->ioPendingList.count () == 0u;
209 }
210 
212  unsigned type, arrayElementCount count, const void * pValue )
213 {
214  guard.assertIdenticalMutex ( this->client.mutexRef() );
215  sgAutoPtr < syncGroupWriteNotify > pNotify ( guard, *this );
217  this->freeListWriteOP, *this, & CASG :: recycleWriteNotifyIO, pChan );
218  pNotify->begin ( guard, type, count, pValue );
219  pNotify.release ();
220 }
221 
223  unsigned type, arrayElementCount count, void *pValue )
224 {
225  guard.assertIdenticalMutex ( this->client.mutexRef() );
226  sgAutoPtr < syncGroupReadNotify > pNotify ( guard, *this );
227  pNotify = syncGroupReadNotify::factory (
228  this->freeListReadOP, *this, & CASG :: recycleReadNotifyIO, pChan, pValue );
229  pNotify->begin ( guard, type, count );
230  pNotify.release ();
231 }
232 
234  epicsGuard < epicsMutex > & guard, syncGroupNotify & notify )
235 {
236  guard.assertIdenticalMutex ( this->client.mutexRef() );
237  this->ioPendingList.remove ( notify );
238  this->ioCompletedList.add ( notify );
239  if ( this->ioPendingList.count () == 0u ) {
240  this->sem.signal ();
241  }
242 }
243 
245  syncGroupReadNotify & io )
246 {
247  guard.assertIdenticalMutex ( this->client.mutexRef() );
248  this->freeListReadOP.release ( & io );
249 }
250 
252  syncGroupWriteNotify & io )
253 {
254  guard.assertIdenticalMutex ( this->client.mutexRef() );
255  this->freeListWriteOP.release ( & io );
256 }
257 
258 int CASG :: printFormated ( const char *pformat, ... )
259 {
260  va_list theArgs;
261  int status;
262 
263  va_start ( theArgs, pformat );
264 
265  status = this->client.varArgsPrintFormated ( pformat, theArgs );
266 
267  va_end ( theArgs );
268 
269  return status;
270 }
271 
272 void CASG::exception (
274  int status, const char * pContext,
275  const char * pFileName, unsigned lineNo )
276 {
277  guard.assertIdenticalMutex ( this->client.mutexRef() );
278  if ( status != ECA_CHANDESTROY ) {
279  this->client.exception (
280  guard, status, pContext, pFileName, lineNo );
281  }
282 }
283 
284 void CASG::exception (
286  int status, const char * pContext,
287  const char * pFileName, unsigned lineNo, oldChannelNotify & chan,
288  unsigned type, arrayElementCount count, unsigned op )
289 {
290  guard.assertIdenticalMutex ( this->client.mutexRef() );
291  if ( status != ECA_CHANDESTROY ) {
292  this->client.exception (
293  guard, status, pContext, pFileName,
294  lineNo, chan, type, count, op );
295  }
296 }
297 
298 void CASG::operator delete ( void * )
299 {
300  // Visual C++ .net appears to require operator delete if
301  // placement operator delete is defined? I smell a ms rat
302  // because if I declare placement new and delete, but
303  // comment out the placement delete definition there are
304  // no undefined symbols.
305  errlogPrintf ( "%s:%d this compiler is confused about placement delete - memory was probably leaked",
306  __FILE__, __LINE__ );
307 }
#define ECA_EVDISALLOW
Definition: caerr.h:103
double timeout
Definition: pvutils.cpp:25
void exception epicsGuard< epicsMutex > int const char const char unsigned oldChannelNotify & chan
Definition: syncGroup.h:177
void reset(CallbackGuard &, epicsGuard< epicsMutex > &)
Definition: CASG.cpp:131
tsFreeList< class syncGroupReadNotify, 128, epicsMutexNOOP > freeListReadOP
Definition: syncGroup.h:192
epicsEvent sem
Definition: syncGroup.h:189
LIBCOM_API void *epicsStdCall epicsThreadPrivateGet(epicsThreadPrivateId)
Definition: osdThread.c:973
static syncGroupReadNotify * factory(tsFreeList< class syncGroupReadNotify, 128, epicsMutexNOOP > &, CASG &, PRecycleFunc, chid, void *pValueIn)
void destructor(CallbackGuard &, epicsGuard< epicsMutex > &guard)
Definition: CASG.cpp:37
#define printf
Definition: epicsStdio.h:41
void assertIdenticalMutex(const T &) const
Definition: epicsGuard.h:80
void exception epicsGuard< epicsMutex > int const char const char unsigned oldChannelNotify unsigned type
Definition: syncGroup.h:177
void recycleReadNotifyIO(epicsGuard< epicsMutex > &, syncGroupReadNotify &)
Definition: CASG.cpp:244
epicsThreadPrivateId caClientCallbackThreadId
virtual void show(epicsGuard< epicsMutex > &, unsigned level) const =0
void show(epicsGuard< epicsMutex > &, unsigned level) const
Definition: CASG.cpp:178
bool valid() const
Definition: tsDLList.h:506
bool verify(epicsGuard< epicsMutex > &) const
Definition: CASG.cpp:54
void exception epicsGuard< epicsMutex > int const char const char unsigned oldChannelNotify unsigned arrayElementCount unsigned op
Definition: syncGroup.h:177
~CASG()
Definition: CASG.cpp:33
unsigned magic
Definition: syncGroup.h:191
#define ECA_NORMAL
Definition: caerr.h:77
Definition: server.h:76
int block(epicsGuard< epicsMutex > *pcbGuard, epicsGuard< epicsMutex > &guard, double timeout)
Definition: CASG.cpp:62
static syncGroupWriteNotify * factory(tsFreeList< class syncGroupWriteNotify, 128, epicsMutexNOOP > &, CASG &, PRecycleFunc, chid)
void exception epicsGuard< epicsMutex > int const char const char * pFileName
Definition: syncGroup.h:174
void exception epicsGuard< epicsMutex > int const char const char unsigned oldChannelNotify unsigned arrayElementCount count
Definition: syncGroup.h:177
void recycleWriteNotifyIO(epicsGuard< epicsMutex > &, syncGroupWriteNotify &)
Definition: CASG.cpp:251
int errlogPrintf(const char *pFormat,...)
Definition: errlog.c:105
tsFreeList< class syncGroupWriteNotify, 128, epicsMutexNOOP > freeListWriteOP
Definition: syncGroup.h:193
bool ioComplete(CallbackGuard &, epicsGuard< epicsMutex > &guard)
Definition: CASG.cpp:202
virtual void destroy(CallbackGuard &cbGuard, epicsGuard< epicsMutex > &guard)=0
unsigned long arrayElementCount
Definition: cacIO.h:57
void put(epicsGuard< epicsMutex > &, chid pChan, unsigned type, arrayElementCount count, const void *pValue)
Definition: CASG.cpp:211
void destroyPendingIO(CallbackGuard &cbGuard, epicsGuard< epicsMutex > &guard)
Definition: CASG.cpp:152
void exception epicsGuard< epicsMutex > int const char * pContext
Definition: syncGroup.h:174
void get(epicsGuard< epicsMutex > &, chid pChan, unsigned type, arrayElementCount count, void *pValue)
Definition: CASG.cpp:222
epicsPlacementDeleteOperator((void *, tsFreeList< struct CASG, 128, epicsMutexNOOP > &)) private tsDLList< syncGroupNotify ioCompletedList)
Definition: syncGroup.h:183
#define ECA_CHANDESTROY
Definition: caerr.h:132
void release(void *p)
Definition: tsFreeList.h:176
#define ECA_TIMEOUT
Definition: caerr.h:87
void exception epicsGuard< epicsMutex > int status
Definition: syncGroup.h:174
int printFormated(const char *pFormat,...)
Definition: CASG.cpp:258
void completionNotify(epicsGuard< epicsMutex > &, syncGroupNotify &)
Definition: CASG.cpp:233
#define CAC_SIGNIFICANT_DELAY
Definition: iocinf.h:36
void begin(epicsGuard< epicsMutex > &, unsigned type, arrayElementCount count)
T * release()
Definition: sgAutoPtr.h:89
CASG(epicsGuard< epicsMutex > &, ca_client_context &cacIn)
Definition: CASG.cpp:27
void destroyCompletedIO(CallbackGuard &cbGuard, epicsGuard< epicsMutex > &guard)
Definition: CASG.cpp:141
void begin(epicsGuard< epicsMutex > &, unsigned type, arrayElementCount count, const void *pValueIn)
void exception epicsGuard< epicsMutex > int const char const char unsigned lineNo
Definition: syncGroup.h:174