From c28bb13e9aa7974067d75c58514add14269f4cc9 Mon Sep 17 00:00:00 2001 From: Jeff Hill Date: Mon, 23 Sep 2002 22:10:20 +0000 Subject: [PATCH] its probably best for a put callback to save a private copy of the users data that is being written --- src/db/dbPutNotifyBlocker.cpp | 30 ++++++++++++++++++++++++------ src/db/dbPutNotifyBlocker.h | 18 ++++++++++++++++++ 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/db/dbPutNotifyBlocker.cpp b/src/db/dbPutNotifyBlocker.cpp index ef4e5b47f..8d565ce61 100644 --- a/src/db/dbPutNotifyBlocker.cpp +++ b/src/db/dbPutNotifyBlocker.cpp @@ -46,14 +46,19 @@ epicsSingleton < tsFreeList < dbPutNotifyBlocker, 1024 > > dbPutNotifyBlocker::pFreeList; dbPutNotifyBlocker::dbPutNotifyBlocker ( dbChannelIO &chanIn ) : - pNotify ( 0 ) + pNotify ( 0 ), maxValueSize ( sizeof ( this->dbrScalarValue ) ) { - memset ( &this->pn, '\0', sizeof ( this->pn ) ); + memset ( & this->pn, '\0', sizeof ( this->pn ) ); + memset ( & this->dbrScalarValue, '\0', sizeof ( this->dbrScalarValue ) ); + this->pn.pbuffer = & this->dbrScalarValue; } dbPutNotifyBlocker::~dbPutNotifyBlocker () { this->cancel (); + if ( this->maxValueSize > sizeof ( this->dbrScalarValue ) ) { + delete [] this->pn.pbuffer; + } } void dbPutNotifyBlocker::destroy () @@ -66,11 +71,23 @@ void dbPutNotifyBlocker::cancel () if ( this->pn.paddr ) { dbNotifyCancel ( &this->pn ); } - memset ( &this->pn, '\0', sizeof ( this->pn ) ); this->pNotify = 0; this->block.signal (); } +void dbPutNotifyBlocker::expandValueBuf ( unsigned long newSize ) +{ + if ( this->maxValueSize < newSize ) { + if ( this->maxValueSize > sizeof ( this->dbrScalarValue ) ) { + delete [] this->pn.pbuffer; + this->maxValueSize = sizeof ( this->dbrScalarValue ); + this->pn.pbuffer = & this->dbrScalarValue; + } + this->pn.pbuffer = new char [newSize]; + this->maxValueSize = newSize; + } +} + extern "C" void putNotifyCompletion ( putNotify *ppn ) { dbPutNotifyBlocker *pBlocker = static_cast < dbPutNotifyBlocker * > ( ppn->usrPvt ); @@ -97,7 +114,6 @@ extern "C" void putNotifyCompletion ( putNotify *ppn ) errlogPrintf ( "put notify completion with nill pNotify?\n" ); } // no need to lock here because only one put notify at a time is allowed to run - memset ( &pBlocker->pn, '\0', sizeof ( pBlocker->pn ) ); pBlocker->pNotify = 0; pBlocker->block.signal (); } @@ -140,17 +156,19 @@ void dbPutNotifyBlocker::initiatePutNotify ( epicsGuard < epicsMutex > & locker, status = dbPutNotifyMapType ( &this->pn, static_cast ( type ) ); if ( status ) { - memset ( &this->pn, '\0', sizeof ( this->pn ) ); this->pNotify = 0; throw cacChannel::badType(); } - this->pn.pbuffer = const_cast < void * > ( pValue ); this->pn.nRequest = static_cast < unsigned > ( count ); this->pn.paddr = &addr; this->pn.userCallback = putNotifyCompletion; this->pn.usrPvt = this; + unsigned long size = dbr_size_n ( type, count ); + this->expandValueBuf ( size ); + memcpy ( this->pn.pbuffer, pValue, size ); + ::dbPutNotify ( &this->pn ); } diff --git a/src/db/dbPutNotifyBlocker.h b/src/db/dbPutNotifyBlocker.h index bd5414929..c15f0b57b 100644 --- a/src/db/dbPutNotifyBlocker.h +++ b/src/db/dbPutNotifyBlocker.h @@ -58,9 +58,27 @@ protected: virtual ~dbPutNotifyBlocker (); private: putNotify pn; + // + // Include a union of all scalar types + // including fixed length strings so + // that in many cases we can avoid + // allocating another buffer + // + union { + dbr_string_t strval; + dbr_short_t shrtval; + dbr_short_t intval; + dbr_float_t fltval; + dbr_enum_t enmval; + dbr_char_t charval; + dbr_long_t longval; + dbr_double_t doubleval; + } dbrScalarValue; epicsEvent block; cacWriteNotify * pNotify; + unsigned long maxValueSize; dbSubscriptionIO * isSubscription (); + void dbPutNotifyBlocker::expandValueBuf ( unsigned long newSize ); static epicsSingleton < tsFreeList < dbPutNotifyBlocker > > pFreeList; friend void putNotifyCompletion ( putNotify *ppn ); dbPutNotifyBlocker ( const dbPutNotifyBlocker & );