Different behaviour between old and new streamer

Good morning everyone.
I have been experimenting a bit with ROOT’s IO system and I tried implementing a streamer for a class on my own. For that I tried copying what rootcling generates when it finds a ClassDef macro, as it’s the easiest to follow. I am able to serialize the class properly, and I can deserialize it if I let rootcling generate the streamer by itself. I then tried adding a ‘+’ in the LinkDef.h entry for the class, switching to the StreamerInfo assisted streamer. I expected the two to be equal, but it seems that in case of an STL member in the class (a vector or a map, for example) the new streamer is unable to properly read the file. Is this the intended behaviour?

The fact that I’m experimenting might just mean that the file is broken beyond repairs, so that could be the reason for the failure. I’m asking because I was able to read it in one case, but not in the other.

This is the class I’m doing my test on. testClass.h (387 Bytes)
The LinkDef is simply the pragmas for the test class and the map.
My streamer is exactly what rootcling would write, just generated another way.

I’m using ROOT version 6.11, compiled from the git repository, and Ubuntu 16.04 with gcc 5.4.

Thanks in advance.

Elusian

I think @pcanal will be able to give you a proper answer…

Yes, somewhat. The old streamer implementation does not stream all STL collection correctly and the format was changed. Being able to read old and new file requires a blend of old and new streamer code.

For that I tried copying what rootcling generates when it finds a ClassDef macro, as it’s the easiest to follow.

Yes, but it is much more limited in features. Beside the already mentioned STL defect, it also prevent splitting of your class and leave the file to not be ‘self-describing’ per se.

and I tried implementing a streamer for a class on my own.

What is your end goal? There is nowadays only a few case where you would need to. For example customization is now better handle via IO customization read rules.

Cheers,
Philippe.

I see. Since I suppose I should follow the newer format, might I ask for info about it? I do think the related functions are located in the file io/io/src/TStreamerInfoActions.cxx, but I have troubles following it. What is, for example, the difference between MemberWise and ObjectWise streaming?

It’s ok, I expected that, after all right now I’m trying to generate the streamer as a function, so I can’t expect the object to be split.

The goal is to be able to use ROOT’s IO for a kind of structure I can’t feed to rootcling, but for which I have nonetheless enough information to generate a streamer function (and other things that usually rootcling takes care of, such as for example contructors and destructors TClass methods), but not a StreamerInfo to use the new system on. I wanted to see if I managed to adapt what I have to the framework. What I’m doing might just not be supported, though.

Thanks

Elusian

Memberwise vs Objectwise are two different way of streaming the element of a collection. Objectwise, we stream each element of the collection entirely one after the other. Memberwise we stream each member of the class/struct for all element of the collection at ‘once’. So for collection containing a struct { X, Y }; In ObjectWise we stream in the order X0, Y0, X1, Y1, etc. (this ignore some metadata). While MemberWise we stream in the X0, X1, …, then Y0, Y1, … etc.

a kind of structure I can’t feed to rootcling,

Why not?

but for which I have nonetheless enough information to …

Then you probably have enough information to generate a POD version of the struct/class that can be parsed by Cling (at run-time) and be enough to generate the proper StreamerInfo [you would still need a dictionary for the collection it uses]

Cheers,
Philippe.

I see, thanks.

I don’t. What I have is a function that deals with the class, to which I can teach what it means to write a basic type, mapping to the TBuffer’s basic functions, or a complex type like a collection, imitating what ROOT does in that case.

Thanks for the help, I’ll look more in TStreamerInfoActions to understand what happens exactly.

Elusian

I am a bit intrigued in the even bigger picture :slight_smile: What is the context in which this function is called? What is the flow? What is preventing from having a complete view of the ‘member’ of the ‘class’?

Thanks,
Philippe.

It really is a StreamerFunc, a different take on StreamerFunc generated another way. It’s generic on what actually does the reading/writing, like TBuffer is through its concrete implementations, which is how I manage to sneak the TBuffer interface inside.

It’s not that I can’t, it’s that it isn’t what I’m trying to do. The code that generates that function is not mine and there are people using it. I’m just the one that noticed the similarity and is trying to glue the two approaches together by adding a compatibility layer. For this reason, any additional parsing would pretty much vanify my efforts. I was aware that I wouldn’t be able to gain the benefits of a StreamerInfo, but I can at least try to emulate the old system.

Elusian

It’s not that I can’t, it’s that it isn’t what I’m trying to do. The code that generates that function is not mine …

Fair enough …

I wouldn’t be able to gain the benefits of a StreamerInfo, but I can at least try to emulate the old system.

You may want to take a look at TStreamerInfoReadBuffer.cxx and TStreamerInfoWriteBuffer.cxx.
which are probably simpler to read than StreamerInfoActions.cxx,

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.