NDArrayPool源代码:
- #include
- #include
- #include
- #include
-
- #include
- #include
- #include
- #include
- #include
-
- #include
-
- #include
-
- #include "asynNDArrayDriver.h"
- #include "NDArray.h"
-
- // 在认为一个NDArray对象太大前,它必须比所需的尺寸大多少。
- #define THRESHOLD_SIZE_RATIO 1.5
-
- static 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
::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对象数目加1
- pArray = 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;
- // 维度数组置0
- memset(pArray->dims, 0, sizeof(pArray->dims));
- for (int i=0; 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
::iterator it; - // 已用内存+dataSiz大于可用最大内存量,需要释放数组
- while (!freeList_.empty() && ((memorySize_ + dataSize) > maxMemory_)) {
- it = freeList_.end(); // 获取末尾的freeListElement对象
- it--;
- freeArray = it->pArray_;
- // 从空闲列表中删除获取的freeListElement对象
- freeList_.erase(it);
- // 内存使用量减少获取的freeListElement对象的dataSize
- memorySize_ -= freeArray->dataSize;
- // NDArray对象数目减少1
- numBuffers_--;
- // 释放获取的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
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--;// 引用次数减少1
- if (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
- *pDataOut++ = (dataTypeOut)(*pDataIn++); // 将输入数组中数据类型转成输出数据中数据类型
- }
- }
-
- //把输入数组数据类型转成输出数组数据类型
- template <typename dataTypeOut> int convertTypeSwitch (NDArray *pIn, NDArray *pOut)
- {
- int status = ND_SUCCESS;
-
- switch(pIn->dataType) {
- case NDInt8:
- convertType
(pIn, pOut); - break;
- case NDUInt8:
- convertType
(pIn, pOut); - break;
- case NDInt16:
- convertType
(pIn, pOut); - break;
- case NDUInt16:
- convertType
(pIn, pOut); - break;
- case NDInt32:
- convertType
(pIn, pOut); - break;
- case NDUInt32:
- convertType
(pIn, pOut); - break;
- case NDInt64:
- convertType
(pIn, pOut); - break;
- case NDUInt64:
- convertType
(pIn, pOut); - break;
- case NDFloat32:
- convertType
(pIn, pOut); - break;
- case NDFloat64:
- convertType
(pIn, pOut); - break;
- default:
- status = ND_ERROR;
- break;
- }
- return(status);
- }
-
- /*
- 1、当输入和输出数组都是一维数组时,dim = 0
- 1 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为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
// 逐个从输入数组中按顺序取数值进行转换放入输出数组数据区 - for (bin=0; bin
- if (dim > 0) {
- convertDim
(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
(pIn, pOut, pDataIn, pDataOut, dim); - break;
- case NDUInt8:
- convertDim
(pIn, pOut, pDataIn, pDataOut, dim); - break;
- case NDInt16:
- convertDim
(pIn, pOut, pDataIn, pDataOut, dim); - break;
- case NDUInt16:
- convertDim
(pIn, pOut, pDataIn, pDataOut, dim); - break;
- case NDInt32:
- convertDim
(pIn, pOut, pDataIn, pDataOut, dim); - break;
- case NDUInt32:
- convertDim
(pIn, pOut, pDataIn, pDataOut, dim); - break;
- case NDInt64:
- convertDim
(pIn, pOut, pDataIn, pDataOut, dim); - break;
- case NDUInt64:
- convertDim
(pIn, pOut, pDataIn, pDataOut, dim); - break;
- case NDFloat32:
- convertDim
(pIn, pOut, pDataIn, pDataOut, dim); - break;
- case NDFloat64:
- convertDim
(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
(pIn, pOut, pDataIn, pDataOut, dim); - break;
- case NDUInt8:
- convertDimensionSwitch
(pIn, pOut, pDataIn, pDataOut, dim); - break;
- case NDInt16:
- convertDimensionSwitch
(pIn, pOut, pDataIn, pDataOut, dim); - break;
- case NDUInt16:
- convertDimensionSwitch
(pIn, pOut, pDataIn, pDataOut, dim); - break;
- case NDInt32:
- convertDimensionSwitch
(pIn, pOut, pDataIn, pDataOut, dim); - break;
- case NDUInt32:
- convertDimensionSwitch
(pIn, pOut, pDataIn, pDataOut, dim); - break;
- case NDInt64:
- convertDimensionSwitch
(pIn, pOut, pDataIn, pDataOut, dim); - break;
- case NDUInt64:
- convertDimensionSwitch
(pIn, pOut, pDataIn, pDataOut, dim); - break;
- case NDFloat32:
- convertDimensionSwitch
(pIn, pOut, pDataIn, pDataOut, dim); - break;
- case NDFloat64:
- convertDimensionSwitch
(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
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
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
(pIn, pOut); - break;
- case NDUInt8:
- convertTypeSwitch
(pIn, pOut); - break;
- case NDInt16:
- convertTypeSwitch
(pIn, pOut); - break;
- case NDUInt16:
- convertTypeSwitch
(pIn, pOut); - break;
- case NDInt32:
- convertTypeSwitch
(pIn, pOut); - break;
- case NDUInt32:
- convertTypeSwitch
(pIn, pOut); - break;
- case NDInt64:
- convertTypeSwitch
(pIn, pOut); - break;
- case NDUInt64:
- convertTypeSwitch
(pIn, pOut); - break;
- case NDFloat32:
- convertTypeSwitch
(pIn, pOut); - break;
- case NDFloat64:
- convertTypeSwitch
(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
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
::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
::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
- #include
- #include
- #include
-
- #include
- #include
- #include
- #include
- #include
-
- #include
-
- #include
-
- #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=0
- memorySize=0, maxMemory=10000
- freeList: (index, dataSize, pArray)
- *************************************************************
- **********************Test NDArrayPool::alloc:***************
- NDArray Information:
-
- NDArray Array address=0x558d2d9090:
- ndims=2 dims=[2 3 ]
- dataType=4, dataSize=24, pData=0x558d2d92d0
- uniqueId=0, timeStamp=0.000000, epicsTS.secPastEpoch=0, epicsTS.nsec=0
- referenceCount=1
- number of attributes=0
-
- NDAttributeList: address=0x558d2d9230:
- number of attributes=0
- NDArrayPool information:
-
- NDArrayPool:
- numBuffers=1, numFree=0
- memorySize=24, maxMemory=10000
- freeList: (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 5
-
- New created pArrayout information:
-
- NDArray Array address=0x558d2d9310:
- ndims=2 dims=[2 3 ]
- dataType=4, dataSize=24, pData=0x558d2d92f0
- uniqueId=0, timeStamp=0.000000, epicsTS.secPastEpoch=0, epicsTS.nsec=0
- referenceCount=1
- number of attributes=0
-
- NDAttributeList: address=0x558d2d94b0:
- number of attributes=0
- NDArrayPool information:
-
- NDArrayPool:
- numBuffers=2, numFree=0
- memorySize=48, maxMemory=10000
- freeList: (index, dataSize, pArray)
- *************************************************************
- **********************Test NDArrayPool::reserve**************
- NDArray Information:
-
- NDArray Array address=0x558d2d9090:
- ndims=2 dims=[2 3 ]
- dataType=4, dataSize=24, pData=0x558d2d92d0
- uniqueId=0, timeStamp=0.000000, epicsTS.secPastEpoch=0, epicsTS.nsec=0
- referenceCount=2
- number of attributes=0
-
- NDAttributeList: address=0x558d2d9230:
- number of attributes=0
- *************************************************************
- **********************Test NDArrayPool:release**************
- New created pArrayout information:
-
- NDArrayPool:
- numBuffers=2, numFree=1
- memorySize=48, maxMemory=10000
- freeList: (index, dataSize, pArray)
- 0 24 0x558d2d9310
- Array 1
-
- NDArray Array address=0x558d2d9310:
- ndims=2 dims=[2 3 ]
- dataType=4, dataSize=24, pData=0x558d2d92f0
- uniqueId=0, timeStamp=0.000000, epicsTS.secPastEpoch=0, epicsTS.nsec=0
- referenceCount=0
- number of attributes=0
-
- NDAttributeList: 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=0x558d2d97f0
- uniqueId=0, timeStamp=0.000000, epicsTS.secPastEpoch=0, epicsTS.nsec=0
- referenceCount=1
- number of attributes=0
-
- NDAttributeList: address=0x558d2d9750:
- number of attributes=0
- *************************************************************
- **********************Use NArrayPool::convert***************
-
- NDArray Array address=0x558d2d9830:
- ndims=2 dims=[3 2 ]
- dataType=9, dataSize=48, pData=0x558d2d9a70
- uniqueId=0, timeStamp=0.000000, epicsTS.secPastEpoch=0, epicsTS.nsec=0
- referenceCount=1
- number of attributes=0
-
- NDAttributeList: 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=1
- memorySize=144, maxMemory=10000
- freeList: (index, dataSize, pArray)
- 0 24 0x558d2d9310
- Array 1
-
- NDArray Array address=0x558d2d9310:
- ndims=2 dims=[2 3 ]
- dataType=4, dataSize=24, pData=0x558d2d92f0
- uniqueId=0, timeStamp=0.000000, epicsTS.secPastEpoch=0, epicsTS.nsec=0
- referenceCount=0
- number of attributes=0
-
- NDAttributeList: address=0x558d2d94b0:
- number of attributes=0
-
相关阅读:
LabVIEW如何修复或重置NI MAX数据库文件
Job 和 DaemonSet
web安全渗透
Facebook的创新实验室:人工智能与新技术探索
热门项目!知识付费小程序源码系统 带完整的安装代码包以及安装部署教程
Java架构师设计思想
【Python】Python环境安装与简单代码运行
在kubernetes中部署kubersphere
【Unity3D】拖尾TrailRenderer
高级Shopify主题开发教程
-
原文地址:https://blog.csdn.net/yuyuyuliang00/article/details/133692126