How to use attach & detach to access node value of big volume array

Questions regarding the use of the C++ SDK for Server or Client development or integration into customer products ...

Moderator: uasdkcpp

Post Reply
dy_100000
Full Member
Full Member
Posts: 9
Joined: 11 May 2012, 09:53

How to use attach & detach to access node value of big volume array

Post by dy_100000 »

Hello, support team:

I just want to do some statistic job with big size array variable node, so I'd like to use attach & detach in order to avoid data copy. But I’m a little confused because, for example, when I read/write an UaInt16Array from/to a node, the pointer will be passed between UaDataValue, UaVariant and UaInt16Array, and I’m not sure how to combine the attach & detach of each type to avoid the memory leak or double pointer delete.

Here is a simple code from my side:

Step 1: Obtain the data inside the node.

UaVariable* pVariable = (UaVariable*)nodeManager->getNode(nodeId);

If (NULL == pVariable) return;

pVariable->releaseReference();

//Question 1: The following cod seems that pVariable->value(NULL) return a UaDataValue instance by copying the data inside the node, and the assignment operator “=” copies the instance's data to dataValue, so the data is copied for 2 times, is it correct?

UaDataValue dataValue = pVariable->value(NULL);

//Question 2: To avoid double data copy, is it possible to do like this instead of above code?

const OpcUa_DataValue* pDataValue = pVariable->value(NULL).detach(NULL);
UaDataValue dataValue;
dataValue.attach(pDataValue);


Step 2: Obtain value inside the dataValue
UaVairant variant;
variant.attach(dataValue.value());

const OpcUa_Variant* pVariant(variant);

UaInt16Array int16Array;
int16Array.attach(pVariant->Value.Array.Length, pVariant->Value.Array.Value.Int16Array);


Step 3: Post processing after data access,
//Question 3: To give up the ownership of the pointer, I must detach the data, is that correct?
int16Array.detach();
variant.detach();

Thanks a lot.:lol:

User avatar
Support Team
Hero Member
Hero Member
Posts: 3072
Joined: 18 Mar 2011, 15:09

Re:How to use attach & detach to access node value of big volume array

Post by Support Team »

1)
The UaDataValue class uses implicit sharing. So copying the class will just copy the internal pointer to the data and increase the reference counter. The the data is copied only if and when a function writes to it, i.e., copy-on-write. The UaVariant class doesn't use implicit sharing at the moment. We figured out that in almost any case you won't separate the value from the status and timestamps - so you'll always want to keep the UaDataValue as long as your processing is done.

2)
Usually there's no need to do that because of 1).
Note that detach only works if the reference counter is not bigger than 1. Otherwise detach will return 0. So always check the result.

Comment on Step 2:
- UaDataValue::value() just returns a pointer to the OpcUa_Variant structure
- UaVariant::attach takes ownership of the variant structure. So only use if nobody else has ownership of the structure.
That combination will not work. You have 2 classes pointing to the same data if the OpcUa_Variant structure holds non scalar data.

If you want to attach the UaInt16Array to the data you have to make sure that data is not references anymore .i.e. copy the structure before.

The other option and the most efficient one is to access the data directly (assumed you already know that the value is an Uint16Array - otherwise you'll have to check the datatype before).

Code: Select all

const OpcUa_Variant* pVariantStruct = dataValue.value(); // will just copy the pointer

Code: Select all

OpcUa_Int32 size = pVariantStruct->Value.Array.Value.Length; // the size of the array

Code: Select all

OpcUa_UInt16* data =  pVariantStruct->Value.Array.Value.UInt16Array; // pointer to access the data

Code: Select all

// your data processing
....

Code: Select all

// Once you're done you don't have to cleanup anything.

3)

As long as you deal with classes you don't have to think about cleaning up memory. The destructor will take care of that. If you explicitly copy data to a structure using any of the clone or copy methods you have to free that memory.

We're currently working on a version that won't show the ua stack c-structures anymore.
Best regards
Unified Automation Support Team

dy_100000
Full Member
Full Member
Posts: 9
Joined: 11 May 2012, 09:53

Re:How to use attach & detach to access node value of big volume array

Post by dy_100000 »

That's clear. It seems that I make the thing complicated. Thanks a lot.

By the way, there is one more question related with UaDataValue.

In some case, I just want to update the status and time stamp of the node value without any value change.

As you mentioned, the UaVariable::value will return an UaDataValue instance obtaining the internal pointer of the node, does it means that I just need to call UaDataValue::setStatusCode or UaDataValue::setSourceTimestamp?

User avatar
Support Team
Hero Member
Hero Member
Posts: 3072
Joined: 18 Mar 2011, 15:09

Re:How to use attach & detach to access node value of big volume array

Post by Support Team »

As I mentioned above the UaDataValue class has a copy on write strategy. So when you call setStatusCode or setSourceTimestamp that will internally create a new copy of the DataValue and set the StatusCode or timestamp on that new copy.
I'm not sure what your intent is. But look at the class as an object you don't know how it works. For using the class you don't need to know how it works internally. So when you set any data on an instance of that class it won't change anything anywhere else. Having the implicit sharing is just an implementation detail of the class for better performance. Logically that has no effect for using it.
Best regards
Unified Automation Support Team

dy_100000
Full Member
Full Member
Posts: 9
Joined: 11 May 2012, 09:53

Re:How to use attach & detach to access node value of big volume array

Post by dy_100000 »

Ok, I just misunderstood your answer in the beginning, now it is ok.

My intention to write only timestamp of the node is that my UA server will sample periodically the data in PLC, and if the value does not change, I only need to update the source time stamp. But I think that is no more necessary because, as explained in UA specification, the source time stamp is used to indicate the time of last change.

Thanks again.

Post Reply