Contents
A Templated C++ Attribute Library for Object Persistence and Export
 
 
Printer-Friendly VersionPrinter-Friendly Version
 
Latest News
spacer View All spacer
 
November 22, 2009
 
Video Game Watchdog National Institute On Media And The Family Shutting Down [11]
 
Modern Warfare 2 Infinity Ward's 'Most Successful PC Version' Yet [12]
 
New Tech, Design Details Of Project Natal To Emerge At Gamefest In February
spacer
Latest Jobs
spacer View All     Post a Job     RSS spacer
 
November 22, 2009
 
Trion Redwood City
Sr. Evnironment Modeler
 
Trion Redwood City
Sr. Environment Artist
 
Sucker Punch Productions
3D Environment Artist
 
Sucker Punch Productions
Network Programmer
 
Sucker Punch Productions
Character Artist
 
Sucker Punch Productions
Texture Artist
 
Monolith Productions
Sr. Software Engineer, Engine - Monolith Productions - #113767
 
Sony Online Entertainment
Brand Manager
spacer
Latest Features
spacer View All spacer
 
November 22, 2009
 
arrow Upping The Craft: Susan O'Connor On Games Writing [6]
 
arrow Small Developers: Minimizing Risks in Large Productions - Part II [7]
 
arrow iPhone Piracy: The Inside Story [48]
 
arrow And Yet It Grows: Analyzing the Size and Growth of the European Game Market [5]
 
arrow NPD: Behind the Numbers, October 2009 [13]
 
arrow Reflecting On Uncharted 2: How They Did It [5]
 
arrow Sponsored Feature: Rasterization on Larrabee -- Adaptive Rasterization Helps Boost Efficiency
 
arrow Postmortem: Wadjet Eye's The Blackwell Convergence [2]
spacer
Latest Blogs
spacer View All     Post     RSS spacer
 
November 22, 2009
 
Time Fcuk [1]
 
Accepting the Inherent Value of Games
 
Planckogenesis, Part II: Song Structure & Gravy Train [1]
spacer
About
spacer News Director:
Leigh Alexander
Features Director:
Christian Nutt
Editor At Large:
Chris Remo
Advertising:
John 'Malik' Watson
Recruitment/Education:
Gina Gross
 
Features
  A Templated C++ Attribute Library for Object Persistence and Export
by Gary McNickle
1 comments
Share RSS
 
 
June 4, 2008 Article Start Previous Page 4 of 5 Next
 

Controlling the Output Format of Specific Types

I mentioned earlier that all that was needed to support a given type as an Attribute is that the input and output stream operators exist for that type.

While this is true, relying on the standard operators for default types may not give you the results you expect or want. C++ stream operators provide several manipulators and output format controls for controlling the output of a variable to the stream.

Advertisement

You might, for example, want your floating point types to output in fixed notation rather than scientific. You do not have to sacrifice this ability when using Attributes.

Using partial template specialization you can override the default serialization for any type of object. Essentially, output to a stream is accomplished by first converting the object to a string representation through a call to the ‘ToString’ method of the Attribute class.

Input is done the same way by calling FromString. Providing specialized versions of these methods gives you the means to completely control the format of types which have already implemented the << and >> stream operators.

Here is the template specialization for ‘Attribute<double>::ToString()’:

Listing 6

template <>
_string Attribute<double>::ToString()
{
_ostringstream s;

if ( m_pData )
s << setiosflags(std::ios::fixed) << *m_pData;

return s.str();
}

You may notice in the included source code that template specializations are also provided for both the ToString and FromString methods of the default string type. This is done as a performance enhancement to avoid using stringstream to ‘convert’ std::string objects.

Possible Changes

The included library uses a policy pattern for implementing the IO of the AttributeContainer. One drawback to this pattern is that it does not provide for different IO mechanisms. As written, if you want to serialize to more than one type of medium, you have to use different AttributeContainers.

One solution around this problem is to use the strategy pattern instead. Policies are compile-time bound, whereas strategies can be changed at run-time. I leave this implementation up to you. You can find more information on strategies in any number of books on patterns.

Performance Considerations

It is always important to know your tools and how they will impact the overall performance characteristics of your software. Attribute and AttributeContainer, while they are very useful and convenient tools, do have some important considerations regarding memory.

On the Windows operating system, using Visual Studio, Attribute uses 52 bytes of memory in debug, and 44 in release. Since Attribute stores only a pointer to the variable, the size of the variable type is irrelevant. AttributeContainer uses 36 bytes. It is important to note however, that these values can be significantly reduced with some careful thought.

The version of the library that accompanies this article was written to be easily understandable and easily expanded. It is not optimized for memory use. Here are some suggestions to optimize the memory use to better suit your specific needs:

  1. Change the type of the variable used to hold the behavior flags in Attribute from the default unsigned long (4 bytes) to a short int (2 bytes) or unsigned char (1 byte). This will reduce the total number of flags that your library can support, but once you know how many flags you need you can reduce this variable to a more reasonable size.
  2. Change the type of the string object to char* or to a string class with a smaller memory footprint than std::string. Keep in mind that while std::string seems excessive in its memory footprint, many implementations of it use a shared string manager to reduce the overall memory requirements. 32 bytes of the total memory used by Attribute is used by std::string.
  3. Consider removing the ‘bind order' variable entirely. AttributeContainer keeps track of the order in which Attributes are bound so that it can write them out to xml or otherwise list them in the same order. This is a convenience that can likely be lived without in environments with rigid memory requirements. This is another candidate for an #ifdef. It might be useful in your UI editor to list all of the Attributes in the order they were bound, but you may not need that functionality in your release code.
  4. Consider using a Proxy object rather than having your object inherit directly from AttributeContainer. In this case, you will most likely be swapping memory for performance issues.
 
Article Start Previous Page 4 of 5 Next
 
Comments

Andrew Ames
profile image
The biggest memory savings can be found by separating the attribute container into a class meta data object that is instantiated and filled only once for the class, instead of for each object instance.

After rereading the article, I see you mentioned this refactor potential:

"One alternative is to have a global instance of AttributeContainer (or at least one that is in a larger scope than the objects it manages). While this saves some memory, it does complicate use, as each bound attribute must be somehow uniquely identified per object."

There are certainly some not-too-difficult solutions that simplify the global shared container pattern for client code.

In a system I worked with, the following client code would serialize an object's properties to a stream:

Object *pObject = ...;

MutableString mutstr;
StringOutputStream sos(mutstr);
XmlSerializer ser(os);

ser.Serialize(pObject);


none
 
Comment:
 


Submit Comment