I tried to use RCF::ByteBuffer to serialize a part of complex structure as below
Trying to simplify the things, so skipping unrelated details
// an entity
class CZoneRule {.... in6_addr v6addr; ...};
// list of the entities
class CZoneRuleList : private std::vector<CZoneRule*>{ }; // actually more complex but can be simplified to the vector<>
// list of the entities + additional data (skipped)
class CZone {.... CZoneRuleList zoneruleslist; ....};
So I had to write the serializers
void serialize(SF::Archive &ar, in6_addr & v6addr)
{
if (ar.isWrite())
{
RCF::ByteBuffer buf((char*)&v6addr,sizeof(v6addr)); // here is my fault
ar & buf;
}
else
{
RCF::ByteBuffer buf;
ar & buf;
// sizeof controlling. skipped
v6addr=*(in6_addr*)buf.getPtr();
}
}
void serialize(SF::Archive &ar, CZoneRule &zonerule) { ar & zonerule.v6addr; }
void serialize(SF::Archive &ar, CZoneRuleList &zonerulelist)
{
if (ar.isWrite())
{
unsigned long cnt=zonerulelist.count(); ar & cnt;
forevery-zone-rule in the zonerulelist // just to hide the unrelated details
{
CZoneRule zr=getZoneRuleFromTheVector();
ar & zr;
}
}
else // deserialization
{
unsigned long cnt=0;
ar & cnt;
for (unsigned long i=0;i<cnt;i++)
{
CZoneRule zr;
ar & zr;
InsertTheZoneRuleToTheList(zr);
}
}
}
void serialize(SF::Archive &ar, CZone &zone) { ar & zone.zoneruleslist; }
You could ask me why I did not serialize the underlying vector<CZoneRule*> as std::vector<> with the native serializer.
The answer is simple - Because of the “protected” access specifier.
The RCF engine just have no required access to the vector and changing to “protected” to public may have negative effects to the main (big enough) project.
On the client side everything worked OK excepting the v6addr structures.
After some thinking I have detected the problem. The problem was in no-copy semantics of RCF::ByteBuffer. As the result the locally defined buffer brought garbage instead of v6addr on the server side.
I have found a workaround
void serialize(SF::Archive &ar, in6_addr & v6addr)
{
for (int i=0;i< sizeof(v6addr.u.Word)/sizeof(v6addr.u.Word[0]);i++)
ar & v6addr.u.Word;
return;
}
So I got rid of RCF::ByteBuffer and started to pass the in6_addr elements word-by-word.
Anyway the problem has been solved.
For now I’m just curious
(a) whether there is a way to force copy for RCF::ByteBuffer
(b) Is there a way to serialize structures of fixed size simply.
I do realize why there is no an automatic way to serialize a random structure at once. The structure may have pointers to independent allocations.
But what if there are no pointers and the structure contains participants allocated directly with the entire structure only.
Have I just missed something important?
Thanks for the feedback,
Konstantin
PS. BTW the the framework is brilliant! No problems at all excepting inspired by myself. Many thanks to Jarl!
RCF::ByteBuffer and copy semantics
Re: RCF::ByteBuffer and copy semantics
Hi Konstantin,
To get ByteBuffer to do a copy, you can do this:
You can serialize fixed size C arrays directly:
, as well as dynamically sized arrays:
If you want to serialize data structures by dumping their memory contents, you need to be sure that there are no pointers in the contents, and also that the client and server have exactly the same memory layout.
Hope that helps.
To get ByteBuffer to do a copy, you can do this:
Code: Select all
// Allocate memory owned by the ByteBuffer.
RCF::ByteBuffer buffer( sizeof(v6addr) );
// Copy to the ByteBuffer
memcpy(buffer.getPtr(), &v6addr, sizeof(v6addr));
// Serialize it.
ar & buffer;
Code: Select all
#include <SF/SerializeStaticArray.hpp>
// ...
char myArray[512] = {0};
ar & myArray;
Code: Select all
#include <SF/SerializeDynamicArray.hpp>
// ...
std::size_t bufSize = 1024;
char * buf = new char[bufSize];
ar & SF::dynamicArray(buf, bufSize);
Hope that helps.
Re: RCF::ByteBuffer and copy semantics
Thank you very much.
I should guess myself about the RCF::ByteBuffer buffer( sizeof(v6addr) ) + memcpy pair, but I did not unfortunately, was just perplexed by the "no-copy semantics" announcement.
Thank you once more,
Konstantin
I should guess myself about the RCF::ByteBuffer buffer( sizeof(v6addr) ) + memcpy pair, but I did not unfortunately, was just perplexed by the "no-copy semantics" announcement.
Thank you once more,
Konstantin