Files
epics-base/modules/database/src/ioc/db/dbCAC.h
Michael Davidsaver 417821ddc0 fixups for DBCORE_API
2021-04-01 11:09:53 -07:00

243 lines
8.1 KiB
C++

/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* SPDX-License-Identifier: EPICS
* EPICS Base is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author Jeffrey O. Hill
* johill@lanl.gov
* 505 665 1831
*
* NOTES:
* 1) This interface is preliminary and will change in the future
*/
#ifndef dbCACh
#define dbCACh
#include "stdlib.h"
#include <memory> // std::auto_ptr
#include "tsDLList.h"
#include "tsFreeList.h"
#include "resourceLib.h"
#include "cacIO.h"
#include "compilerDependencies.h"
#include "dbCoreAPI.h"
#include "db_access.h"
#include "dbNotify.h"
#include "dbEvent.h"
#include "dbChannel.h"
#include "dbLock.h"
#include "dbCommon.h"
#include "db_convert.h"
#include "resourceLib.h"
namespace ca {
#if __cplusplus>=201103L
template<typename T>
using auto_ptr = std::unique_ptr<T>;
#define PTRMOVE(AUTO) std::move(AUTO)
#else
using std::auto_ptr;
#define PTRMOVE(AUTO) (AUTO)
#endif
}
extern "C" int putNotifyPut ( processNotify *ppn, notifyPutType notifyPutType );
extern "C" void putNotifyCompletion ( processNotify *ppn );
class dbContext;
class dbChannelIO;
class dbPutNotifyBlocker;
class dbSubscriptionIO;
class dbBaseIO
: public chronIntIdRes < dbBaseIO > {
public:
virtual dbSubscriptionIO * isSubscription () = 0;
virtual void show ( epicsGuard < epicsMutex > &, unsigned level ) const = 0;
virtual void show ( unsigned level ) const = 0;
dbBaseIO ();
dbBaseIO ( const dbBaseIO & );
dbBaseIO & operator = ( const dbBaseIO & );
protected:
virtual ~dbBaseIO() {}
};
extern "C" void dbSubscriptionEventCallback ( void *pPrivate, struct dbChannel *dbch,
int eventsRemaining, struct db_field_log *pfl );
class dbSubscriptionIO :
public tsDLNode < dbSubscriptionIO >,
public dbBaseIO {
public:
dbSubscriptionIO (
epicsGuard < epicsMutex > &, epicsMutex &,
dbContext &, dbChannelIO &, struct dbChannel *, cacStateNotify &,
unsigned type, unsigned long count, unsigned mask, dbEventCtx );
void destructor ( CallbackGuard &, epicsGuard < epicsMutex > & );
void unsubscribe ( CallbackGuard &, epicsGuard < epicsMutex > & );
void channelDeleteException ( CallbackGuard &, epicsGuard < epicsMutex > & );
void show ( epicsGuard < epicsMutex > &, unsigned level ) const;
void show ( unsigned level ) const;
void * operator new ( size_t size,
tsFreeList < dbSubscriptionIO, 256, epicsMutexNOOP > & );
epicsPlacementDeleteOperator (( void *,
tsFreeList < dbSubscriptionIO, 256, epicsMutexNOOP > & ))
private:
epicsMutex & mutex;
unsigned long count;
cacStateNotify & notify;
dbChannelIO & chan;
dbEventSubscription es;
unsigned type;
unsigned id;
dbSubscriptionIO * isSubscription ();
friend void dbSubscriptionEventCallback (
void * pPrivate, struct dbChannel * dbch,
int eventsRemaining, struct db_field_log * pfl );
dbSubscriptionIO ( const dbSubscriptionIO & );
dbSubscriptionIO & operator = ( const dbSubscriptionIO & );
virtual ~dbSubscriptionIO ();
void operator delete ( void * );
};
class dbContext;
class dbContextPrivateListOfIO {
public:
dbContextPrivateListOfIO ();
~dbContextPrivateListOfIO ();
private:
tsDLList < dbSubscriptionIO > eventq;
dbPutNotifyBlocker * pBlocker;
friend class dbContext;
dbContextPrivateListOfIO ( const dbContextPrivateListOfIO & );
dbContextPrivateListOfIO & operator = ( const dbContextPrivateListOfIO & );
};
class dbContextReadNotifyCacheAllocator {
public:
dbContextReadNotifyCacheAllocator ();
~dbContextReadNotifyCacheAllocator ();
char * alloc ( unsigned long size );
void free ( char * pFree );
void show ( unsigned level ) const;
private:
struct cacheElem_t {
size_t size;
struct cacheElem_t * pNext;
char buf[1];
};
unsigned long _readNotifyCacheSize;
cacheElem_t * _pReadNotifyCache;
void reclaimAllCacheEntries ();
dbContextReadNotifyCacheAllocator ( const dbContextReadNotifyCacheAllocator & );
dbContextReadNotifyCacheAllocator & operator = ( const dbContextReadNotifyCacheAllocator & );
};
class dbContextReadNotifyCache {
public:
dbContextReadNotifyCache ( epicsMutex & );
void callReadNotify ( epicsGuard < epicsMutex > &,
struct dbChannel * dbch, unsigned type, unsigned long count,
cacReadNotify & notify );
void show ( epicsGuard < epicsMutex > &, unsigned level ) const;
private:
dbContextReadNotifyCacheAllocator _allocator;
epicsMutex & _mutex;
dbContextReadNotifyCache ( const dbContextReadNotifyCache & );
dbContextReadNotifyCache & operator = ( const dbContextReadNotifyCache & );
};
class dbContext : public cacContext {
public:
dbContext ( epicsMutex & cbMutex, epicsMutex & mutex,
cacContextNotify & notify );
virtual ~dbContext ();
void destroyChannel ( CallbackGuard &,epicsGuard < epicsMutex > &, dbChannelIO & );
void callReadNotify ( epicsGuard < epicsMutex > &,
struct dbChannel * dbch, unsigned type, unsigned long count,
cacReadNotify & notify );
void callStateNotify ( struct dbChannel * dbch, unsigned type, unsigned long count,
const struct db_field_log * pfl, cacStateNotify & notify );
void subscribe (
epicsGuard < epicsMutex > &,
struct dbChannel * dbch, dbChannelIO & chan,
unsigned type, unsigned long count, unsigned mask,
cacStateNotify & notify, cacChannel::ioid * pId );
void initiatePutNotify (
epicsGuard < epicsMutex > &, dbChannelIO &, struct dbChannel *,
unsigned type, unsigned long count, const void * pValue,
cacWriteNotify & notify, cacChannel::ioid * pId );
void show ( unsigned level ) const;
void showAllIO ( const dbChannelIO & chan, unsigned level ) const;
void destroyAllIO ( CallbackGuard & cbGuard,
epicsGuard < epicsMutex > &, dbChannelIO & chan );
void ioCancel ( CallbackGuard &, epicsGuard < epicsMutex > &,
dbChannelIO & chan, const cacChannel::ioid &id );
void ioShow ( epicsGuard < epicsMutex > &,
const cacChannel::ioid & id, unsigned level ) const;
private:
tsFreeList < dbPutNotifyBlocker, 64, epicsMutexNOOP > dbPutNotifyBlockerFreeList;
tsFreeList < dbSubscriptionIO, 256, epicsMutexNOOP > dbSubscriptionIOFreeList;
tsFreeList < dbChannelIO, 256, epicsMutexNOOP > dbChannelIOFreeList;
chronIntIdResTable < dbBaseIO > ioTable;
dbContextReadNotifyCache readNotifyCache;
dbEventCtx ctx;
unsigned long stateNotifyCacheSize;
epicsMutex & mutex;
epicsMutex & cbMutex;
cacContextNotify & notify;
ca::auto_ptr < cacContext > pNetContext;
char * pStateNotifyCache;
bool isolated;
cacChannel & createChannel (
epicsGuard < epicsMutex > &,
const char * pChannelName, cacChannelNotify &,
cacChannel::priLev );
void flush (
epicsGuard < epicsMutex > & );
unsigned circuitCount (
epicsGuard < epicsMutex > & ) const;
void selfTest (
epicsGuard < epicsMutex > & ) const;
unsigned beaconAnomaliesSinceProgramStart (
epicsGuard < epicsMutex > & ) const;
void show (
epicsGuard < epicsMutex > &, unsigned level ) const;
dbContext ( const dbContext & );
dbContext & operator = ( const dbContext & );
};
inline dbContextPrivateListOfIO::dbContextPrivateListOfIO () :
pBlocker ( 0 )
{
}
inline dbContextPrivateListOfIO::~dbContextPrivateListOfIO ()
{
assert ( ! this->pBlocker );
}
inline void dbContext::callReadNotify (
epicsGuard < epicsMutex > & guard, struct dbChannel * dbch,
unsigned type, unsigned long count, cacReadNotify & notifyIn )
{
guard.assertIdenticalMutex ( this-> mutex );
this->readNotifyCache.callReadNotify ( guard, dbch, type, count, notifyIn );
}
#endif // dbCACh