#ifndef __OUC_BUFF__ #define __OUC_BUFF__ /******************************************************************************/ /* */ /* X r d O u c B u f f e r . h h */ /* */ /* (c) 2013 by the Board of Trustees of the Leland Stanford, Jr., University */ /* All Rights Reserved */ /* Produced by Andrew Hanushevsky for Stanford University under contract */ /* DE-AC02-76-SFO0515 with the Department of Energy */ /* */ /* This file is part of the XRootD software suite. */ /* */ /* XRootD is free software: you can redistribute it and/or modify it under */ /* the terms of the GNU Lesser General Public License as published by the */ /* Free Software Foundation, either version 3 of the License, or (at your */ /* option) any later version. */ /* */ /* XRootD is distributed in the hope that it will be useful, but WITHOUT */ /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */ /* License for more details. */ /* */ /* You should have received a copy of the GNU Lesser General Public License */ /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */ /* COPYING (GPL license). If not, see . */ /* */ /* The copyright holder's institutional names and contributor's names may not */ /* be used to endorse or promote products derived from this software without */ /* specific prior written permission of the institution or contributor. */ /******************************************************************************/ #include #include "XrdOuc/XrdOucChain.hh" #include "XrdSys/XrdSysPthread.hh" /******************************************************************************/ /* X r d O u c B u f f P o o l */ /******************************************************************************/ class XrdOucBuffer; //----------------------------------------------------------------------------- //! These classes allow for buffer management to minimize data copying. They //! are typically used in conjunction with the XrdOucErrInfo class. The //! XrdOucBuffPool class defines a pool of buffers and one such object must //! exist for each buffer pool (there can be many such pools). This object //! manufactures XrdOucBuffer objects. You can also create XrdOucBuffers //! without using a buffer pool (i.e. one time buffers). See the XrdOucBuffer //! constructor for details on how to do this and the associated caveats. //----------------------------------------------------------------------------- class XrdOucBuffPool { friend class XrdOucBuffer; public: //----------------------------------------------------------------------------- //! Allocate a buffer object. //! //! @param sz - the desired size. It os rounded up to be a multiple of //! incBsz but cannot exceed maxBsz. //! //! @return !0 - pointer to usable buffer object of suitable size. //! @return =0 - insufficient memort ro allocate a buffer. //----------------------------------------------------------------------------- XrdOucBuffer *Alloc(int sz); //----------------------------------------------------------------------------- //! Obtain the maximum size a buffer can have. //! //! @return The maximum size a buffer can be. //----------------------------------------------------------------------------- inline int MaxSize() const {return maxBsz;} //----------------------------------------------------------------------------- //! Constructor //! //! @param minsz - the minimum size a buffer can have. If it is smaller than //! 1024 it is set to 1024. The minsz is also adjusted to be //! equal to the closest smaller value of 1024*(2**n) (i.e. 1K, //! 2k, 4K, etc). If it's greater than 16MB, it is set to 16MB. //! @param maxsz - the maximum size a buffer can have and must be >= minsz. //! If it's >minsz it is rounded up to the next minsz increment. //! Buffer sizes are always allocated in minsz increments. //! @param minh - the minimum number of buffers that should be held in //! reserve when a buffer is recycled. //! @param maxh - the maximum number of buffers that should be held in //! reserve when a buffer is recycled. The value applies to the //! smallest buffer size and is progessively reduced as the //! buffer size increases. If maxh < minh it is set to minh. //! @param rate - specifies how quickly the hold vale is to be reduced as //! buffer sizes increase. A rate of 0 specifies a purely linear //! decrease. Higher values logrithmically decrease the hold. //----------------------------------------------------------------------------- XrdOucBuffPool(int minsz=4096, int maxsz=65536, int minh=1, int maxh=16, int rate=1); //----------------------------------------------------------------------------- //! Destructor - You must not destroy this object prior to recycling all //! oustanding buffers allocated out of this pool. //----------------------------------------------------------------------------- ~XrdOucBuffPool() {delete [] bSlot;} private: static int alignit; struct BuffSlot {XrdSysMutex SlotMutex; XrdOucBuffer *buffFree; int size; short numbuff; short maxbuff; void Recycle(XrdOucBuffer *bP); BuffSlot() : buffFree(0), size(0), numbuff(0), maxbuff(0) {} ~BuffSlot(); }; BuffSlot *bSlot; int incBsz; int shfBsz; int rndBsz; int maxBsz; int slots; }; /******************************************************************************/ /* X r d O u c B u f f e r */ /******************************************************************************/ class XrdOucBuffer { friend class XrdOucBuffPool; public: //----------------------------------------------------------------------------- //! Get the pointer to the buffer. //! //! @return pointer to the buffer. //----------------------------------------------------------------------------- inline char *Buffer() const {return data;} //----------------------------------------------------------------------------- //! Get the size of the buffer. //! //! @return size of the buffer. //----------------------------------------------------------------------------- inline int BuffSize() const {return size;} //----------------------------------------------------------------------------- //! Produce a clone of this buffer. //! //! @param trim - when true the memory buffer is trimmed to be of //! sufficient size to hold the actual data. Otherwise, the //! cloned memory buffer is of the same length. //! //! @return !0 - pointer to the cloned buffer. //! =0 - insufficient memory to clone the buffer. //----------------------------------------------------------------------------- XrdOucBuffer *Clone(bool trim=true); //----------------------------------------------------------------------------- //! Get a pointer to the data in the buffer. //! //! @return pointer to the data. //----------------------------------------------------------------------------- inline char *Data() const {return data+doff;} //----------------------------------------------------------------------------- //! Get a pointer to the data in the buffer and the length of the data. //! //! @param dataL - place where the length is to be stored. //! //! @return pointer to the data with dataL holding its length. //----------------------------------------------------------------------------- inline char *Data(int &dataL) const {dataL = dlen; return data+doff;} //----------------------------------------------------------------------------- //! Get the data length. //! //! @return The data length. //----------------------------------------------------------------------------- inline int DataLen() {return dlen;} //----------------------------------------------------------------------------- //! Highjack the buffer contents and reinitialize the original buffer. //! //! @param bPsz - the desired size to be given to the highjacked buffer. If //! zero, the current size is used. Same size resictions apply //! as for buffer pool Alloc(), above. //! //! @return !0 - pointer to a usable buffer object which is identical to the //! original buffer. The original buffer was reallocated with //! the specified size. //! @return =0 - insufficient memory to allocate a buffer. //----------------------------------------------------------------------------- XrdOucBuffer *Highjack(int bPsz=0); //----------------------------------------------------------------------------- //! Recycle the buffer. The buffer may be reused in the future. //----------------------------------------------------------------------------- inline void Recycle() {buffPool->bSlot[slot].Recycle(this);} //----------------------------------------------------------------------------- //! Resize the buffer. //! //! @param newsz - the size that the buffer is to have. The same restrictions //! apply as for buffer pool Alloc(), above. //! //! @return true - buffer has been reallocated. //! @return false - insufficient memoy to reallocated the buffer. //----------------------------------------------------------------------------- bool Resize(int newsz); //----------------------------------------------------------------------------- //! Set the data length of offset. //! //! @param dataL - the length of the data. //! @param dataO - the offset of the data in the buffer. //----------------------------------------------------------------------------- inline void SetLen(int dataL, int dataO=0) {dlen = dataL; doff = dataO;} //----------------------------------------------------------------------------- //! Public constructor. You can create one-time buffers not associated with a //! buffer pool via new to associated your own storage area that will be //! freed when the buffer is recycled. This may be handy to pass along such a //! buffer to XrdOucErrInfo in a pinch. A one-time buffer is restricted and //! the Clone(), Highjack() and Resize() methods will always fail. However, //! all the other methods will work in the expected way. //! //! @param buff - pointer to a storage area obtained via posix_memalign() //! and it will be released via free(). //! @param blen - the size of the buffer as well as the data length. //! Use SetLen() to set a new data length if it differs. //----------------------------------------------------------------------------- XrdOucBuffer(char *buff, int blen); private: XrdOucBuffer(XrdOucBuffPool *pP, int snum) : data(0), dlen(0), doff(0), size(pP->bSlot[snum].size), slot(snum), buffPool(pP) {} XrdOucBuffer() : data(0), dlen(0), doff(0), size(0), slot(0), buffPool(0) {} ~XrdOucBuffer() {if (data) free(data);} char *data; int dlen; int doff; int size; int slot; union{XrdOucBuffer *buffNext; XrdOucBuffPool *buffPool; }; }; #endif