PageRenderTime 49ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/ATF2/control-software/epics-3.14.10/base/src/ca/oldChannelNotify.cpp

http://atf2flightsim.googlecode.com/
C++ | 706 lines | 555 code | 52 blank | 99 comment | 30 complexity | 4fa57204b01237abb7ce8f4943a7ead5 MD5 | raw file
Possible License(s): BSD-2-Clause, LGPL-2.0, IPL-1.0, BSD-3-Clause
  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 Versions 3.13.7
  7. * and higher are 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
  21. * johill@lanl.gov
  22. * 505 665 1831
  23. */
  24. #include <string>
  25. #include <stdexcept>
  26. #ifdef _MSC_VER
  27. # pragma warning(disable:4355)
  28. #endif
  29. #define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
  30. #include "errlog.h"
  31. #define epicsExportSharedSymbols
  32. #include "iocinf.h"
  33. #include "oldAccess.h"
  34. #include "cac.h"
  35. #include "autoPtrFreeList.h"
  36. extern "C" void cacNoopAccesRightsHandler ( struct access_rights_handler_args )
  37. {
  38. }
  39. oldChannelNotify::oldChannelNotify (
  40. epicsGuard < epicsMutex > & guard, ca_client_context & cacIn,
  41. const char *pName, caCh * pConnCallBackIn,
  42. void * pPrivateIn, capri priority ) :
  43. cacCtx ( cacIn ),
  44. io ( cacIn.createChannel ( guard, pName, *this, priority ) ),
  45. pConnCallBack ( pConnCallBackIn ),
  46. pPrivate ( pPrivateIn ), pAccessRightsFunc ( cacNoopAccesRightsHandler ),
  47. ioSeqNo ( 0 ), currentlyConnected ( false ), prevConnected ( false )
  48. {
  49. guard.assertIdenticalMutex ( cacIn.mutexRef () );
  50. this->ioSeqNo = cacIn.sequenceNumberOfOutstandingIO ( guard );
  51. if ( pConnCallBackIn == 0 ) {
  52. cacIn.incrementOutstandingIO ( guard, this->ioSeqNo );
  53. }
  54. }
  55. oldChannelNotify::~oldChannelNotify ()
  56. {
  57. }
  58. void oldChannelNotify::destructor (
  59. epicsGuard < epicsMutex > & guard )
  60. {
  61. guard.assertIdenticalMutex ( this->cacCtx.mutexRef () );
  62. this->io.destroy ( guard );
  63. // no need to worry about a connect preempting here because
  64. // the io (the nciu) has been destroyed above
  65. if ( this->pConnCallBack == 0 && ! this->currentlyConnected ) {
  66. this->cacCtx.decrementOutstandingIO ( guard, this->ioSeqNo );
  67. }
  68. this->~oldChannelNotify ();
  69. }
  70. void oldChannelNotify::connectNotify (
  71. epicsGuard < epicsMutex > & guard )
  72. {
  73. this->currentlyConnected = true;
  74. this->prevConnected = true;
  75. if ( this->pConnCallBack ) {
  76. struct connection_handler_args args;
  77. args.chid = this;
  78. args.op = CA_OP_CONN_UP;
  79. caCh * pFunc = this->pConnCallBack;
  80. {
  81. epicsGuardRelease < epicsMutex > unguard ( guard );
  82. ( *pFunc ) ( args );
  83. }
  84. }
  85. else {
  86. this->cacCtx.decrementOutstandingIO ( guard, this->ioSeqNo );
  87. }
  88. }
  89. void oldChannelNotify::disconnectNotify (
  90. epicsGuard < epicsMutex > & guard )
  91. {
  92. this->currentlyConnected = false;
  93. if ( this->pConnCallBack ) {
  94. struct connection_handler_args args;
  95. args.chid = this;
  96. args.op = CA_OP_CONN_DOWN;
  97. caCh * pFunc = this->pConnCallBack;
  98. {
  99. epicsGuardRelease < epicsMutex > unguard ( guard );
  100. ( *pFunc ) ( args );
  101. }
  102. }
  103. else {
  104. this->cacCtx.incrementOutstandingIO (
  105. guard, this->ioSeqNo );
  106. }
  107. }
  108. void oldChannelNotify::serviceShutdownNotify (
  109. epicsGuard < epicsMutex > & guard )
  110. {
  111. this->disconnectNotify ( guard );
  112. }
  113. void oldChannelNotify::accessRightsNotify (
  114. epicsGuard < epicsMutex > & guard, const caAccessRights & ar )
  115. {
  116. struct access_rights_handler_args args;
  117. args.chid = this;
  118. args.ar.read_access = ar.readPermit();
  119. args.ar.write_access = ar.writePermit();
  120. caArh * pFunc = this->pAccessRightsFunc;
  121. {
  122. epicsGuardRelease < epicsMutex > unguard ( guard );
  123. ( *pFunc ) ( args );
  124. }
  125. }
  126. void oldChannelNotify::exception (
  127. epicsGuard < epicsMutex > & guard, int status, const char * pContext )
  128. {
  129. this->cacCtx.exception ( guard, status, pContext, __FILE__, __LINE__ );
  130. }
  131. void oldChannelNotify::readException (
  132. epicsGuard < epicsMutex > & guard, int status, const char *pContext,
  133. unsigned type, arrayElementCount count, void * /* pValue */ )
  134. {
  135. this->cacCtx.exception ( guard, status, pContext,
  136. __FILE__, __LINE__, *this, type, count, CA_OP_GET );
  137. }
  138. void oldChannelNotify::writeException (
  139. epicsGuard < epicsMutex > & guard, int status, const char *pContext,
  140. unsigned type, arrayElementCount count )
  141. {
  142. this->cacCtx.exception ( guard, status, pContext,
  143. __FILE__, __LINE__, *this, type, count, CA_OP_PUT );
  144. }
  145. void * oldChannelNotify::operator new ( size_t ) // X aCC 361
  146. {
  147. // The HPUX compiler seems to require this even though no code
  148. // calls it directly
  149. throw std::logic_error ( "why is the compiler calling private operator new" );
  150. }
  151. void oldChannelNotify::operator delete ( void * )
  152. {
  153. // Visual C++ .net appears to require operator delete if
  154. // placement operator delete is defined? I smell a ms rat
  155. // because if I declare placement new and delete, but
  156. // comment out the placement delete definition there are
  157. // no undefined symbols.
  158. errlogPrintf ( "%s:%d this compiler is confused about placement delete - memory was probably leaked",
  159. __FILE__, __LINE__ );
  160. }
  161. /*
  162. * ca_get_host_name ()
  163. */
  164. unsigned epicsShareAPI ca_get_host_name (
  165. chid pChan, char * pBuf, unsigned bufLength )
  166. {
  167. epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef() );
  168. return pChan->io.getHostName ( guard, pBuf, bufLength );
  169. }
  170. /*
  171. * ca_host_name ()
  172. *
  173. * !!!! not thread safe !!!!
  174. *
  175. */
  176. const char * epicsShareAPI ca_host_name (
  177. chid pChan )
  178. {
  179. epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
  180. return pChan->io.pHostName ( guard );
  181. }
  182. /*
  183. * ca_set_puser ()
  184. */
  185. void epicsShareAPI ca_set_puser (
  186. chid pChan, void * puser )
  187. {
  188. epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
  189. pChan->pPrivate = puser;
  190. }
  191. /*
  192. * ca_get_puser ()
  193. */
  194. void * epicsShareAPI ca_puser (
  195. chid pChan )
  196. {
  197. epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
  198. return pChan->pPrivate;
  199. }
  200. /*
  201. * Specify an event subroutine to be run for connection events
  202. */
  203. int epicsShareAPI ca_change_connection_event ( chid pChan, caCh * pfunc )
  204. {
  205. epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
  206. if ( ! pChan->currentlyConnected ) {
  207. if ( pfunc ) {
  208. if ( ! pChan->pConnCallBack ) {
  209. pChan->cacCtx.decrementOutstandingIO ( guard, pChan->ioSeqNo );
  210. }
  211. }
  212. else {
  213. if ( pChan->pConnCallBack ) {
  214. pChan->cacCtx.incrementOutstandingIO ( guard, pChan->ioSeqNo );
  215. }
  216. }
  217. }
  218. pChan->pConnCallBack = pfunc;
  219. return ECA_NORMAL;
  220. }
  221. /*
  222. * ca_replace_access_rights_event
  223. */
  224. int epicsShareAPI ca_replace_access_rights_event (
  225. chid pChan, caArh *pfunc )
  226. {
  227. epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
  228. // The order of the following is significant to guarantee that the
  229. // access rights handler is always gets called even if the channel connects
  230. // while this is running. There is some very small chance that the
  231. // handler could be called twice here with the same access rights state, but
  232. // that will not upset the application.
  233. pChan->pAccessRightsFunc = pfunc ? pfunc : cacNoopAccesRightsHandler;
  234. caAccessRights tmp = pChan->io.accessRights ( guard );
  235. if ( pChan->currentlyConnected ) {
  236. struct access_rights_handler_args args;
  237. args.chid = pChan;
  238. args.ar.read_access = tmp.readPermit ();
  239. args.ar.write_access = tmp.writePermit ();
  240. epicsGuardRelease < epicsMutex > unguard ( guard );
  241. ( *pChan->pAccessRightsFunc ) ( args );
  242. }
  243. return ECA_NORMAL;
  244. }
  245. /*
  246. * ca_array_get ()
  247. */
  248. int epicsShareAPI ca_array_get ( chtype type,
  249. arrayElementCount count, chid pChan, void *pValue )
  250. {
  251. int caStatus;
  252. try {
  253. if ( type < 0 ) {
  254. return ECA_BADTYPE;
  255. }
  256. unsigned tmpType = static_cast < unsigned > ( type );
  257. epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
  258. pChan->eliminateExcessiveSendBacklog ( guard );
  259. autoPtrFreeList < getCopy, 0x400, epicsMutexNOOP > pNotify
  260. ( pChan->getClientCtx().getCopyFreeList,
  261. new ( pChan->getClientCtx().getCopyFreeList )
  262. getCopy ( guard, pChan->getClientCtx(), *pChan,
  263. tmpType, count, pValue ) );
  264. pChan->io.read ( guard, type, count, *pNotify, 0 );
  265. pNotify.release ();
  266. caStatus = ECA_NORMAL;
  267. }
  268. catch ( cacChannel::badString & )
  269. {
  270. caStatus = ECA_BADSTR;
  271. }
  272. catch ( cacChannel::badType & )
  273. {
  274. caStatus = ECA_BADTYPE;
  275. }
  276. catch ( cacChannel::outOfBounds & )
  277. {
  278. caStatus = ECA_BADCOUNT;
  279. }
  280. catch ( cacChannel::noReadAccess & )
  281. {
  282. caStatus = ECA_NORDACCESS;
  283. }
  284. catch ( cacChannel::notConnected & )
  285. {
  286. caStatus = ECA_DISCONN;
  287. }
  288. catch ( cacChannel::unsupportedByService & )
  289. {
  290. caStatus = ECA_UNAVAILINSERV;
  291. }
  292. catch ( cacChannel::requestTimedOut & )
  293. {
  294. caStatus = ECA_TIMEOUT;
  295. }
  296. catch ( std::bad_alloc & )
  297. {
  298. caStatus = ECA_ALLOCMEM;
  299. }
  300. catch ( cacChannel::msgBodyCacheTooSmall & ) {
  301. caStatus = ECA_TOLARGE;
  302. }
  303. catch ( ... )
  304. {
  305. caStatus = ECA_GETFAIL;
  306. }
  307. return caStatus;
  308. }
  309. /*
  310. * ca_array_get_callback ()
  311. */
  312. int epicsShareAPI ca_array_get_callback ( chtype type,
  313. arrayElementCount count, chid pChan,
  314. caEventCallBackFunc *pfunc, void *arg )
  315. {
  316. int caStatus;
  317. try {
  318. if ( type < 0 ) {
  319. return ECA_BADTYPE;
  320. }
  321. unsigned tmpType = static_cast < unsigned > ( type );
  322. epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
  323. pChan->eliminateExcessiveSendBacklog ( guard );
  324. autoPtrFreeList < getCallback, 0x400, epicsMutexNOOP > pNotify
  325. ( pChan->getClientCtx().getCallbackFreeList,
  326. new ( pChan->getClientCtx().getCallbackFreeList )
  327. getCallback ( *pChan, pfunc, arg ) );
  328. pChan->io.read ( guard, tmpType, count, *pNotify, 0 );
  329. pNotify.release ();
  330. caStatus = ECA_NORMAL;
  331. }
  332. catch ( cacChannel::badString & )
  333. {
  334. caStatus = ECA_BADSTR;
  335. }
  336. catch ( cacChannel::badType & )
  337. {
  338. caStatus = ECA_BADTYPE;
  339. }
  340. catch ( cacChannel::outOfBounds & )
  341. {
  342. caStatus = ECA_BADCOUNT;
  343. }
  344. catch ( cacChannel::noReadAccess & )
  345. {
  346. caStatus = ECA_NORDACCESS;
  347. }
  348. catch ( cacChannel::notConnected & )
  349. {
  350. caStatus = ECA_DISCONN;
  351. }
  352. catch ( cacChannel::unsupportedByService & )
  353. {
  354. caStatus = ECA_UNAVAILINSERV;
  355. }
  356. catch ( cacChannel::requestTimedOut & )
  357. {
  358. caStatus = ECA_TIMEOUT;
  359. }
  360. catch ( std::bad_alloc & )
  361. {
  362. caStatus = ECA_ALLOCMEM;
  363. }
  364. catch ( cacChannel::msgBodyCacheTooSmall ) {
  365. caStatus = ECA_TOLARGE;
  366. }
  367. catch ( ... )
  368. {
  369. caStatus = ECA_GETFAIL;
  370. }
  371. return caStatus;
  372. }
  373. void oldChannelNotify::read (
  374. epicsGuard < epicsMutex > & guard,
  375. unsigned type, arrayElementCount count,
  376. cacReadNotify & notify, cacChannel::ioid * pId )
  377. {
  378. this->io.read ( guard, type, count, notify, pId );
  379. }
  380. /*
  381. * ca_array_put_callback ()
  382. */
  383. int epicsShareAPI ca_array_put_callback ( chtype type, arrayElementCount count,
  384. chid pChan, const void *pValue, caEventCallBackFunc *pfunc, void *usrarg )
  385. {
  386. int caStatus;
  387. try {
  388. if ( type < 0 ) {
  389. return ECA_BADTYPE;
  390. }
  391. epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
  392. pChan->eliminateExcessiveSendBacklog ( guard );
  393. unsigned tmpType = static_cast < unsigned > ( type );
  394. autoPtrFreeList < putCallback, 0x400, epicsMutexNOOP > pNotify
  395. ( pChan->getClientCtx().putCallbackFreeList,
  396. new ( pChan->getClientCtx().putCallbackFreeList )
  397. putCallback ( *pChan, pfunc, usrarg ) );
  398. pChan->io.write ( guard, tmpType, count, pValue, *pNotify, 0 );
  399. pNotify.release ();
  400. caStatus = ECA_NORMAL;
  401. }
  402. catch ( cacChannel::badString & )
  403. {
  404. caStatus = ECA_BADSTR;
  405. }
  406. catch ( cacChannel::badType & )
  407. {
  408. caStatus = ECA_BADTYPE;
  409. }
  410. catch ( cacChannel::outOfBounds & )
  411. {
  412. caStatus = ECA_BADCOUNT;
  413. }
  414. catch ( cacChannel::noWriteAccess & )
  415. {
  416. caStatus = ECA_NOWTACCESS;
  417. }
  418. catch ( cacChannel::notConnected & )
  419. {
  420. caStatus = ECA_DISCONN;
  421. }
  422. catch ( cacChannel::unsupportedByService & )
  423. {
  424. caStatus = ECA_UNAVAILINSERV;
  425. }
  426. catch ( cacChannel::requestTimedOut & )
  427. {
  428. caStatus = ECA_TIMEOUT;
  429. }
  430. catch ( std::bad_alloc & )
  431. {
  432. caStatus = ECA_ALLOCMEM;
  433. }
  434. catch ( ... )
  435. {
  436. caStatus = ECA_PUTFAIL;
  437. }
  438. return caStatus;
  439. }
  440. /*
  441. * ca_array_put ()
  442. */
  443. int epicsShareAPI ca_array_put ( chtype type, arrayElementCount count,
  444. chid pChan, const void * pValue )
  445. {
  446. if ( type < 0 ) {
  447. return ECA_BADTYPE;
  448. }
  449. unsigned tmpType = static_cast < unsigned > ( type );
  450. int caStatus;
  451. try {
  452. epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
  453. pChan->eliminateExcessiveSendBacklog ( guard );
  454. pChan->io.write ( guard, tmpType, count, pValue );
  455. caStatus = ECA_NORMAL;
  456. }
  457. catch ( cacChannel::badString & )
  458. {
  459. caStatus = ECA_BADSTR;
  460. }
  461. catch ( cacChannel::badType & )
  462. {
  463. caStatus = ECA_BADTYPE;
  464. }
  465. catch ( cacChannel::outOfBounds & )
  466. {
  467. caStatus = ECA_BADCOUNT;
  468. }
  469. catch ( cacChannel::noWriteAccess & )
  470. {
  471. caStatus = ECA_NOWTACCESS;
  472. }
  473. catch ( cacChannel::notConnected & )
  474. {
  475. caStatus = ECA_DISCONN;
  476. }
  477. catch ( cacChannel::unsupportedByService & )
  478. {
  479. caStatus = ECA_UNAVAILINSERV;
  480. }
  481. catch ( cacChannel::requestTimedOut & )
  482. {
  483. caStatus = ECA_TIMEOUT;
  484. }
  485. catch ( std::bad_alloc & )
  486. {
  487. caStatus = ECA_ALLOCMEM;
  488. }
  489. catch ( ... )
  490. {
  491. caStatus = ECA_PUTFAIL;
  492. }
  493. return caStatus;
  494. }
  495. int epicsShareAPI ca_create_subscription (
  496. chtype type, arrayElementCount count, chid pChan,
  497. long mask, caEventCallBackFunc * pCallBack, void * pCallBackArg,
  498. evid * monixptr )
  499. {
  500. if ( type < 0 ) {
  501. return ECA_BADTYPE;
  502. }
  503. unsigned tmpType = static_cast < unsigned > ( type );
  504. if ( INVALID_DB_REQ (type) ) {
  505. return ECA_BADTYPE;
  506. }
  507. if ( pCallBack == NULL ) {
  508. return ECA_BADFUNCPTR;
  509. }
  510. static const long maskMask = 0xffff;
  511. if ( ( mask & maskMask ) == 0) {
  512. return ECA_BADMASK;
  513. }
  514. if ( mask & ~maskMask ) {
  515. return ECA_BADMASK;
  516. }
  517. try {
  518. epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
  519. try {
  520. // if this stalls out on a live circuit then an exception
  521. // can be forthcoming which we must ignore (this is a
  522. // special case preserving legacy ca_create_subscription
  523. // behavior)
  524. pChan->eliminateExcessiveSendBacklog ( guard );
  525. }
  526. catch ( cacChannel::notConnected & ) {
  527. // intentionally ignored (its ok to subscribe when not connected)
  528. }
  529. new ( pChan->getClientCtx().subscriptionFreeList )
  530. oldSubscription (
  531. guard, *pChan, pChan->io, tmpType, count, mask,
  532. pCallBack, pCallBackArg, monixptr );
  533. // dont touch object created after above new because
  534. // the first callback might have canceled, and therefore
  535. // destroyed, it
  536. return ECA_NORMAL;
  537. }
  538. catch ( cacChannel::badType & )
  539. {
  540. return ECA_BADTYPE;
  541. }
  542. catch ( cacChannel::outOfBounds & )
  543. {
  544. return ECA_BADCOUNT;
  545. }
  546. catch ( cacChannel::badEventSelection & )
  547. {
  548. return ECA_BADMASK;
  549. }
  550. catch ( cacChannel::noReadAccess & )
  551. {
  552. return ECA_NORDACCESS;
  553. }
  554. catch ( cacChannel::unsupportedByService & )
  555. {
  556. return ECA_UNAVAILINSERV;
  557. }
  558. catch ( std::bad_alloc & )
  559. {
  560. return ECA_ALLOCMEM;
  561. }
  562. catch ( cacChannel::msgBodyCacheTooSmall & ) {
  563. return ECA_TOLARGE;
  564. }
  565. catch ( ... )
  566. {
  567. return ECA_INTERNAL;
  568. }
  569. }
  570. void oldChannelNotify::write (
  571. epicsGuard < epicsMutex > & guard, unsigned type, arrayElementCount count,
  572. const void * pValue, cacWriteNotify & notify, cacChannel::ioid * pId )
  573. {
  574. this->io.write ( guard, type, count, pValue, notify, pId );
  575. }
  576. /*
  577. * ca_field_type()
  578. */
  579. short epicsShareAPI ca_field_type ( chid pChan )
  580. {
  581. epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
  582. return pChan->io.nativeType ( guard );
  583. }
  584. /*
  585. * ca_element_count ()
  586. */
  587. arrayElementCount epicsShareAPI ca_element_count ( chid pChan )
  588. {
  589. epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
  590. return pChan->io.nativeElementCount ( guard );
  591. }
  592. /*
  593. * ca_state ()
  594. */
  595. enum channel_state epicsShareAPI ca_state ( chid pChan ) // X aCC 361
  596. {
  597. epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
  598. if ( pChan->io.connected ( guard ) ) {
  599. return cs_conn;
  600. }
  601. else if ( pChan->prevConnected ){
  602. return cs_prev_conn;
  603. }
  604. else {
  605. return cs_never_conn;
  606. }
  607. }
  608. /*
  609. * ca_read_access ()
  610. */
  611. unsigned epicsShareAPI ca_read_access ( chid pChan )
  612. {
  613. epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
  614. return pChan->io.accessRights(guard).readPermit();
  615. }
  616. /*
  617. * ca_write_access ()
  618. */
  619. unsigned epicsShareAPI ca_write_access ( chid pChan )
  620. {
  621. epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
  622. return pChan->io.accessRights(guard).writePermit();
  623. }
  624. /*
  625. * ca_name ()
  626. */
  627. const char * epicsShareAPI ca_name ( chid pChan )
  628. {
  629. epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
  630. return pChan->io.pName ( guard );
  631. }
  632. unsigned epicsShareAPI ca_search_attempts ( chid pChan )
  633. {
  634. epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
  635. return pChan->io.searchAttempts ( guard );
  636. }
  637. double epicsShareAPI ca_beacon_period ( chid pChan )
  638. {
  639. epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
  640. return pChan->io.beaconPeriod ( guard );
  641. }
  642. double epicsShareAPI ca_receive_watchdog_delay ( chid pChan )
  643. {
  644. epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
  645. return pChan->io.receiveWatchdogDelay ( guard );
  646. }
  647. /*
  648. * ca_v42_ok(chid chan)
  649. */
  650. int epicsShareAPI ca_v42_ok ( chid pChan )
  651. {
  652. epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
  653. return pChan->io.ca_v42_ok ( guard );
  654. }