NDArrayPool源代码解析以及测试程序

编程入门 行业动态 更新时间:2024-10-11 21:25:53

NDArrayPool<a href=https://www.elefans.com/category/jswz/34/1769335.html style=源代码解析以及测试程序"/>

NDArrayPool源代码解析以及测试程序

 NDArrayPool源代码:

#include <string.h>
#include <stdlib.h>
#include <dbDefs.h>
#include <stdint.h>#include <epicsMutex.h>
#include <epicsThread.h>
#include <epicsTime.h>
#include <ellLib.h>
#include <cantProceed.h>#include <asynPortDriver.h>#include <epicsExport.h>#include "asynNDArrayDriver.h"
#include "NDArray.h"// 在认为一个NDArray对象太大前,它必须比所需的尺寸大多少。
#define THRESHOLD_SIZE_RATIO 1.5static const char *driverName = "NDArrayPool";/** eraseNDAttributes是一个控制每次用NDArrayPool->alloc()分配一个新数组时是否调用NDArray::clearAttributes()的全局标记。* 默认值是0,表示clearAttributes()不被调用。这种模式是高效的,因为它节省了大量的分配/接触分配,并且当一旦* 为一个驱动设置了这些属性并且不变化时,这是可以的。如果驱动属性被删除,如果这个标记为0,分配的数组将仍然有这些旧的属性,* 设置这个标记在每次分配一个的NDArray时强制删除属性。*/
volatile int eraseNDAttributes=0;
// 导出这个变量到EPICS IOC
extern "C" {epicsExportAddress(int, eraseNDAttributes);}/** NDArrayPool构造器* [in] pDriver: 指向创建这个对象的asynNDArrayDriver的指针.* [in] maxMemory : 允许这个池使用的最大内存字节量,所有NDArray对象求和,0=无限*/
NDArrayPool::NDArrayPool(class asynNDArrayDriver *pDriver, size_t maxMemory): numBuffers_(0), maxMemory_(maxMemory), memorySize_(0), pDriver_(pDriver)
// 初始化时,NDArray对象数目为0,使用内存字节数为0,可用内存最大字节数为传入的maxMemory
{listLock_ = epicsMutexCreate(); // 创建互斥量
}/** 创建新的NDArray对象。* 这个方法应该被管理派生自NDArray类的对象的池对象重写。*/
NDArray* NDArrayPool::createArray()
{return new NDArray;
}/** 管理派生自NDArray类的对象的池类的hook。* 在新的数组已经被分配后,这个hook被调用。* [in] pArray: 指向分配的NDArray对象的指针 */
void NDArrayPool::onAllocateArray(NDArray *pArray)
{
}/** 管理派生自NDArray类的对象的池类的hook。* 在这个数组已经被保留后,这个hook被调用。* [in] pArray : 指向被保留的NDArray对象的指针*/
void NDArrayPool::onReserveArray(NDArray *pArray)
{
}/** 管理派生自NDArray类的对象的池类的hook。* 在这个数组已经被释放后,这个hook被调用。* [in] pArray:指向被释放的NDArray对象的指针 */
void NDArrayPool::onReleaseArray(NDArray *pArray)
{
}/** 分配一个新的NDArray对象,需要前3个参数.* [in] ndims:这个NDArray中维度数目.* [in] dims :维度的数组,其尺寸必须至少为ndims.* [in] dataType : NDArray的数据类型.* [in] dataSize :为数组数据分配的字节数目 ; 如果0,则alloc将从ndims, * 如果0,则alloc()将从ndims,dims和dataType计算除所需的尺寸。* [in] pData : 指向一个数据缓存的指针;如果NULL,则alloc将分配一个新的数组缓存;如果非0,则认为它指向一个有效缓存。* 如果pData不是NULL,则dataSize必须包含已有数组中实际的字节数目,并且这个数组必须足够大来保存这些数组数据。* alloc()搜索它的空闲列表来查找一个空闲的NDArray缓存。如果不能找到一个空闲的,则它将分配一个新数组* 并且添加它到这个空闲列表。如果分配这个NDArray所需的内存将使得为这个池分配的累积内存超过maxMemory,* 则将返回一个错误。alloc()设置返回的NDArray的引用计数为1.*/
NDArray* NDArrayPool::alloc(int ndims, size_t *dims, NDDataType_t dataType, size_t dataSize, void *pData)
{NDArray *pArray=NULL;NDArrayInfo_t arrayInfo;const char* functionName = "NDArrayPool::alloc:";epicsMutexLock(listLock_);// 计算所需的NDArray尺寸NDArray::computeArrayInfo(ndims, dims, dataType, &arrayInfo); // 根据ndims,dims和dataType获取每个总字节数if (dataSize == 0) {dataSize = arrayInfo.totalBytes;}std::multiset<freeListElement>::iterator pListElement; // freeListElement对象迭代器// 传入的数组数据未空,从空闲列表中获取一个if (!pData) {//  尝试寻找空闲列表中足够大的数组freeListElement testElement(NULL, dataSize);pListElement = freeList_.lower_bound(testElement); // dataSize为下限的迭代器,调用一次返回一个freeListElement对象} else {// 传入的数组数据不为空,则从空闲列表中获取第一个最小的freeListElement对象// dataSize没关系, pData将被替代.pListElement = freeList_.begin();}if (pListElement == freeList_.end()) {/* 我们未找到一个足够大的空闲列表,分配一个新数组 */numBuffers_++; //NDArray对象数目加1pArray = this->createArray();} else {pArray = pListElement->pArray_; //到一个足够大的空闲列表,取出这个NDArray对象if (pData || (pListElement->dataSize_ > (dataSize * THRESHOLD_SIZE_RATIO))) {// 我们找到了一个数组,但它太大。设置这个尺寸为0,因而在下面分配它memorySize_ -= pArray->dataSize;free(pArray->pData);pArray->pData = NULL;}freeList_.erase(pListElement); //空闲列表从删除这个freeListElement对象}/* 初始化字段:设置这个分配这个NDArray对象的NDArrayPool,引用次数,分配这个NDArray的驱动,数组数据类型,数组数据维度数目 */pArray->pNDArrayPool = this;pArray->referenceCount = 1;pArray->pDriver = pDriver_;pArray->dataType = dataType;pArray->ndims = ndims;// 维度数组置0memset(pArray->dims, 0, sizeof(pArray->dims));for (int i=0; i<ndims && i<ND_ARRAY_MAX_DIMS; i++) {pArray->dims[i].size = dims[i];pArray->dims[i].offset = 0;pArray->dims[i].binning = 1;pArray->dims[i].reverse = 0;}/* 如果置位了全局标记,删除这些属性 */if (eraseNDAttributes) pArray->pAttributeList->clear();/* 清除codec */pArray->codec.clear();/* 到此,pArray存在,但pArray->pData可能是NULL *//* 如果调用者传递一个有效缓存,使用那个缓存 */if (pData) {pArray->pData = pData;pArray->dataSize = dataSize;memorySize_ += dataSize;} else if (pArray->pData == NULL) {if ((maxMemory_ > 0) && ((memorySize_ + dataSize) > maxMemory_)) {/** 我们没有分配这个数组的足够内存,看我们是否能通过删除数组获取内存* 首先删除最大的数组,及从freeList_末尾开始。       */NDArray *freeArray;std::multiset<freeListElement>::iterator it;// 已用内存+dataSiz大于可用最大内存量,需要释放数组while (!freeList_.empty() && ((memorySize_ + dataSize) > maxMemory_)) {it = freeList_.end(); // 获取末尾的freeListElement对象it--;freeArray = it->pArray_;// 从空闲列表中删除获取的freeListElement对象freeList_.erase(it);// 内存使用量减少获取的freeListElement对象的dataSizememorySize_ -= freeArray->dataSize;// NDArray对象数目减少1numBuffers_--;// 释放获取的freeListElement对象delete freeArray;}}// 如果最大可用内存量有限制并且已用内存量+dataSize大于最大可用内存量if ((maxMemory_ > 0) && ((memorySize_ + dataSize) > maxMemory_)) {asynPrint(pDriver_->pasynUserSelf, ASYN_TRACE_ERROR,"%s: error: reached limit of %ld memory (%d buffers)\n",functionName, (long)maxMemory_, numBuffers_);} else {pArray->pData = malloc(dataSize); // 分配数组数据区if (pArray->pData) {//分配成功,设置NDArray的dataSize和pArray->dataSize = dataSize; pArray->compressedSize = dataSize;memorySize_ += dataSize; // 内存使用量增加dataSize}}}// 如果我们没有一个有效内存缓存,设置pArray为NULL来表示错误if (pArray && (pArray->pData == NULL)) {delete pArray;numBuffers_--;pArray = NULL;}// 调用分配hook(用于管理派生自NDArray类的对象的池)onAllocateArray(pArray);epicsMutexUnlock(listLock_);return (pArray);
}/** 这个方法复制一个NDArray对象。* [in] pIn :要被复制的输入数组.* [in] pOut:将被复制到的输出数组;可以是NULL或者一个指向一个已有NDArray的指针。* [in] copyData:如果这个标记为true,则包括数组数据的所有东西都被复制。如果0, 复制除了数据外(包括属性)的所有东西。* [in] copyDimensions :如果这个标记为true, 则即使pOut不为NULL,也复制这些维度;默认为true* [in] copyDataType:如果这个标记为true, 即使pOut不为NULL,也复制dataType, 默认为true* 返回:返回一个指向输出数组的指针** 如果pOut为NULL,首先分配它。如果输出数组对象已经存在(pOut!=NULL),则必须已经分配足够空间给它来保存数据。*/
NDArray* NDArrayPool::copy(NDArray *pIn, NDArray *pOut, bool copyData, bool copyDimensions, bool copyDataType)
{//const char *functionName = "copy";size_t dimSizeOut[ND_ARRAY_MAX_DIMS];int i;size_t numCopy;NDArrayInfo arrayInfo;/*  如果输出数组不存在,则创建它 */if (!pOut) {for (i=0; i<pIn->ndims; i++) dimSizeOut[i] = pIn->dims[i].size; // 从输入数组的每个维度获取输出数组每个维度尺寸pOut = this->alloc(pIn->ndims, dimSizeOut, pIn->dataType, 0, NULL); // 数据类型使用输入数组的数据类型,dataSize取0,则alloc自行计算if(NULL==pOut) return NULL;}// 复制uniqueId, timeStamp,epicsTS pOut->uniqueId = pIn->uniqueId;pOut->timeStamp = pIn->timeStamp;pOut->epicsTS = pIn->epicsTS;// 如果copyDimensions为true,则复制维度数目以及每个维度上的尺寸if (copyDimensions) {pOut->ndims = pIn->ndims;memcpy(pOut->dims, pIn->dims, sizeof(pIn->dims));}// 如果copyDataType为true,则复制数据类型if (copyDataType) {pOut->dataType = pIn->dataType;}// 复制编码算法名pOut->codec.name = pIn->codec.name;// 复制压缩后的尺寸pOut->compressedSize = pIn->compressedSize;// 如果copyData为true,if (copyData) { // pIn->getInfo(&arrayInfo);numCopy = pIn->codec.empty() ? arrayInfo.totalBytes : pIn->compressedSize; // codec.empty()为true,表示没有使用压缩算法if (pOut->dataSize < numCopy) numCopy = pOut->dataSize; //需要复制的数据量取数组数据尺寸和输入数组尺寸中的小者memcpy(pOut->pData, pIn->pData, numCopy); // 将输入数组中数据区中数据复制到输出数组中数据区}pOut->pAttributeList->clear(); // 清除输出数组中属性列表中所有属性pIn->pAttributeList->copy(pOut->pAttributeList); // 将输入数组中属性列表中所有属性复制到输出数组的属性列表中return(pOut);
}/** 这个方法增加这个NDArray对象的引用次数。* [in] pArray :对这个数组增加引用计数.* 当一个NDArray被放到一个队列为了之后处理,插件必须调用reserve()。*/
int NDArrayPool::reserve(NDArray *pArray)
{const char *functionName = "reserve";/* Make sure we own this array 确认我们拥有这个数组 */if (pArray->pNDArrayPool != this) {// 这个NDArray对象不是这个NDArrayPool对象分配的asynPrint(pDriver_->pasynUserSelf, ASYN_TRACE_ERROR,"%s::%s: ERROR, not owner!  owner=%p, should be this=%p\n",driverName, functionName, pArray->pNDArrayPool, this);return(ND_ERROR);}//asynPrint(pDriver_->pasynUserSelf, ASYN_TRACE_FLOW,//  "NDArrayPool::reserve pArray=%p, count=%d\n", pArray, pArray->referenceCount);epicsMutexLock(listLock_);// 如果引用次数少于1,则出问题了,这个NDArray已经被释放了if (pArray->referenceCount < 1) {cantProceed("%s:reserve ERROR, reference count = %d, should be >= 1, pArray=%p\n",driverName, pArray->referenceCount, pArray);}pArray->referenceCount++; // 传入NDArray对象的引用次数加1// 调用保留hook(用于管理派生自NDArray类的对象的池)onReserveArray(pArray);epicsMutexUnlock(listLock_);return ND_SUCCESS;
}/** 这个方法减小对NDArray对象的引用次数。* [in] pArray :对这个数组减少引用次数* 当引用次数到达0,NDArray被放回空闲列表。* 当一个NDArray被从队列移除并且对其处理结束时,插件必须调用release()。* 在调用所有插件后,驱动必须调用release()。*/
int NDArrayPool::release(NDArray *pArray)
{const char *functionName = "release";/* 确认我们拥有这个数组 */if (pArray->pNDArrayPool != this) {asynPrint(pDriver_->pasynUserSelf, ASYN_TRACE_ERROR,"%s::%s: ERROR, not owner!  owner=%p, should be this=%p\n",driverName, functionName, pArray->pNDArrayPool, this);return(ND_ERROR);}//asynPrint(pDriver_->pasynUserSelf, ASYN_TRACE_FLOW,//  "NDArrayPool::release pArray=%p, count=%d\n", pArray, pArray->referenceCount);epicsMutexLock(listLock_);pArray->referenceCount--;// 引用次数减少1if (pArray->referenceCount == 0) {// 引用次数为0/* The last user has released this image, add it back to the free list 最后的用户释放这个图像,添加它到空闲列表*/freeListElement listElement(pArray, pArray->dataSize);freeList_.insert(listElement);}if (pArray->referenceCount < 0) {cantProceed("%s:release ERROR, reference count < 0 pArray=%p\n",driverName, pArray);}// 调用释放释放hook(用于管理派生自NDArray类的池)onReleaseArray(pArray);epicsMutexUnlock(listLock_);return ND_SUCCESS;
}// 输入数组数据类型和输出数组数据类型之间的转换
template <typename dataTypeIn, typename dataTypeOut> void convertType(NDArray *pIn, NDArray *pOut)
{size_t i;dataTypeIn *pDataIn = (dataTypeIn *)pIn->pData; // 输入数组的数据区dataTypeOut *pDataOut = (dataTypeOut *)pOut->pData; // 输出数组的数据区NDArrayInfo_t arrayInfo;pOut->getInfo(&arrayInfo);for (i=0; i<arrayInfo.nElements; i++) {*pDataOut++ = (dataTypeOut)(*pDataIn++); // 将输入数组中数据类型转成输出数据中数据类型}
}//把输入数组数据类型转成输出数组数据类型
template <typename dataTypeOut> int convertTypeSwitch (NDArray *pIn, NDArray *pOut)
{int status = ND_SUCCESS;switch(pIn->dataType) {case NDInt8:convertType<epicsInt8, dataTypeOut> (pIn, pOut);break;case NDUInt8:convertType<epicsUInt8, dataTypeOut> (pIn, pOut);break;case NDInt16:convertType<epicsInt16, dataTypeOut> (pIn, pOut);break;case NDUInt16:convertType<epicsUInt16, dataTypeOut> (pIn, pOut);break;case NDInt32:convertType<epicsInt32, dataTypeOut> (pIn, pOut);break;case NDUInt32:convertType<epicsUInt32, dataTypeOut> (pIn, pOut);break;case NDInt64:convertType<epicsInt64, dataTypeOut> (pIn, pOut);break;case NDUInt64:convertType<epicsUInt64, dataTypeOut> (pIn, pOut);break;case NDFloat32:convertType<epicsFloat32, dataTypeOut> (pIn, pOut);break;case NDFloat64:convertType<epicsFloat64, dataTypeOut> (pIn, pOut);break;default:status = ND_ERROR;break;}return(status);
}/*1、当输入和输出数组都是一维数组时,dim = 01 2 3 4 5 6  => 1 2 3
*/
template <typename dataTypeIn, typename dataTypeOut> void convertDim(NDArray *pIn, NDArray *pOut,void *pDataIn, void *pDataOut, int dim)
{dataTypeOut *pDOut = (dataTypeOut *)pDataOut; // 输出数组数据区dataTypeIn *pDIn = (dataTypeIn *)pDataIn;     // 输入数组数据区/*size_t size;   size_t offset;                int binning;   int reverse;
*/ NDDimension_t *pOutDims = pOut->dims; // 输出数组的维度数组NDDimension_t *pInDims = pIn->dims;    //输入数组的维度数组size_t inStep, outStep, inOffset;int inDir;int i, bin;size_t inc, in, out;inStep = 1;outStep = 1;inDir = 1;inOffset = pOutDims[dim].offset;for (i=0; i<dim; i++) {// 以dim为1为例子,inStep是输入数组元素数目,outStep是输出数组元素数目inStep  *= pInDims[i].size;outStep *= pOutDims[i].size;}if (pOutDims[dim].reverse) {// 如果输出数组是反向的,输入数组中要取的最后一个元素的偏移inOffset += pOutDims[dim].size * pOutDims[dim].binning - 1;inDir = -1; // 表示输入数组反向取}inc = inDir * inStep;    // 步长pDIn += inOffset*inStep; // 输入数组数据区取值起始位置for (in=0, out=0; out<pOutDims[dim].size; out++, in++) { // 逐个从输入数组中按顺序取数值进行转换放入输出数组数据区for (bin=0; bin<pOutDims[dim].binning; bin++) {if (dim > 0) {convertDim <dataTypeIn, dataTypeOut> (pIn, pOut, pDIn, pDOut, dim-1);} else {*pDOut += (dataTypeOut)*pDIn;}pDIn += inc;}pDOut += outStep;}
}// 
template <typename dataTypeOut> int convertDimensionSwitch(NDArray *pIn, NDArray *pOut,void *pDataIn, void *pDataOut, int dim)
{int status = ND_SUCCESS;switch(pIn->dataType) {case NDInt8:convertDim <epicsInt8, dataTypeOut> (pIn, pOut, pDataIn, pDataOut, dim);break;case NDUInt8:convertDim <epicsUInt8, dataTypeOut> (pIn, pOut, pDataIn, pDataOut, dim);break;case NDInt16:convertDim <epicsInt16, dataTypeOut> (pIn, pOut, pDataIn, pDataOut, dim);break;case NDUInt16:convertDim <epicsUInt16, dataTypeOut> (pIn, pOut, pDataIn, pDataOut, dim);break;case NDInt32:convertDim <epicsInt32, dataTypeOut> (pIn, pOut, pDataIn, pDataOut, dim);break;case NDUInt32:convertDim <epicsUInt32, dataTypeOut> (pIn, pOut, pDataIn, pDataOut, dim);break;case NDInt64:convertDim <epicsInt64, dataTypeOut> (pIn, pOut, pDataIn, pDataOut, dim);break;case NDUInt64:convertDim <epicsUInt64, dataTypeOut> (pIn, pOut, pDataIn, pDataOut, dim);break;case NDFloat32:convertDim <epicsFloat32, dataTypeOut> (pIn, pOut, pDataIn, pDataOut, dim);break;case NDFloat64:convertDim <epicsFloat64, dataTypeOut> (pIn, pOut, pDataIn, pDataOut, dim);break;default:status = ND_ERROR;break;}return(status);
}static int convertDimension(NDArray *pIn,NDArray *pOut,void *pDataIn,void *pDataOut,int dim)
{int status = ND_SUCCESS;/* 这个例程被传递:* 一个指向输入数据起始位置的指针:* 一个指向输出数据起始位置的指针* 一个维度的数组* 维度索引*/switch(pOut->dataType) {case NDInt8:convertDimensionSwitch <epicsInt8>(pIn, pOut, pDataIn, pDataOut, dim);break;case NDUInt8:convertDimensionSwitch <epicsUInt8> (pIn, pOut, pDataIn, pDataOut, dim);break;case NDInt16:convertDimensionSwitch <epicsInt16> (pIn, pOut, pDataIn, pDataOut, dim);break;case NDUInt16:convertDimensionSwitch <epicsUInt16> (pIn, pOut, pDataIn, pDataOut, dim);break;case NDInt32:convertDimensionSwitch <epicsInt32> (pIn, pOut, pDataIn, pDataOut, dim);break;case NDUInt32:convertDimensionSwitch <epicsUInt32> (pIn, pOut, pDataIn, pDataOut, dim);break;case NDInt64:convertDimensionSwitch <epicsInt64> (pIn, pOut, pDataIn, pDataOut, dim);break;case NDUInt64:convertDimensionSwitch <epicsUInt64> (pIn, pOut, pDataIn, pDataOut, dim);break;case NDFloat32:convertDimensionSwitch <epicsFloat32> (pIn, pOut, pDataIn, pDataOut, dim);break;case NDFloat64:convertDimensionSwitch <epicsFloat64> (pIn, pOut, pDataIn, pDataOut, dim);break;default:status = ND_ERROR;break;}return(status);
}/**  从一个输入NDArray创建一个新的输出NDArray,执行转换操作。* 这个函数形式用于仅更改数据类型,不是维度,维度被保留。* [in] pIn :输入数组,转换的来源.* [out] ppOut : 输出数组,转换结果。* [in] dataTypeOut :输出数组的数据类型*/
int NDArrayPool::convert(NDArray *pIn,NDArray **ppOut,NDDataType_t dataTypeOut){NDDimension_t dims[ND_ARRAY_MAX_DIMS];int i;// 输出数组的维度与输入数组的维度一样for (i=0; i<pIn->ndims; i++) {dims[i].size  = pIn->dims[i].size;dims[i].offset  = 0;dims[i].binning = 1;dims[i].reverse = 0;}return this->convert(pIn, ppOut, dataTypeOut, dims);
}/** 从一个输入NDArray创建一个新的输出NDArray,执行转换操作。* 如果dataTypeout不同于pIn->dataType,转换可以更改数据类型。* 它也可以更改维度,outDims其每个维度可以有与输入数组维度(pIn->dims)不同的size,binning,offset和reverse的值。* * [in] pIn :这个输入数组,转换的来源.* [out]ppOut:输出数组,转换的结果 * [in] dataTypeOut:输出数组的数据类型 * [in] dimsOut :输出数组的维度.*/
int NDArrayPool::convert(NDArray *pIn,NDArray **ppOut,NDDataType_t dataTypeOut,NDDimension_t *dimsOut)
{int dimsUnchanged;size_t dimSizeOut[ND_ARRAY_MAX_DIMS];NDDimension_t dimsOutCopy[ND_ARRAY_MAX_DIMS];int i;NDArray *pOut;NDArrayInfo_t arrayInfo;NDAttribute *pAttribute;int colorMode, colorModeMono = NDColorModeMono;const char *functionName = "convert";/* 初始化出错 */*ppOut = NULL;/* 不能转换被压缩的数据 */if (!pIn->codec.empty()) {fprintf(stderr, "%s:%s: can't convert compressed data [%s]\n",driverName, functionName, pIn->codec.name.c_str());return ND_ERROR;}/*  因为我们需要修改它,但我们不要影响调用者,复制输入维度数组 */memcpy(dimsOutCopy, dimsOut, pIn->ndims*sizeof(NDDimension_t)); // 维度数由输入数组的维度数决定/* 计算输出数组的维度  */dimsUnchanged = 1;for (i=0; i<pIn->ndims; i++) {dimsOutCopy[i].size = dimsOutCopy[i].size/dimsOutCopy[i].binning; // 输出数组每个维度的尺寸if (dimsOutCopy[i].size <= 0) {asynPrint(pDriver_->pasynUserSelf, ASYN_TRACE_ERROR,"%s:%s: ERROR, invalid output dimension, size=%d, binning=%d\n",driverName, functionName, (int)dimsOut[i].size, dimsOut[i].binning);return(ND_ERROR);}dimSizeOut[i] = dimsOutCopy[i].size; // 存储输出数组每一维度的尺寸的数组if ((pIn->dims[i].size  != dimsOutCopy[i].size) || // 只要满足输出数组每个维度上尺寸与输入输入对那个维度不同(dimsOutCopy[i].offset != 0) || // 或者输出数组每个维度上有偏移量或者有binning或者反向了,则输出维度就发生了变化(dimsOutCopy[i].binning != 1) ||(dimsOutCopy[i].reverse != 0)) dimsUnchanged = 0;}/*  我们知道了输出数组的数据类型和维度,分配它 */pOut = alloc(pIn->ndims, dimSizeOut, dataTypeOut, 0, NULL);*ppOut = pOut;if (!pOut) {asynPrint(pDriver_->pasynUserSelf, ASYN_TRACE_ERROR,"%s:%s: ERROR, cannot allocate output array\n",driverName, functionName);return(ND_ERROR);}/*从输入NDArray对象复制字段到输出NDArray对象  */pOut->timeStamp = pIn->timeStamp;pOut->epicsTS = pIn->epicsTS;pOut->uniqueId = pIn->uniqueId;/*  用传递给这个函数的那些维度结构体替换输出NDArray中的dims中存储的维度结构体 */memcpy(pOut->dims, dimsOutCopy, pIn->ndims*sizeof(NDDimension_t));pIn->pAttributeList->copy(pOut->pAttributeList);pOut->getInfo(&arrayInfo);if (dimsUnchanged) {if (pIn->dataType == pOut->dataType) {/** 维度相同并且数据类型相同,则仅复制输入图像到输出图像。*/memcpy(pOut->pData, pIn->pData, arrayInfo.totalBytes);return ND_SUCCESS;} else {/* 我们需要转换数据类型 */switch(pOut->dataType) {// 根据输出NDArray中数据类型,将输入NDArray中数据转成输出NDArray中数据类型case NDInt8:convertTypeSwitch <epicsInt8> (pIn, pOut);break;case NDUInt8:convertTypeSwitch <epicsUInt8> (pIn, pOut);break;case NDInt16:convertTypeSwitch <epicsInt16> (pIn, pOut);break;case NDUInt16:convertTypeSwitch <epicsUInt16> (pIn, pOut);break;case NDInt32:convertTypeSwitch <epicsInt32> (pIn, pOut);break;case NDUInt32:convertTypeSwitch <epicsUInt32> (pIn, pOut);break;case NDInt64:convertTypeSwitch <epicsInt64> (pIn, pOut);break;case NDUInt64:convertTypeSwitch <epicsUInt64> (pIn, pOut);break;case NDFloat32:convertTypeSwitch <epicsFloat32> (pIn, pOut);break;case NDFloat64:convertTypeSwitch <epicsFloat64> (pIn, pOut);break;default://status = ND_ERROR;break;}}} else {/* 对整个输出NDArray的数据清零 */memset(pOut->pData, 0, arrayInfo.totalBytes);convertDimension(pIn, pOut, pIn->pData, pOut->pData, pIn->ndims-1);}/*  设置输出数组中的字段 */for (i=0; i<pIn->ndims; i++) {pOut->dims[i].offset = pIn->dims[i].offset + dimsOutCopy[i].offset;pOut->dims[i].binning = pIn->dims[i].binning * dimsOutCopy[i].binning;if (pIn->dims[i].reverse) pOut->dims[i].reverse = !pOut->dims[i].reverse;}/* * 如果帧是RGBx帧,并且我们折叠那个维度,则更改颜色模式*/pAttribute = pOut->pAttributeList->find("ColorMode");if (pAttribute && pAttribute->getValue(NDAttrInt32, &colorMode)) {if      ((colorMode == NDColorModeRGB1) && (pOut->dims[0].size != 3))pAttribute->setValue(&colorModeMono);else if ((colorMode == NDColorModeRGB2) && (pOut->dims[1].size != 3))pAttribute->setValue(&colorModeMono);else if ((colorMode == NDColorModeRGB3) && (pOut->dims[2].size != 3))pAttribute->setValue(&colorModeMono);}return ND_SUCCESS;
}/** 返回这个对象当分配的缓存数目 */
int NDArrayPool::getNumBuffers()
{return numBuffers_;
}/**  0=unlimited 返回允许这个对象分配的最大内存字节 */
size_t NDArrayPool::getMaxMemory()
{return maxMemory_;
}/**  返回这个对象当前已经分配的内存字节数 */
size_t NDArrayPool::getMemorySize()
{return memorySize_;
}/** 返回空闲列表中NDArray对象的数目  */
int NDArrayPool::getNumFree()
{epicsMutexLock(listLock_);int size = (int)freeList_.size();epicsMutexUnlock(listLock_);return size;
}/**  删除空闲列表中所有NDArrays */
void NDArrayPool::emptyFreeList()
{NDArray *freeArray;std::multiset<freeListElement>::iterator it; // 获取freeListElement对象的迭代器epicsMutexLock(listLock_);while (!freeList_.empty()) { it = freeList_.begin(); // 获取第一个freeListElement对象freeArray = it->pArray_; // 获取NDArray对象freeList_.erase(it);  // 从空闲列表中删除memorySize_ -= freeArray->dataSize;numBuffers_--;delete freeArray;}epicsMutexUnlock(listLock_);
}/** 报告NDArrayPool空闲列表尺寸和其它性质。* [in] fp : 报告输出的文件指针* [in] details : 所要报告的详细程度,当前什么也没做.*/
int NDArrayPool::report(FILE *fp, int details)
{fprintf(fp, "\n");fprintf(fp, "NDArrayPool:\n");fprintf(fp, "  numBuffers=%d, numFree=%d\n",numBuffers_, this->getNumFree()); // 缓存数量,还可分配的内存fprintf(fp, "  memorySize=%ld, maxMemory=%ld\n",(long)memorySize_, (long)maxMemory_); //已用内存数,最大内存分配数量if (details > 5) { // 每个NDArray的信息:NDArray序号,NDArray数据区的尺寸,以及NDArray的地址int i;std::multiset<freeListElement>::iterator it;NDArray *freeArray;fprintf(fp, "  freeList: (index, dataSize, pArray)\n");epicsMutexLock(listLock_);for (it=freeList_.begin(),i=0; it!=freeList_.end(); ++it,i++) {fprintf(fp, "    %d %d %p\n", i, (int)it->dataSize_, it->pArray_);}// 每个NDArray的详细信息: NDArray对象的地址 DArray对象的维度数目  // NDArray对象每个维度的元素数目  数据类型,数据尺寸,数据地址 唯一id,时间戳 引用计数 属性数目 每个属性信息if (details > 10) {for (it=freeList_.begin(); it!=freeList_.end(); ++it) {freeArray = it->pArray_;fprintf(fp, "    Array %d\n", i);freeArray->report(fp, details);}}epicsMutexUnlock(listLock_);}return ND_SUCCESS;
}

NDArrayPool类中方法的测试:

#include <string.h>
#include <stdlib.h>
#include <dbDefs.h>
#include <stdint.h>#include <epicsMutex.h>
#include <epicsThread.h>
#include <epicsTime.h>
#include <ellLib.h>
#include <cantProceed.h>#include <asynPortDriver.h>#include <epicsExport.h>#include "asynNDArrayDriver.h"
#include "NDArray.h"int main()
{// NDArrayPool::NDArrayPool(class asynNDArrayDriver *pDriver, size_t maxMemory)printf("***********Test NDArrayPool construct:*********************\n");NDArrayPool * pPool = new NDArrayPool(NULL, 10000);printf("NDArrayPool information:\n");pPool->report(stdout, 11);printf("*************************************************************\n");printf("**********************Test NDArrayPool::alloc:***************\n");size_t dims[2] = {2,3};int ndims = 2;NDArray * pArray = pPool->alloc(ndims, dims, NDInt32, 0, NULL);printf("NDArray Information:\n");pArray->report(stdout, 11);printf("NDArrayPool information:\n");pPool->report(stdout , 11);printf("*************************************************************\n");printf("********************Test NDArrayPool::copy:*****************\n");NDArrayInfo_t info;pArray->getInfo(&info);size_t i;size_t j;printf("Set Value for pArray:\n");epicsInt32* pArr = (epicsInt32 *)pArray->pData;for (i = 0; i < info.nElements; i++){pArr[i] = i;}printf("copy a new NDArray from pArray:\n");NDArray * pArrayout = pPool->copy(pArray, NULL, true, true, true);pArrayout->getInfo(&info);pArr = (epicsInt32 *)pArrayout->pData;printf("xDim = %d, yDim = %d, xSize = %lu, ySize = %lu\n", info.xDim, info.yDim, info.xSize, info.ySize);printf("output the values from the new NDArray:\n");for (i = 0; i < info.ySize; i++){for (j = 0; j < info.xSize; j++){printf("%d\t", pArr[i * info.xSize + j]);}printf("\n");}printf("\n");printf("New created pArrayout information:\n");pArrayout->report(stdout, 11);printf("NDArrayPool information:\n");pPool->report(stdout ,11);printf("*************************************************************\n");printf("**********************Test NDArrayPool::reserve**************\n");pPool->reserve(pArray);printf("NDArray Information:\n");pArray->report(stdout, 11);printf("*************************************************************\n");printf("**********************Test NDArrayPool:release**************\n");printf("New created pArrayout information:\n");pPool->release(pArrayout);pPool->report(stdout ,11);printf("*************************************************************\n");printf("Use NDArrayPool::alloc to allocate a new NDArray:*************\n");dims[0] = 3;dims[1] = 2;printf("NDArrayPool Information:\n");NDArray * pArrayOut = pPool->alloc(ndims, dims, NDFloat64, 0, NULL);pArrayOut->report(stdout, 11);printf("*************************************************************\n");printf("**********************Use NArrayPool::convert***************\n");NDArray * pnewNDArray = NULL;//int NDArrayPool::convert(NDArray *pIn, NDArray **ppOut, NDDataType_t dataTypeOut, NDDimension_t *dimsOut)pPool->convert(pArray, &pnewNDArray, NDFloat64, pArrayOut->dims);pnewNDArray->report(stdout, 11);epicsFloat64 * pf64 = (epicsFloat64 *)pnewNDArray->pData;pnewNDArray->getInfo(&info);printf("xDim = %d, yDim = %d, xSize = %lu, ySize = %lu\n", info.xDim, info.yDim, info.xSize, info.ySize);for (i = 0; i < info.ySize; i++){for (j = 0; j < info.xSize; j++){printf("%f\t", pf64[j + info.xSize * i]);}printf("\n");}printf("*************************************************************\n");pPool->report(stdout, 11);return 0;
}

测试结果如下:

orangepi@orangepi5:~/C_program/host_program/hostApp$ O.linux-aarch64/testNDArrayPool
***********Test NDArrayPool construct:*********************
NDArrayPool information:NDArrayPool:numBuffers=0, numFree=0memorySize=0, maxMemory=10000freeList: (index, dataSize, pArray)
*************************************************************
**********************Test NDArrayPool::alloc:***************
NDArray Information:NDArray  Array address=0x558d2d9090:ndims=2 dims=[2 3 ]dataType=4, dataSize=24, pData=0x558d2d92d0uniqueId=0, timeStamp=0.000000, epicsTS.secPastEpoch=0, epicsTS.nsec=0referenceCount=1number of attributes=0NDAttributeList: address=0x558d2d9230:number of attributes=0
NDArrayPool information:NDArrayPool:numBuffers=1, numFree=0memorySize=24, maxMemory=10000freeList: (index, dataSize, pArray)
*************************************************************
********************Test NDArrayPool::copy:*****************
Set Value for pArray:
copy a new NDArray from pArray:
xDim = 0, yDim = 1, xSize = 2, ySize = 3
output the values from the new NDArray:
0       1
2       3
4       5New created pArrayout information:NDArray  Array address=0x558d2d9310:ndims=2 dims=[2 3 ]dataType=4, dataSize=24, pData=0x558d2d92f0uniqueId=0, timeStamp=0.000000, epicsTS.secPastEpoch=0, epicsTS.nsec=0referenceCount=1number of attributes=0NDAttributeList: address=0x558d2d94b0:number of attributes=0
NDArrayPool information:NDArrayPool:numBuffers=2, numFree=0memorySize=48, maxMemory=10000freeList: (index, dataSize, pArray)
*************************************************************
**********************Test NDArrayPool::reserve**************
NDArray Information:NDArray  Array address=0x558d2d9090:ndims=2 dims=[2 3 ]dataType=4, dataSize=24, pData=0x558d2d92d0uniqueId=0, timeStamp=0.000000, epicsTS.secPastEpoch=0, epicsTS.nsec=0referenceCount=2number of attributes=0NDAttributeList: address=0x558d2d9230:number of attributes=0
*************************************************************
**********************Test NDArrayPool:release**************
New created pArrayout information:NDArrayPool:numBuffers=2, numFree=1memorySize=48, maxMemory=10000freeList: (index, dataSize, pArray)0 24 0x558d2d9310Array 1NDArray  Array address=0x558d2d9310:ndims=2 dims=[2 3 ]dataType=4, dataSize=24, pData=0x558d2d92f0uniqueId=0, timeStamp=0.000000, epicsTS.secPastEpoch=0, epicsTS.nsec=0referenceCount=0number of attributes=0NDAttributeList: address=0x558d2d94b0:number of attributes=0
*************************************************************
Use NDArrayPool::alloc to allocate a new NDArray:*************
NDArrayPool Information:NDArray  Array address=0x558d2d95b0:ndims=2 dims=[3 2 ]dataType=9, dataSize=48, pData=0x558d2d97f0uniqueId=0, timeStamp=0.000000, epicsTS.secPastEpoch=0, epicsTS.nsec=0referenceCount=1number of attributes=0NDAttributeList: address=0x558d2d9750:number of attributes=0
*************************************************************
**********************Use NArrayPool::convert***************NDArray  Array address=0x558d2d9830:ndims=2 dims=[3 2 ]dataType=9, dataSize=48, pData=0x558d2d9a70uniqueId=0, timeStamp=0.000000, epicsTS.secPastEpoch=0, epicsTS.nsec=0referenceCount=1number of attributes=0NDAttributeList: address=0x558d2d99d0:number of attributes=0
xDim = 0, yDim = 1, xSize = 3, ySize = 2
0.000000        1.000000        2.000000
2.000000        3.000000        4.000000
*************************************************************NDArrayPool:numBuffers=4, numFree=1memorySize=144, maxMemory=10000freeList: (index, dataSize, pArray)0 24 0x558d2d9310Array 1NDArray  Array address=0x558d2d9310:ndims=2 dims=[2 3 ]dataType=4, dataSize=24, pData=0x558d2d92f0uniqueId=0, timeStamp=0.000000, epicsTS.secPastEpoch=0, epicsTS.nsec=0referenceCount=0number of attributes=0NDAttributeList: address=0x558d2d94b0:number of attributes=0

更多推荐

NDArrayPool源代码解析以及测试程序

本文发布于:2023-12-04 09:27:58,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1660479.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:源代码   测试   程序   NDArrayPool

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!