diff --git a/silecs-communication-cpp/src/silecs-communication/interface/equipment/CNVBlock.cpp b/silecs-communication-cpp/src/silecs-communication/interface/equipment/CNVBlock.cpp index e5a09d2f8351f12295f9b87d8c9e99cf766446e9..e99d17e2ea4ee3ac86ea21e6268aacf6cdcc96f5 100644 --- a/silecs-communication-cpp/src/silecs-communication/interface/equipment/CNVBlock.cpp +++ b/silecs-communication-cpp/src/silecs-communication/interface/equipment/CNVBlock.cpp @@ -14,6 +14,16 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. #ifdef NI_SUPPORT_ENABLED +/* +Copyright (c) 2017 European Organization for Nuclear Research (CERN). +All rights reserved. This program and the accompanying materials +are made available under the terms of the GNU Public License v3.0 +which accompanies this distribution, and is available at +http://www.gnu.org/licenses/gpl.html + +Contributors: + European Organization for Nuclear Research (CERN) - initial API and implementation +*/ #include <silecs-communication/interface/equipment/SilecsCluster.h> #include <silecs-communication/interface/equipment/SilecsDevice.h> #include <silecs-communication/interface/utility/Thread.h> @@ -33,327 +43,365 @@ namespace Silecs { - /* Check for errors */ - void CNVBlock::errChk(int code) +/* Check for errors */ +void CNVBlock::errChk(int code) +{ + if (code != 0) { - if(code != 0) - { - LOG(DEBUG) << "CNV Exception raised: " << std::string(CNVGetErrorDescription(code)); - throw SilecsException(__FILE__, __LINE__, CNV_INTERNAL_ERROR, std::string(CNVGetErrorDescription(code))+" in block "+ name_); - } + LOG(DEBUG) << "CNV Exception raised: " << std::string(CNVGetErrorDescription(code)); + throw SilecsException(__FILE__, __LINE__, CNV_INTERNAL_ERROR, std::string(CNVGetErrorDescription(code)) + " in block " + name_); } +} - //------------------------------------------------------------------------------------------- - //------ CNVBlock - //------------------------------------------------------------------------------------------- +//------------------------------------------------------------------------------------------- +//------ CNVBlock +//------------------------------------------------------------------------------------------- - CNVBlock::CNVBlock(PLC* thePLC, ElementXML* pDesignEl, AccessType accessType, AccessArea accessArea, std::vector<ElementXML*>* pDesignBlockRegisterElCol): - Block(thePLC, pDesignEl, accessType, accessArea, pDesignBlockRegisterElCol) - { - // associate buffer pointer with created buffer - pBuffer_ = (CNVData*)& buffer_; - } +CNVBlock::CNVBlock(PLC* thePLC, ElementXML* pDesignEl, AccessType accessType, AccessArea accessArea, std::vector<ElementXML*>* pDesignBlockRegisterElCol) : + Block(thePLC, pDesignEl, accessType, accessArea, pDesignBlockRegisterElCol) +{ + // associate buffer pointer with created buffer + pBuffer_ = (CNVData*)&buffer_; +} - CNVBlock::~CNVBlock() - { - } +CNVBlock::~CNVBlock() +{ +} - //------------------------------------------------------------------------------------------- - //------ CNVInputBlock - //------------------------------------------------------------------------------------------- +//------------------------------------------------------------------------------------------- +//------ CNVInputBlock +//------------------------------------------------------------------------------------------- - CNVInputBlock::CNVInputBlock(PLC* thePLC, ElementXML* pDesignEl, AccessType accessType, AccessArea accessArea, std::vector<ElementXML*>* pDesignBlockRegisterElCol) : - CNVBlock(thePLC, pDesignEl, accessType, accessArea, pDesignBlockRegisterElCol) - { - if (DEBUG & Log::topics_) LOG(ALLOC) << "Block (create): " << name_ << ", CNV: " << getPLC()->getName() << ", access: Input" << ", hasMaster: " << (hasMasterRegister() ? "yes" : "no") << ", hasSlave: " << (hasSlaveRegister() ? "yes" : "no") << ", address: " << address_ << ", mem-size: " << memSize_; //<< ", buffer-size: " << bufferSize_; +CNVInputBlock::CNVInputBlock(PLC* thePLC, ElementXML* pDesignEl, AccessType accessType, AccessArea accessArea, std::vector<ElementXML*>* pDesignBlockRegisterElCol) : + CNVBlock(thePLC, pDesignEl, accessType, accessArea, pDesignBlockRegisterElCol) +{ + if (DEBUG & Log::topics_) + LOG(ALLOC) << "Block (create): " << name_ << ", CNV: " << getPLC()->getName() << ", access: Input" << ", hasMaster: " << (hasMasterRegister() ? "yes" : "no") << ", hasSlave: " << (hasSlaveRegister() ? "yes" : "no") << ", address: " << address_ << ", mem-size: " << memSize_; //<< ", buffer-size: " << bufferSize_; - handle_ = NULL; - subscriptionFlag_ = false; + handle_ = NULL; + subscriptionFlag_ = false; - // Creates receive task which relies on the block exchange - if (getPLC()->getProtocolModeID() == BlockMode) + // Creates receive task which relies on the block exchange + if (getPLC()->getProtocolModeID() == BlockMode) pAction_ = new CNVRecvBlockMode(this, name_ + "_" + getPLC()->getName()); - else + else pAction_ = new CNVRecvDeviceMode(this, name_ + "_" + getPLC()->getName()); - WrapperAction wrapperAction(pAction_); - pTask_ = new Task<WrapperAction>(WrapperAction::function, wrapperAction); - } + WrapperAction wrapperAction(pAction_); + pTask_ = new Task<WrapperAction>(WrapperAction::function, wrapperAction); +} - CNVInputBlock::~CNVInputBlock() - { - } +CNVInputBlock::~CNVInputBlock() +{ +} - bool CNVInputBlock::doSubscribe() +bool CNVInputBlock::doSubscribe() +{ + if (!subscriptionFlag_) { - if(!subscriptionFlag_) - { - LOG(ALLOC) << "CNVInputBlock::doSubscribe (create-buffer):" << name_ << std::endl; + LOG(ALLOC) << "CNVInputBlock::doSubscribe (create-buffer):" << name_ << std::endl; - int numberOfDevice = static_cast<int>(thePLC_->getDeviceMap().size()); - handle_ = (CNVBufferedSubscriber*)calloc(numberOfDevice,sizeof(CNVBufferedSubscriber)); + int numberOfDevice = static_cast<int>(thePLC_->getDeviceMap().size()); + handle_ = (CNVBufferedSubscriber*)calloc(numberOfDevice, sizeof(CNVBufferedSubscriber)); - subscriptionFlag_ = true; //subscription is fine a priori + subscriptionFlag_ = true; //subscription is fine a priori - deviceVectorType::iterator pDeviceIter; - int i=0; - for(pDeviceIter = thePLC_->getDeviceMap().begin(); pDeviceIter != thePLC_->getDeviceMap().end(); ++pDeviceIter) - { + deviceVectorType::iterator pDeviceIter; + int i = 0; + for (pDeviceIter = thePLC_->getDeviceMap().begin(); pDeviceIter != thePLC_->getDeviceMap().end(); ++pDeviceIter) + { - std::string blockAddress = "\\\\"+thePLC_->getName()+"\\'" - +thePLC_->theCluster_->getClassName()+"-"+thePLC_->theCluster_->getClassVersion()+"'\\" - + pDeviceIter->second->getLabel()+"\\"+name_; + std::string blockAddress = "\\\\" + thePLC_->getName() + "\\'" + thePLC_->theCluster_->getClassName() + "-" + thePLC_->theCluster_->getClassVersion() + "'\\" + pDeviceIter->second->getLabel() + "\\" + name_; - LOG(DEBUG) << "doSubscribe(): Subscribing to address: " << blockAddress; + LOG(DEBUG) << "doSubscribe(): Subscribing to address: " << blockAddress; - int code = CNVCreateBufferedSubscriber(blockAddress.c_str(), 0 , 0, 2, (int)CNVWaitForever, 0, &handle_[i]); + int code = CNVCreateBufferedSubscriber(blockAddress.c_str(), 0, 0, 2, (int)CNVWaitForever, 0, &handle_[i]); - if(code != 0) - { LOG(DEBUG) << "doSubscribe(): CNV Exception raised: " << std::string(CNVGetErrorDescription(code)); - unSubscribe(); //dispose subscription resources if any and update subscriptionFlag_ - break; - } - i++; + if (code != 0) + { + LOG(DEBUG) << "doSubscribe(): CNV Exception raised: " << std::string(CNVGetErrorDescription(code)); + unSubscribe(); //dispose subscription resources if any and update subscriptionFlag_ + break; } + i++; } - return subscriptionFlag_; } + return subscriptionFlag_; +} - void CNVInputBlock::unSubscribe() +void CNVInputBlock::unSubscribe() +{ + if (handle_ != NULL) { - if(handle_!=NULL) - { - LOG(ALLOC) << "CNVInputBlock::unSubscribe (dispose):" << name_ << std::endl; + LOG(ALLOC) << "CNVInputBlock::unSubscribe (dispose):" << name_ << std::endl; - for(unsigned int i=0; i<thePLC_->getDeviceMap().size(); i++) + for (unsigned int i = 0; i < thePLC_->getDeviceMap().size(); i++) + { + int code = CNVDispose(handle_[i]); + if (code != 0) { - int code = CNVDispose(handle_[i]); - if(code != 0) - { LOG(DEBUG) << "unSubscribe(): CNV Exception raised: " << std::string(CNVGetErrorDescription(code)); - break; - } + LOG(DEBUG) << "unSubscribe(): CNV Exception raised: " << std::string(CNVGetErrorDescription(code)); + break; } - free(handle_); - handle_ = NULL; - subscriptionFlag_ = false; } + free(handle_); + handle_ = NULL; + subscriptionFlag_ = false; } +} - CNVBufferedSubscriber* CNVInputBlock::getHandle(std::string deviceName) +CNVBufferedSubscriber* CNVInputBlock::getHandle(std::string deviceName) +{ + int i = 0; + deviceVectorType::iterator pDeviceIter; + for (pDeviceIter = thePLC_->getDeviceMap().begin(); pDeviceIter != thePLC_->getDeviceMap().end(); ++pDeviceIter) { - int i=0; - deviceVectorType::iterator pDeviceIter; - for(pDeviceIter = thePLC_->getDeviceMap().begin(); pDeviceIter != thePLC_->getDeviceMap().end(); ++pDeviceIter) - { - if(pDeviceIter->second->getLabel()==deviceName) + if (pDeviceIter->second->getLabel() == deviceName) return &handle_[i]; - i++; - } - return NULL; + i++; } + return NULL; +} - //------------------------------------------------------------------------------------------- - //------ CNVOutputBlock - //------------------------------------------------------------------------------------------- - void CNVOutputBlock::createDataValue(Silecs::Register* regRef, CNVData* builderRef) - { - if(regRef->isScalar()) - { // allocate space for a scalar - switch(regRef->getFormat()) +//------------------------------------------------------------------------------------------- +//------ CNVOutputBlock +//------------------------------------------------------------------------------------------- +void CNVOutputBlock::createDataValue(Silecs::Register* regRef, CNVData* builderRef) +{ + if (regRef->isScalar()) + { // allocate space for a scalar + switch (regRef->getFormat()) + { + /* type Buffer element CNVType DefaultValue*/ + case uInt8: + { + errChk(CNVCreateScalarDataValue(builderRef, CNVUInt8, 0)); + break; + } + case Int8: + { + errChk(CNVCreateScalarDataValue(builderRef, CNVInt8, 0)); + break; + } + case uInt16: + { + errChk(CNVCreateScalarDataValue(builderRef, CNVUInt16, 0)); + break; + } + case Int16: { - /* type Buffer element CNVType DefaultValue*/ - case uInt8: - { errChk(CNVCreateScalarDataValue(builderRef, CNVUInt8, 0 )); break;} - case Int8: - { errChk(CNVCreateScalarDataValue(builderRef, CNVInt8, 0 )); break;} - case uInt16: - { errChk(CNVCreateScalarDataValue(builderRef, CNVUInt16, 0 )); break;} - case Int16: - { errChk(CNVCreateScalarDataValue(builderRef, CNVInt16, 0 )); break;} - case uInt32: - { errChk(CNVCreateScalarDataValue(builderRef, CNVUInt32, 0 )); break;} - case Int32: - { errChk(CNVCreateScalarDataValue(builderRef, CNVInt32, 0 )); break;} - case uInt64: - { errChk(CNVCreateScalarDataValue(builderRef, CNVUInt64, 0 )); break;} - case Int64: - { errChk(CNVCreateScalarDataValue(builderRef, CNVInt64, 0 )); break;} - case Float32: - { errChk(CNVCreateScalarDataValue(builderRef, CNVSingle, 0 )); break;} - case Float64: - { errChk(CNVCreateScalarDataValue(builderRef, CNVDouble, 0 )); break;} + errChk(CNVCreateScalarDataValue(builderRef, CNVInt16, 0)); + break; + } + case uInt32: + { + errChk(CNVCreateScalarDataValue(builderRef, CNVUInt32, 0)); + break; + } + case Int32: + { + errChk(CNVCreateScalarDataValue(builderRef, CNVInt32, 0)); + break; + } + case uInt64: + { + errChk(CNVCreateScalarDataValue(builderRef, CNVUInt64, 0)); + break; + } + case Int64: + { + errChk(CNVCreateScalarDataValue(builderRef, CNVInt64, 0)); + break; + } + case Float32: + { + errChk(CNVCreateScalarDataValue(builderRef, CNVSingle, 0)); + break; + } + case Float64: + { + errChk(CNVCreateScalarDataValue(builderRef, CNVDouble, 0)); + break; + } // CNV does not support date. Double is used instead - case Date: - { errChk(CNVCreateScalarDataValue(builderRef, CNVDouble, 0 )); break;} - case String: - { errChk(CNVCreateScalarDataValue(builderRef, CNVString, "" )); break;} + case Date: + { + errChk(CNVCreateScalarDataValue(builderRef, CNVDouble, 0)); + break; + } + case String: + { + errChk(CNVCreateScalarDataValue(builderRef, CNVString, "")); + break; } } - else - { //allocate space for an array (up to 2 dimensions) - long unsigned int dimension[2]; - dimension[0] = regRef->getDimension1(); - dimension[1] = regRef->getDimension2(); - long unsigned int flatDimension = dimension[0] * dimension[1]; - void* array = NULL; - - switch(regRef->getFormat()) + } + else + { //allocate space for an array (up to 2 dimensions) + long unsigned int dimension[2]; + dimension[0] = regRef->getDimension1(); + dimension[1] = regRef->getDimension2(); + long unsigned int flatDimension = dimension[0] * dimension[1]; + void* array = NULL; + + switch (regRef->getFormat()) + { + /* type Buffer element CNVType array? Dimensions*/ + case uInt8: + { + array = (uint8_t*)calloc(flatDimension, sizeof(uint8_t)); + errChk(CNVCreateArrayDataValue(builderRef, CNVInt8, array, 2, dimension)); + break; + } + case Int8: + { + array = (int8_t*)calloc(flatDimension, sizeof(int8_t)); + errChk(CNVCreateArrayDataValue(builderRef, CNVUInt8, array, 2, dimension)); + break; + } + case uInt16: + { + array = (uint16_t*)calloc(flatDimension, sizeof(uint16_t)); + errChk(CNVCreateArrayDataValue(builderRef, CNVUInt16, array, 2, dimension)); + break; + } + case Int16: + { + array = (int16_t*)calloc(flatDimension, sizeof(int16_t)); + errChk(CNVCreateArrayDataValue(builderRef, CNVInt16, array, 2, dimension)); + break; + } + case uInt32: + { + array = (uint32_t*)calloc(flatDimension, sizeof(uint32_t)); + errChk(CNVCreateArrayDataValue(builderRef, CNVUInt32, array, 2, dimension)); + break; + } + case Int32: + { + array = (int32_t*)calloc(flatDimension, sizeof(int32_t)); + errChk(CNVCreateArrayDataValue(builderRef, CNVInt32, array, 2, dimension)); + break; + } + case uInt64: + { + array = (uint64_t*)calloc(flatDimension, sizeof(uint64_t)); + errChk(CNVCreateArrayDataValue(builderRef, CNVUInt64, array, 2, dimension)); + break; + } + case Int64: + { + array = (int64_t*)calloc(flatDimension, sizeof(int64_t)); + errChk(CNVCreateArrayDataValue(builderRef, CNVInt64, array, 2, dimension)); + break; + } + case Float32: + { + array = (float*)calloc(flatDimension, sizeof(float)); + errChk(CNVCreateArrayDataValue(builderRef, CNVSingle, array, 2, dimension)); + break; + } + case Float64: { - /* type Buffer element CNVType array? Dimensions*/ - case uInt8: - { - array = (uint8_t*)calloc(flatDimension,sizeof(uint8_t)); - errChk(CNVCreateArrayDataValue(builderRef, CNVInt8, array ,2 , dimension)); - break; - } - case Int8: - { - array = (int8_t*)calloc(flatDimension,sizeof(int8_t)); - errChk(CNVCreateArrayDataValue(builderRef, CNVUInt8, array ,2 , dimension)); - break; - } - case uInt16: - { - array = (uint16_t*)calloc(flatDimension,sizeof(uint16_t)); - errChk(CNVCreateArrayDataValue(builderRef, CNVUInt16, array ,2 , dimension)); - break; - } - case Int16: - { - array = (int16_t*)calloc(flatDimension,sizeof(int16_t)); - errChk(CNVCreateArrayDataValue(builderRef, CNVInt16, array ,2 , dimension)); - break; - } - case uInt32: - { - array = (uint32_t*)calloc(flatDimension,sizeof(uint32_t)); - errChk(CNVCreateArrayDataValue(builderRef, CNVUInt32, array ,2 , dimension)); - break; - } - case Int32: - { - array = (int32_t*)calloc(flatDimension,sizeof(int32_t)); - errChk(CNVCreateArrayDataValue(builderRef, CNVInt32, array ,2 , dimension)); - break; - } - case uInt64: - { - array = (uint64_t*)calloc(flatDimension,sizeof(uint64_t)); - errChk(CNVCreateArrayDataValue(builderRef, CNVUInt64, array ,2 , dimension)); - break; - } - case Int64: - { - array = (int64_t*)calloc(flatDimension,sizeof(int64_t)); - errChk(CNVCreateArrayDataValue(builderRef, CNVInt64,array ,2 , dimension)); - break; - } - case Float32: - { - array = (float*)calloc(flatDimension,sizeof(float)); - errChk(CNVCreateArrayDataValue(builderRef, CNVSingle, array ,2 , dimension)); - break; - } - case Float64: - { - array = (double*)calloc(flatDimension,sizeof(double)); - errChk(CNVCreateArrayDataValue(builderRef, CNVDouble, array ,2 , dimension)); - break; - } - case Date: - { - array = (double*)calloc(flatDimension,sizeof(double)); - errChk(CNVCreateArrayDataValue(builderRef, CNVDouble, array ,2 , dimension)); - break; - } - case String: - { - array = (char*)calloc(flatDimension,sizeof(char*)); - errChk(CNVCreateArrayDataValue(builderRef, CNVString, array ,2 , dimension)); - break; - } + array = (double*)calloc(flatDimension, sizeof(double)); + errChk(CNVCreateArrayDataValue(builderRef, CNVDouble, array, 2, dimension)); + break; + } + case Date: + { + array = (double*)calloc(flatDimension, sizeof(double)); + errChk(CNVCreateArrayDataValue(builderRef, CNVDouble, array, 2, dimension)); + break; + } + case String: + { + array = (char*)calloc(flatDimension, sizeof(char*)); + errChk(CNVCreateArrayDataValue(builderRef, CNVString, array, 2, dimension)); + break; } - free(array); } + free(array); } +} - CNVOutputBlock::CNVOutputBlock(PLC* thePLC, ElementXML* pDesignEl, AccessType accessType, AccessArea accessArea, std::vector<ElementXML*>* pDesignBlockRegisterElCol) : - CNVBlock(thePLC, pDesignEl, accessType, accessArea, pDesignBlockRegisterElCol) - { - if (DEBUG & Log::topics_) LOG(ALLOC) << "Block (create): " << name_ << ", CNV: " << getPLC()->getName() << ", access: Output" << ", hasMaster: " << (hasMasterRegister() ? "yes" : "no") << ", hasSlave: " << (hasSlaveRegister() ? "yes" : "no") << ", address: " << address_ << ", mem-size: " << memSize_; // << ", buffer-size: " << bufferSize_; - - /* ALLOCATE THE BUFFER */ - deviceVectorType deviceCol = thePLC->getDeviceMap(); - Device* currentDev = deviceCol[0].second; - std::vector<Register*> regCol = currentDev->getRegisterCollection(name_); - - //Allocate the CNVStruct for the buffer - int numberOfReg = static_cast<int>(regCol.size()); - CNVData *structBuilder = (CNVData*)calloc(numberOfReg,sizeof(CNVData));//allocate space for number of register in the block +CNVOutputBlock::CNVOutputBlock(PLC* thePLC, ElementXML* pDesignEl, AccessType accessType, AccessArea accessArea, std::vector<ElementXML*>* pDesignBlockRegisterElCol) : + CNVBlock(thePLC, pDesignEl, accessType, accessArea, pDesignBlockRegisterElCol) +{ + if (DEBUG & Log::topics_) + LOG(ALLOC) << "Block (create): " << name_ << ", CNV: " << getPLC()->getName() << ", access: Output" << ", hasMaster: " << (hasMasterRegister() ? "yes" : "no") << ", hasSlave: " << (hasSlaveRegister() ? "yes" : "no") << ", address: " << address_ << ", mem-size: " << memSize_; // << ", buffer-size: " << bufferSize_; - // Creates send task which relies on the block exchange - if (getPLC()->getProtocolModeID() == BlockMode) - { - // ALLOCATE A OUTPUT BLOCK IN BLOCK MODE - int numberOfDevice = static_cast<int>(thePLC->getDeviceMap().size()); + /* ALLOCATE THE BUFFER */ + deviceVectorType deviceCol = thePLC->getDeviceMap(); + Device* currentDev = deviceCol[0].second; + std::vector<Register*> regCol = currentDev->getRegisterCollection(name_); - CNVData *arrayBuilder = (CNVData*)calloc(numberOfDevice,sizeof(CNVData)*numberOfReg);//allocate space for number of device in the device array + //Allocate the CNVStruct for the buffer + int numberOfReg = static_cast<int>(regCol.size()); + CNVData *structBuilder = (CNVData*)calloc(numberOfReg, sizeof(CNVData)); //allocate space for number of register in the block - for(int j=0;j<numberOfDevice;j++) - { - // for each register in the current block - for(int i=0;i<numberOfReg;i++) - { - createDataValue(regCol[i], &structBuilder[i]); - } - - errChk(CNVCreateStructDataValue (&arrayBuilder[j], // data handler - structBuilder,// input structure - numberOfReg));// number of fields - } - - long unsigned int dimensions[1] = - { numberOfDevice}; - errChk(CNVCreateArrayDataValue (&buffer_, // data handler - CNVStruct,// array type - arrayBuilder,// input array - 1,// mono-dimensional array - dimensions));// array length + // Creates send task which relies on the block exchange + if (getPLC()->getProtocolModeID() == BlockMode) + { + // ALLOCATE A OUTPUT BLOCK IN BLOCK MODE + int numberOfDevice = static_cast<int>(thePLC->getDeviceMap().size()); - pAction_ = new CNVSendBlockMode(this, name_ + "_" + getPLC()->getName()); + CNVData *arrayBuilder = (CNVData*)calloc(numberOfDevice, sizeof(CNVData) * numberOfReg); //allocate space for number of device in the device array - free(arrayBuilder); - } - else + for (int j = 0; j < numberOfDevice; j++) { - // ALLOCATE A OUTPUT BLOCK IN DEVICE MODE // for each register in the current block - for(int i=0;i<numberOfReg;i++) + for (int i = 0; i < numberOfReg; i++) { createDataValue(regCol[i], &structBuilder[i]); } - errChk(CNVCreateStructDataValue (&buffer_, // data handler - structBuilder,// input structure - numberOfReg));// number of fields - pAction_ = new CNVSendDeviceMode(this, name_ + "_" + getPLC()->getName()); + errChk(CNVCreateStructDataValue(&arrayBuilder[j], // data handler + structBuilder, // input structure + numberOfReg)); // number of fields } - for(int i=0;i<numberOfReg;i++) // TO check if works - CNVDisposeData(structBuilder[i]); + long unsigned int dimensions[1] = {static_cast<long unsigned int>(numberOfDevice)}; + errChk(CNVCreateArrayDataValue(&buffer_, // data handler + CNVStruct, // array type + arrayBuilder, // input array + 1, // mono-dimensional array + dimensions)); // array length - free(structBuilder); + pAction_ = new CNVSendBlockMode(this, name_ + "_" + getPLC()->getName()); - WrapperAction wrapperAction(pAction_); - pTask_ = new Task<WrapperAction>(WrapperAction::function, wrapperAction); + free(arrayBuilder); } - - CNVOutputBlock::~CNVOutputBlock() + else { - if (DEBUG & Log::topics_) LOG(ALLOC) << "CNVOutputBlock (delete): " << name_; + // ALLOCATE A OUTPUT BLOCK IN DEVICE MODE + // for each register in the current block + for (int i = 0; i < numberOfReg; i++) + { + createDataValue(regCol[i], &structBuilder[i]); + } + errChk(CNVCreateStructDataValue(&buffer_, // data handler + structBuilder, // input structure + numberOfReg)); // number of fields - CNVDisposeData(*((CNVData*)pBuffer_)); + pAction_ = new CNVSendDeviceMode(this, name_ + "_" + getPLC()->getName()); } + + for (int i = 0; i < numberOfReg; i++) // TO check if works + CNVDisposeData(structBuilder[i]); + + free(structBuilder); + + WrapperAction wrapperAction(pAction_); + pTask_ = new Task<WrapperAction>(WrapperAction::function, wrapperAction); +} + +CNVOutputBlock::~CNVOutputBlock() +{ + if (DEBUG & Log::topics_) + LOG(ALLOC) << "CNVOutputBlock (delete): " << name_; + + CNVDisposeData(* ((CNVData*)pBuffer_)); +} } #endif //NI_SUPPORT_ENABLED diff --git a/silecs-communication-cpp/src/silecs-communication/interface/utility/Thread.h b/silecs-communication-cpp/src/silecs-communication/interface/utility/Thread.h index 2a7d93c6da488b6c5b1e4ca589b99c477c0020ef..c3c49365844bba41f6560ee841d9e6ae361d0fee 100644 --- a/silecs-communication-cpp/src/silecs-communication/interface/utility/Thread.h +++ b/silecs-communication-cpp/src/silecs-communication/interface/utility/Thread.h @@ -236,13 +236,12 @@ void Thread<UserDataType>::schedule(Task<UserDataType> *pt, Context* pContext) template<typename UserDataType> Thread<UserDataType>::~Thread() { - int err; pThreadCompletion_->lock(); // To protect the endThread_ condition variable endThread_ = true; // Thread shall stop on the next loop pThreadCompletion_->signal(); // Wake-up the thread to execute this referred task pThreadCompletion_->unlock(); - err = pthread_join(*pTid_, NULL); // Wait for thread end before continuing clean-up + pthread_join(*pTid_, NULL); // Wait for thread end before continuing clean-up delete pTaskCompletion_; delete pThreadCompletion_;