Click here to Skip to main content
15,875,017 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I would like to serialize and deserialize the undo queue. I have a base class for transactions. All of the subclasses are listed by their base class in the m_undo deque. I want to be able to call the specialized input/output functions from the base class. I can do this easily for writing out by using a virtual function in the base and overriding it in the subclasses and then cast the passed transaction pointer parameter to its subclass.

But I can't see an easy solution for reading in. One solution I can think of is to do like my consultant taught me (along with some fussing on my own) for my document's factory serialization.

1. Global Serialize and Deserialize functions for implementing everything below
2. An extern SerializeMap that maps an element pointer to a bool (true) and an extern DeserializeMap that maps an element pointer to its id. The maps are global.
3. An "entry" class (global) to house a static deserialize funtion map that maps a registering class name to a pointer to the registering class' deserialize function, and a constructor that initializes the static deserialize function map
4. A declaration macro that embeds an instance of the entry class statically into registering classes and also declares a static deserialize function. It also has inline virtual istream and ostream functions.
5. A definition macro that initializes the static entry class of the registering class with the registering class' name mapped to the address of its deserialize funtion. Finally the definition for the deserialize function magically expands the registering class' name so that at run time it can create a new instance of the subclass. The function takes an id parameter that can then be assigned to by the new object in the map. The instance is then read in.

It's neat that the macro can take a class name variable like a string, stringize it with operator #, and then when the macro is expanded the name appears and acts as the class name in the code of all the subclasses that use the macro. Then we write out and read in the name as in xml and add a "C" to it and find it in the function map to call the correct deserialize function.

I think I might be able to leave out the identifier part from above for the transactions since all of the transactions would be different. We use it in the doc element version because some elements are pointed to by many different things.

One major concern is that if I added the new factory, I'd be introducing two new static maps, and they'd be serializing objects within them that rely on the doc factory with its two static maps. It worries me but maybe it would be OK since all of the registering and initialization happens at compile time and then the usage of them happens at run time. Or would you suggest just subclassing the transaction as a doc element and adding them to the factory already in place; should a transaction be a doc object?

Another problem is that I'd have to put all of the definition macros in one place, in one .ccp file, after the definition of the static function map since I haven't found a better way to do it to enforce the initialization order correctly. Since there will be hundreds if not thousands of transactions, it doesn't seem great.

My question is, is there a better, simpler, and safer way to to this, read in varying subclassed objects (diverse transactions) objects from a list of their base class (transaction)?

Another solution I can think of is to have a switch that handles the name read in and then casts the transaction appropriately but that doesn't sound like much fun but maybe it is better after all.

Have any good tricks for this? Can't wait.
Posted
Updated 15-Oct-10 23:03pm
v2
Comments
Alain Rist 16-Oct-10 5:19am    
Did you consider the boost Serialization library ?http://www.boost.org/doc/libs/1_44_0/libs/serialization/doc/index.html
Brian Bennett 18-Oct-10 2:04am    
Thanks for pointing that out, I hadn't known about it. After reading the documentation I have enough questions about it that I'm hesitant to try it, questions about mixing use with iostream (since all of my document objects are already implemented that way), using with shared_ptr, and using with .NET 7.0.

1 solution

Hi Brian,

IMHO using Boost Serialization[^] should be simpler and easier to maintain than a home cooked solution, with not much more initial investment.

I don't foresee any problem with std::iostream as the boost::serialization::archive classes use them internally.

The current (1.44) library does not know about C++0x std::shared_ptr, but the source for serializing boost::shared_ptr is not that difficult to transpose to a custom std::shared_ptr serialization.

cheers,
AR
 
Share this answer
 
Comments
Brian Bennett 20-Oct-10 6:49am    
I agree with your answer. But I had already started with a home-spun pluggable factory and now it's working. It's a very simple pattern and I've decided that I probably won't try to templatize it on the basis that it won't be used much and it will make the code more readable and usable. It'll be easier to copy it and change a key word if I need to use it again.

This has been par for this project, using home-spun patterns, for instance I'm using my own shared pointers. I wonder if not using boost would have any advantages. I understand the high value of stl and boost code but sometimes I wonder if just having a very simple pattern, highly adapted for a certain implementation, even generic, would be a better way to go. One advantage is that there's no extra code and another is that the style is homogeneous. I'd love to learn more.
Alain Rist 20-Oct-10 7:25am    
All that is up to you, and if relevant your manager :)

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900