Also unified the header exclusion guard names, removed a couple of files that are no longer used, dropped the '3.13.7' from the Copyright header.
335 lines
9.0 KiB
C++
335 lines
9.0 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.
|
|
* EPICS BASE is distributed subject to a Software License Agreement found
|
|
* in file LICENSE that is included with this distribution.
|
|
\*************************************************************************/
|
|
/*
|
|
*
|
|
*
|
|
* L O S A L A M O S
|
|
* Los Alamos National Laboratory
|
|
* Los Alamos, New Mexico 87545
|
|
*
|
|
* Copyright, 1986, The Regents of the University of California.
|
|
*
|
|
*
|
|
* Author Jeffrey O. Hill
|
|
* johill@lanl.gov
|
|
*/
|
|
|
|
#ifndef INC_comBuf_H
|
|
#define INC_comBuf_H
|
|
|
|
#include <new>
|
|
#include <cstring>
|
|
|
|
#include "epicsAssert.h"
|
|
#include "epicsTypes.h"
|
|
#include "tsFreeList.h"
|
|
#include "tsDLList.h"
|
|
#include "osiWireFormat.h"
|
|
#include "compilerDependencies.h"
|
|
|
|
static const unsigned comBufSize = 0x4000;
|
|
|
|
// this wrapper avoids Tornado 2.0.1 compiler bugs
|
|
class comBufMemoryManager {
|
|
public:
|
|
virtual ~comBufMemoryManager ();
|
|
virtual void * allocate ( size_t ) = 0;
|
|
virtual void release ( void * ) = 0;
|
|
};
|
|
|
|
class wireSendAdapter {
|
|
public:
|
|
virtual unsigned sendBytes ( const void * pBuf,
|
|
unsigned nBytesInBuf,
|
|
const class epicsTime & currentTime ) = 0;
|
|
protected:
|
|
virtual ~wireSendAdapter() {}
|
|
};
|
|
|
|
enum swioCircuitState {
|
|
swioConnected,
|
|
swioPeerHangup,
|
|
swioPeerAbort,
|
|
swioLinkFailure,
|
|
swioLocalAbort
|
|
};
|
|
struct statusWireIO {
|
|
unsigned bytesCopied;
|
|
swioCircuitState circuitState;
|
|
};
|
|
|
|
class wireRecvAdapter {
|
|
public:
|
|
virtual void recvBytes ( void * pBuf,
|
|
unsigned nBytesInBuf, statusWireIO & ) = 0;
|
|
protected:
|
|
virtual ~wireRecvAdapter() {}
|
|
};
|
|
|
|
class comBuf : public tsDLNode < comBuf > {
|
|
public:
|
|
class insufficentBytesAvailable {};
|
|
comBuf ();
|
|
unsigned unoccupiedBytes () const;
|
|
unsigned occupiedBytes () const;
|
|
unsigned uncommittedBytes () const;
|
|
static unsigned capacityBytes ();
|
|
void clear ();
|
|
unsigned copyInBytes ( const void *pBuf, unsigned nBytes );
|
|
unsigned push ( comBuf & );
|
|
template < class T >
|
|
bool push ( const T & value );
|
|
template < class T >
|
|
unsigned push ( const T * pValue, unsigned nElem );
|
|
unsigned push ( const epicsInt8 * pValue, unsigned nElem );
|
|
unsigned push ( const epicsUInt8 * pValue, unsigned nElem );
|
|
unsigned push ( const epicsOldString * pValue, unsigned nElem );
|
|
void commitIncomming ();
|
|
void clearUncommittedIncomming ();
|
|
bool copyInAllBytes ( const void *pBuf, unsigned nBytes );
|
|
unsigned copyOutBytes ( void *pBuf, unsigned nBytes );
|
|
bool copyOutAllBytes ( void *pBuf, unsigned nBytes );
|
|
unsigned removeBytes ( unsigned nBytes );
|
|
bool flushToWire ( wireSendAdapter &, const epicsTime & currentTime );
|
|
void fillFromWire ( wireRecvAdapter &, statusWireIO & );
|
|
struct popStatus {
|
|
bool success;
|
|
bool nowEmpty;
|
|
};
|
|
template < class T >
|
|
popStatus pop ( T & );
|
|
static void throwInsufficentBytesException ();
|
|
void * operator new ( size_t size,
|
|
comBufMemoryManager & );
|
|
epicsPlacementDeleteOperator (( void *, comBufMemoryManager & ))
|
|
private:
|
|
unsigned commitIndex;
|
|
unsigned nextWriteIndex;
|
|
unsigned nextReadIndex;
|
|
epicsUInt8 buf [ comBufSize ];
|
|
void operator delete ( void * );
|
|
template < class T >
|
|
bool push ( const T * ); // disabled
|
|
};
|
|
|
|
inline void * comBuf::operator new ( size_t size,
|
|
comBufMemoryManager & mgr )
|
|
{
|
|
return mgr.allocate ( size );
|
|
}
|
|
|
|
#ifdef CXX_PLACEMENT_DELETE
|
|
inline void comBuf::operator delete ( void * pCadaver,
|
|
comBufMemoryManager & mgr )
|
|
{
|
|
mgr.release ( pCadaver );
|
|
}
|
|
#endif
|
|
|
|
inline comBuf::comBuf () : commitIndex ( 0u ),
|
|
nextWriteIndex ( 0u ), nextReadIndex ( 0u )
|
|
{
|
|
}
|
|
|
|
inline void comBuf :: clear ()
|
|
{
|
|
this->commitIndex = 0u;
|
|
this->nextWriteIndex = 0u;
|
|
this->nextReadIndex = 0u;
|
|
}
|
|
|
|
inline unsigned comBuf :: unoccupiedBytes () const
|
|
{
|
|
return sizeof ( this->buf ) - this->nextWriteIndex;
|
|
}
|
|
|
|
inline unsigned comBuf :: occupiedBytes () const
|
|
{
|
|
return this->commitIndex - this->nextReadIndex;
|
|
}
|
|
|
|
inline unsigned comBuf :: uncommittedBytes () const
|
|
{
|
|
return this->nextWriteIndex - this->commitIndex;
|
|
}
|
|
|
|
inline unsigned comBuf :: push ( comBuf & bufIn )
|
|
{
|
|
unsigned nBytes = this->copyInBytes (
|
|
& bufIn.buf[ bufIn.nextReadIndex ],
|
|
bufIn.commitIndex - bufIn.nextReadIndex );
|
|
bufIn.nextReadIndex += nBytes;
|
|
return nBytes;
|
|
}
|
|
|
|
inline unsigned comBuf :: capacityBytes ()
|
|
{
|
|
return comBufSize;
|
|
}
|
|
|
|
inline void comBuf :: fillFromWire (
|
|
wireRecvAdapter & wire, statusWireIO & stat )
|
|
{
|
|
wire.recvBytes (
|
|
& this->buf[this->nextWriteIndex],
|
|
sizeof ( this->buf ) - this->nextWriteIndex, stat );
|
|
if ( stat.circuitState == swioConnected ) {
|
|
this->nextWriteIndex += stat.bytesCopied;
|
|
}
|
|
}
|
|
|
|
template < class T >
|
|
inline bool comBuf :: push ( const T & value )
|
|
{
|
|
unsigned index = this->nextWriteIndex;
|
|
unsigned available = sizeof ( this->buf ) - index;
|
|
if ( sizeof ( value ) > available ) {
|
|
return false;
|
|
}
|
|
WireSet ( value, & this->buf[index] );
|
|
this->nextWriteIndex = index + sizeof ( value );
|
|
return true;
|
|
}
|
|
|
|
inline unsigned comBuf :: push ( const epicsInt8 *pValue, unsigned nElem )
|
|
{
|
|
return copyInBytes ( pValue, nElem );
|
|
}
|
|
|
|
inline unsigned comBuf :: push ( const epicsUInt8 *pValue, unsigned nElem )
|
|
{
|
|
return copyInBytes ( pValue, nElem );
|
|
}
|
|
|
|
inline unsigned comBuf :: push ( const epicsOldString * pValue, unsigned nElem )
|
|
{
|
|
unsigned index = this->nextWriteIndex;
|
|
unsigned available = sizeof ( this->buf ) - index;
|
|
unsigned nBytes = sizeof ( *pValue ) * nElem;
|
|
if ( nBytes > available ) {
|
|
nElem = available / sizeof ( *pValue );
|
|
nBytes = nElem * sizeof ( *pValue );
|
|
}
|
|
memcpy ( &this->buf[ index ], pValue, nBytes );
|
|
this->nextWriteIndex = index + nBytes;
|
|
return nElem;
|
|
}
|
|
|
|
template < class T >
|
|
unsigned comBuf :: push ( const T * pValue, unsigned nElem )
|
|
{
|
|
unsigned index = this->nextWriteIndex;
|
|
unsigned available = sizeof ( this->buf ) - index;
|
|
unsigned nBytes = sizeof ( *pValue ) * nElem;
|
|
if ( nBytes > available ) {
|
|
nElem = available / sizeof ( *pValue );
|
|
}
|
|
for ( unsigned i = 0u; i < nElem; i++ ) {
|
|
// allow native floating point formats to be converted to IEEE
|
|
WireSet( pValue[i], &this->buf[index] );
|
|
index += sizeof ( *pValue );
|
|
}
|
|
this->nextWriteIndex = index;
|
|
return nElem;
|
|
}
|
|
|
|
inline void comBuf :: commitIncomming ()
|
|
{
|
|
this->commitIndex = this->nextWriteIndex;
|
|
}
|
|
|
|
inline void comBuf :: clearUncommittedIncomming ()
|
|
{
|
|
this->nextWriteIndex = this->commitIndex;
|
|
}
|
|
|
|
inline bool comBuf :: copyInAllBytes ( const void *pBuf, unsigned nBytes )
|
|
{
|
|
unsigned index = this->nextWriteIndex;
|
|
unsigned available = sizeof ( this->buf ) - index;
|
|
if ( nBytes <= available ) {
|
|
memcpy ( & this->buf[index], pBuf, nBytes );
|
|
this->nextWriteIndex = index + nBytes;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
inline unsigned comBuf :: copyInBytes ( const void * pBuf, unsigned nBytes )
|
|
{
|
|
unsigned index = this->nextWriteIndex;
|
|
unsigned available = sizeof ( this->buf ) - index;
|
|
if ( nBytes > available ) {
|
|
nBytes = available;
|
|
}
|
|
memcpy ( & this->buf[index], pBuf, nBytes );
|
|
this->nextWriteIndex = index + nBytes;
|
|
return nBytes;
|
|
}
|
|
|
|
inline bool comBuf :: copyOutAllBytes ( void * pBuf, unsigned nBytes )
|
|
{
|
|
unsigned index = this->nextReadIndex;
|
|
unsigned occupied = this->commitIndex - index;
|
|
if ( nBytes <= occupied ) {
|
|
memcpy ( pBuf, &this->buf[index], nBytes);
|
|
this->nextReadIndex = index + nBytes;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
inline unsigned comBuf :: copyOutBytes ( void *pBuf, unsigned nBytes )
|
|
{
|
|
unsigned index = this->nextReadIndex;
|
|
unsigned occupied = this->commitIndex - index;
|
|
if ( nBytes > occupied ) {
|
|
nBytes = occupied;
|
|
}
|
|
memcpy ( pBuf, &this->buf[index], nBytes);
|
|
this->nextReadIndex = index + nBytes;
|
|
return nBytes;
|
|
}
|
|
|
|
inline unsigned comBuf :: removeBytes ( unsigned nBytes )
|
|
{
|
|
unsigned index = this->nextReadIndex;
|
|
unsigned occupied = this->commitIndex - index;
|
|
if ( nBytes > occupied ) {
|
|
nBytes = occupied;
|
|
}
|
|
this->nextReadIndex = index + nBytes;
|
|
return nBytes;
|
|
}
|
|
|
|
template < class T >
|
|
comBuf :: popStatus comBuf :: pop ( T & returnVal )
|
|
{
|
|
unsigned nrIndex = this->nextReadIndex;
|
|
unsigned popIndex = nrIndex + sizeof ( returnVal );
|
|
unsigned cIndex = this->commitIndex;
|
|
popStatus status;
|
|
status.success = true;
|
|
status.nowEmpty = false;
|
|
if ( popIndex >= cIndex ) {
|
|
if ( popIndex == cIndex ) {
|
|
status.nowEmpty = true;
|
|
}
|
|
else {
|
|
status.success = false;
|
|
return status;
|
|
}
|
|
}
|
|
WireGet ( & this->buf[ nrIndex ], returnVal );
|
|
this->nextReadIndex = popIndex;
|
|
return status;
|
|
}
|
|
|
|
#endif // ifndef INC_comBuf_H
|