EPICS Base  7.0.7.0
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
cacIO.h
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 * SPDX-License-Identifier: EPICS
7 * EPICS BASE is distributed subject to a Software License Agreement found
8 * in file LICENSE that is included with this distribution.
9 \*************************************************************************/
10 /*
11  *
12  *
13  * L O S A L A M O S
14  * Los Alamos National Laboratory
15  * Los Alamos, New Mexico 87545
16  *
17  * Copyright, 1986, The Regents of the University of California.
18  *
19  *
20  * Author Jeffrey O. Hill
22  * 505 665 1831
23  */
24 
25 #ifndef INC_cacIO_H
26 #define INC_cacIO_H
27 
28 //
29 // Open Issues
30 // -----------
31 //
32 // 1) A status code from the old client side interface is passed
33 // to the exception notify callback. Should we just pass a string?
34 // If so, then how do they detect the type of error and recover.
35 // Perhaps we should call a different vf for each type of exception.
36 //
37 // 2) Some exception types are present here but there is no common
38 // exception base class in use.
39 //
40 // 3) Should I be passing the channel reference in cacChannelNotify?
41 //
42 // 4) Should the code for caAccessRights not be inline so that this
43 // interface is version independent.
44 //
45 //
46 
47 #include <new>
48 #include <stdarg.h>
49 
50 #include "tsDLList.h"
51 #include "epicsMutex.h"
52 #include "epicsGuard.h"
53 #include "epicsThread.h"
54 
55 #include "libCaAPI.h"
56 
57 
58 class cacChannel;
59 
60 typedef unsigned long arrayElementCount;
61 
62 // 1) this should not be passing caerr.h status to the exception callback
63 // 2) needless-to-say the data should be passed here using the new data access API
64 class LIBCA_API cacWriteNotify {
65 public:
66  virtual ~cacWriteNotify () = 0;
67  virtual void completion ( epicsGuard < epicsMutex > & ) = 0;
68 // we should probably have a different vf for each type of exception ????
69  virtual void exception (
71  int status, const char * pContext,
72  unsigned type, arrayElementCount count ) = 0;
73 };
74 
75 // 1) this should not be passing caerr.h status to the exception callback
76 // 2) needless-to-say the data should be passed here using the new data access API
77 class LIBCA_API cacReadNotify {
78 public:
79  virtual ~cacReadNotify () = 0;
80  virtual void completion (
81  epicsGuard < epicsMutex > &, unsigned type,
82  arrayElementCount count, const void * pData ) = 0;
83 // we should probably have a different vf for each type of exception ????
84  virtual void exception (
85  epicsGuard < epicsMutex > &, int status,
86  const char * pContext, unsigned type,
87  arrayElementCount count ) = 0;
88 };
89 
90 // 1) this should not be passing caerr.h status to the exception callback
91 // 2) needless-to-say the data should be passed here using the new data access API
92 class LIBCA_API cacStateNotify {
93 public:
94  virtual ~cacStateNotify () = 0;
95  virtual void current (
96  epicsGuard < epicsMutex > &, unsigned type,
97  arrayElementCount count, const void * pData ) = 0;
98 // we should probably have a different vf for each type of exception ????
99  virtual void exception (
100  epicsGuard < epicsMutex > &, int status,
101  const char *pContext, unsigned type,
102  arrayElementCount count ) = 0;
103 };
104 
106 public:
108  bool readPermit = false,
109  bool writePermit = false,
110  bool operatorConfirmationRequest = false);
111  void setReadPermit ();
112  void setWritePermit ();
113  void setOperatorConfirmationRequest ();
114  void clrReadPermit ();
115  void clrWritePermit ();
116  void clrOperatorConfirmationRequest ();
117  bool readPermit () const;
118  bool writePermit () const;
119  bool operatorConfirmationRequest () const;
120 private:
121  bool f_readPermit:1;
122  bool f_writePermit:1;
123  bool f_operatorConfirmationRequest:1;
124 };
125 
126 class LIBCA_API cacChannelNotify {
127 public:
128  virtual ~cacChannelNotify () = 0;
129  virtual void connectNotify ( epicsGuard < epicsMutex > & ) = 0;
130  virtual void disconnectNotify ( epicsGuard < epicsMutex > & ) = 0;
131  virtual void serviceShutdownNotify (
132  epicsGuard < epicsMutex > & mutualExclusionGuard ) = 0;
133  virtual void accessRightsNotify (
134  epicsGuard < epicsMutex > &, const caAccessRights & ) = 0;
135  virtual void exception (
136  epicsGuard < epicsMutex > &, int status, const char *pContext ) = 0;
137 // we should probably have a different vf for each type of exception ????
138  virtual void readException (
139  epicsGuard < epicsMutex > &, int status, const char *pContext,
140  unsigned type, arrayElementCount count, void *pValue ) = 0;
141 // we should probably have a different vf for each type of exception ????
142  virtual void writeException (
143  epicsGuard < epicsMutex > &, int status, const char * pContext,
144  unsigned type, arrayElementCount count ) = 0;
145 };
146 
148  public epicsGuard < epicsMutex > {
149 public:
150  CallbackGuard ( epicsMutex & mutex ) :
151  epicsGuard < epicsMutex > ( mutex ) {}
152 private:
153  CallbackGuard ( const CallbackGuard & );
154  CallbackGuard & operator = ( const CallbackGuard & );
155 };
156 
157 //
158 // Notes
159 // 1) This interface assumes that when a channel is deleted then all
160 // attached IO is deleted. This is left over from the old interface,
161 // but perhaps is a bad practice that should be eliminated? If so,
162 // then the IO should not store or use a pointer to the channel.
163 //
164 class LIBCA_API cacChannel {
165 public:
166  typedef unsigned priLev;
167  static const priLev priorityMax;
168  static const priLev priorityMin;
169  static const priLev priorityDefault;
170  static const priLev priorityLinksDB;
171  static const priLev priorityArchive;
172  static const priLev priorityOPI;
173 
174  typedef unsigned ioid;
175  enum ioStatus { iosSynch, iosAsynch };
176 
178  virtual void destroy (
179  CallbackGuard & callbackGuard,
180  epicsGuard < epicsMutex > & mutualExclusionGuard ) = 0;
181  cacChannelNotify & notify () const; // required ?????
182  virtual unsigned getName (
184  char * pBuf, unsigned bufLen ) const throw () = 0;
185  // !! deprecated, avoid use !!
186  virtual const char * pName (
187  epicsGuard < epicsMutex > & guard ) const throw () = 0;
188  virtual void show (
190  unsigned level ) const = 0;
191  virtual void initiateConnect (
193  virtual unsigned requestMessageBytesPending (
194  epicsGuard < epicsMutex > & mutualExclusionGuard ) = 0;
195  virtual void flush (
196  epicsGuard < epicsMutex > & mutualExclusionGuard ) = 0;
197  virtual ioStatus read (
199  unsigned type, arrayElementCount count,
200  cacReadNotify &, ioid * = 0 ) = 0;
201  virtual void write (
203  unsigned type, arrayElementCount count,
204  const void *pValue ) = 0;
205  virtual ioStatus write (
207  unsigned type, arrayElementCount count,
208  const void *pValue, cacWriteNotify &, ioid * = 0 ) = 0;
209  virtual void subscribe (
210  epicsGuard < epicsMutex > &, unsigned type,
211  arrayElementCount count, unsigned mask, cacStateNotify &,
212  ioid * = 0 ) = 0;
213  // The primary mutex must be released when calling the user's
214  // callback, and therefore a finite interval exists when we are
215  // moving forward with the intent to call the users callback
216  // but the users IO could be deleted during this interval.
217  // To prevent the user's callback from being called after
218  // destroying his IO we must past a guard for the callback
219  // mutex here.
220  virtual void ioCancel (
221  CallbackGuard & callbackGuard,
222  epicsGuard < epicsMutex > & mutualExclusionGuard,
223  const ioid & ) = 0;
224  virtual void ioShow (
226  const ioid &, unsigned level ) const = 0;
227  virtual short nativeType (
228  epicsGuard < epicsMutex > & ) const = 0;
229  virtual arrayElementCount nativeElementCount (
230  epicsGuard < epicsMutex > & ) const = 0;
231  virtual caAccessRights accessRights (
232  epicsGuard < epicsMutex > & ) const;
233  virtual unsigned searchAttempts (
234  epicsGuard < epicsMutex > & ) const;
235  virtual double beaconPeriod (
236  epicsGuard < epicsMutex > & ) const; // negative DBL_MAX if UKN
237  virtual double receiveWatchdogDelay (
238  epicsGuard < epicsMutex > & ) const; // negative DBL_MAX if UKN
239  virtual bool ca_v42_ok (
240  epicsGuard < epicsMutex > & ) const;
241  virtual bool connected (
242  epicsGuard < epicsMutex > & ) const;
243  virtual unsigned getHostName (
245  char * pBuf, unsigned bufLength ) const throw ();
246  // !! deprecated, avoid use !!
247  virtual const char * pHostName (
248  epicsGuard < epicsMutex > & guard ) const throw ();
249 
250  // exceptions
251  class badString {};
252  class badType {};
253  class badPriority {};
254  class outOfBounds {};
256  class noWriteAccess {};
257  class noReadAccess {};
258  class notConnected {};
260  class msgBodyCacheTooSmall {}; // hopefully this one goes away in the future
261  class requestTimedOut {};
262 
263 protected:
264  virtual ~cacChannel () = 0;
265 
266 private:
267  cacChannelNotify & callback;
268  cacChannel ( const cacChannel & );
269  cacChannel & operator = ( const cacChannel & );
270 };
271 
272 class LIBCA_API cacContext {
273 public:
274  virtual ~cacContext ();
275  virtual cacChannel & createChannel (
277  const char * pChannelName, cacChannelNotify &,
278  cacChannel::priLev = cacChannel::priorityDefault ) = 0;
279  virtual void flush (
281  virtual unsigned circuitCount (
282  epicsGuard < epicsMutex > & ) const = 0;
283  virtual void selfTest (
284  epicsGuard < epicsMutex > & ) const = 0;
285  virtual unsigned beaconAnomaliesSinceProgramStart (
286  epicsGuard < epicsMutex > & ) const = 0;
287  virtual void show (
288  epicsGuard < epicsMutex > &, unsigned level ) const = 0;
289 };
290 
291 class LIBCA_API cacContextNotify {
292 public:
293  virtual ~cacContextNotify () = 0;
294  virtual cacContext & createNetworkContext (
295  epicsMutex & mutualExclusion, epicsMutex & callbackControl ) = 0;
296 // we should probably have a different vf for each type of exception ????
297  virtual void exception (
298  epicsGuard < epicsMutex > &, int status, const char * pContext,
299  const char * pFileName, unsigned lineNo ) = 0;
300 // perhaps this should be phased out in deference to the exception mechanism
301  virtual int varArgsPrintFormated ( const char * pformat, va_list args ) const = 0;
302 // backwards compatibility (from here down)
303  virtual void attachToClientCtx () = 0;
304  virtual void callbackProcessingInitiateNotify () = 0;
305  virtual void callbackProcessingCompleteNotify () = 0;
306 };
307 
308 // **** Lock Hierarchy ****
309 // callbackControl must be taken before mutualExclusion if both are held at
310 // the same time
311 class LIBCA_API cacService {
312 public:
313  virtual ~cacService () = 0;
314  virtual cacContext & contextCreate (
315  epicsMutex & mutualExclusion,
316  epicsMutex & callbackControl,
317  cacContextNotify & ) = 0;
318 };
319 
320 LIBCA_API void epicsStdCall caInstallDefaultService ( cacService & service );
321 
322 LIBCA_API extern epicsThreadPrivateId caClientCallbackThreadId;
323 
324 inline cacChannel::cacChannel ( cacChannelNotify & notify ) :
325  callback ( notify )
326 {
327 }
328 
329 inline cacChannelNotify & cacChannel::notify () const
330 {
331  return this->callback;
332 }
333 
334 inline caAccessRights::caAccessRights (
335  bool readPermit, bool writePermit, bool operatorConfirmationRequest) :
336  f_readPermit ( readPermit ), f_writePermit ( writePermit ),
337  f_operatorConfirmationRequest ( operatorConfirmationRequest ) {}
338 
339 inline void caAccessRights::setReadPermit ()
340 {
341  this->f_readPermit = true;
342 }
343 
344 inline void caAccessRights::setWritePermit ()
345 {
346  this->f_writePermit = true;
347 }
348 
349 inline void caAccessRights::setOperatorConfirmationRequest ()
350 {
351  this->f_operatorConfirmationRequest = true;
352 }
353 
354 inline void caAccessRights::clrReadPermit ()
355 {
356  this->f_readPermit = false;
357 }
358 
359 inline void caAccessRights::clrWritePermit ()
360 {
361  this->f_writePermit = false;
362 }
363 
364 inline void caAccessRights::clrOperatorConfirmationRequest ()
365 {
366  this->f_operatorConfirmationRequest = false;
367 }
368 
369 inline bool caAccessRights::readPermit () const
370 {
371  return this->f_readPermit;
372 }
373 
374 inline bool caAccessRights::writePermit () const
375 {
376  return this->f_writePermit;
377 }
378 
379 inline bool caAccessRights::operatorConfirmationRequest () const
380 {
381  return this->f_operatorConfirmationRequest;
382 }
383 
384 #endif // ifndef INC_cacIO_H
Provides classes for RAII style locking and unlocking of mutexes.
C++ and C descriptions for a thread.
The C++ API for an epicsMutex.
Definition: epicsMutex.h:69
struct epicsThreadPrivateOSD * epicsThreadPrivateId
Definition: epicsThread.h:334
APIs for the epicsMutex mutual exclusion semaphore.