Click here to Skip to main content
15,886,873 members
Articles / Programming Languages / C#

HTLSharp - A CSharp Version of the HPC Template Library

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
19 Dec 2017MIT6 min read 10.9K   150   4  
HTLSharp is a C# port and upgrade of the HPC Template Library (HTL).

Author: Anthony Daniels
Email: AnthonyDaniels99@gmail.com

 

Download source

Introduction

HTLSharp is a C# port and upgrade of the HPC Template Library (HTL). The HTL and the HTLSharp library provide packages for thread safe containers, random number generators and distributions, as well as an integrated serialization engine. For more information on the original HTL, see this article.

The packages in the HTLSharp library are as follows:

Package Description Operational Status
HtlArchive: Contains all of the classes necessary for serialization and deserialization of objects. It contains a generic archive tree / node system and different serializer packages (XML, XDL, JSON, etc.) that persist the data structure. Archive Model (100%) XML (100%) XDL(100%) JSON (50%)
HtlBase: Contains the base classes for making objects serializable using the HTL system. (100%)
HtlContainer: Contains all of the container classes of the HTL (HtlVector, HtlMap, HtlQueue, etc.). All containers in this set are serializable in the HTL system. – (fully operational) (100%)
HtlGlobal: Contains globally used enumerated types, structs, etc. (100%)
HtlGUID: Contains the three Global Unique Identifiers (GUID); 64bit, 128bit, and 256bit (100%)
HtlRandNumGen: Contains a system for random number generators and random distribution generators. (100%)
HtlString: Contains the class that provides STL style sprintf() and sscanf() methods. (100%)
HtlTest: Contains the HTL unit testing system. This is a test name based unit test system similar to boost, but no macros were used in it. (100%)
HtlThread: Contains all thread related classes including mutexes, semaphores, threads, etc. (100%)

It should be noted that some packages such as the Signals and Slots were not ported to C# from the original library. This is because the event handling infrastructure already exists in the base C# library. Also, while some multithreaded containers exist in C#.NET, they were not integrated with the HTL serialization engine so the decision was made to wrap the original generic containers. It should be noted that in the source code project provided, there is a unit testing project that illustrates the usage of the code.

HtlArchive Package

The following sections will illustrate the code usage. The HTL Archive package is a very powerful serialization system. The system uses a generic object tree structure to represent any data structure in memory. That data structure is independent of the serialization method used. So the same serialization structure can feed either an XML serialization or a JSON serialization. This allows for the developer to write code for classes without worrying about the method of serialization. Let's get started.

HTLSharp can serialize any integrated data type (bool, int, long, float, double, string, etc.) as well as any class that inherits from HtlBase. HtlBase is a lightweight object that has only two member variables (m_strType, and m_objType) as well as two virtual functions used for the serialization (Save and Load); The m_strType is used in the static object factory for creating any type of object that inherits from HtlBase and has been registered. Let us look at the Save and Load methods. Here are their prototypes:

C#
public virtual int Save(ref HtlElement ptrCurrNode, ref string strMemVarName, bool blnWithSubObjects)
public virtual int Load(ref HtlElement ptrCurrNode, ref string strMemVarName)

The HtlElement passed in is the current node of the generic data structure being saved or loaded. The strMemVarName is the string name of that node. Save also has a Boolean flag passed for whether or not sub objects are to be written. This can be useful in scenarios where you just want to do a shallow printout at that level and not all of the sub objects below. Now let us take a look at them implemented. The TestObj2 is a class in the unit testing project. Here is the save and load methods from that object.

C#
//Virtual Inheritance Serialization Engines
//SERIALIZATION FUNCTIONS///////////////////////////////////////
//!Save member data to the current element node
public override int Save
(ref HtlElement ptrCurrNode, ref string strMemVarName, bool blnWithSubObjects)
{
int intReturn = 0;
//SAFETY CHECK //put at top of all Serialize Methods
if (ptrCurrNode == null) { return 0; };
//CALL PARENT CLASS Serialize()
base.Save(ref ptrCurrNode, ref strMemVarName, blnWithSubObjects);
//strSTDBaseType.clear();
//strBaseType.clear();
//Standard Member Variables
intReturn &= HtlMemVar.SetMemVar<bool>
(ref ptrCurrNode, "m_myBool", ref m_myBool, false);
intReturn &= HtlMemVar.SetMemVar<int>
(ref ptrCurrNode, "m_myInt01", ref m_myInt01, false);
intReturn &= HtlMemVar.SetMemVar<double>
(ref ptrCurrNode, "m_myDouble04", ref m_myDouble04, false);
intReturn &= HtlMemVar.SetMemVar<string>
(ref ptrCurrNode, "m_myString", ref m_myString, false);
          
//Sub Object Member Variables
if (blnWithSubObjects)
{
intReturn &= HtlMemVar.SetMemVar<TestObj01>
(ref ptrCurrNode, "m_myTestObj", ref m_myTestObj, blnWithSubObjects);
};

return intReturn;
}
//!Load member data from the current element node
public override int Load(ref HtlElement ptrCurrNode, ref string strMemVarName)
{
int intReturn = 0;
//SAFETY CHECK //put at top of all Serialize Methods
if (ptrCurrNode == null) { return 0; };
//CALL PARENT CLASS Serialize()
base.Load(ref ptrCurrNode, ref strMemVarName);
//Standard Member Variables
string strRet = System.String.Empty;
intReturn &= HtlMemVar.GetMemVar<bool>
(ref ptrCurrNode, "m_myBool", ref m_myBool);
intReturn &= HtlMemVar.GetMemVar<int>
(ref ptrCurrNode, "m_myInt01", ref m_myInt01);
intReturn &= HtlMemVar.GetMemVar<double>
(ref ptrCurrNode, "m_myDouble04", ref m_myDouble04);
intReturn &= HtlMemVar.GetMemVar<string>
(ref ptrCurrNode, "m_myString", ref m_myString);
intReturn &= HtlMemVar.GetMemVar<TestObj01>
(ref ptrCurrNode, "m_myTestObj", ref m_myTestObj);

return intReturn;
}

The first thing that the Save method does is call the parent class Save method. Then, it proceeds to set all of the member variables for the class. In this case, there is a bool, an int, a double, a string, and a sub object of type TestObj01 which also inherits from HtlBase. Note the TestObj01 is within the Boolean check for print sub objects. The setting of member variables is achieved by calling the HtlMemVar.SetMemVar<T>() method. You pass in the reference to the current node, the string name for that member variable, and the reference to the object. Note all the base object member variables have the blnWithSubObjects set to false.

Similarly, the Load method calls the parent class Load, and then proceeds to call the reciprocal GetMemVar<T> function. It should be noted that the reason for having both a Save and a Load method is that sometimes the developer wishes to have write only member variables (such as GUIDs for example). The system also works for all of the containers in the HTL. Here is an example of a HtlVector being serialized.

C#
intReturn &= HtlMemVar.SetMemVar<HtlVector<TestObj01>>
             (ref ptrCurrNode, "m_arrObjs", ref m_arrObjs, true);

Once the save has been called, the user can then serialize with the desired serializer. The following example is using the XDL serializer.

C#
TestObj02 obj = new TestObj02();
string strOut = System.String.Empty;
string strTopName = "rootobject";
HtlXDLWriter writer = new HtlXDLWriter();
HtlElement root = new HtlElement();
//serialize
obj.Save(ref root, ref strTopName, true);
root.UpdateIndexes();
writer.SaveXDLTree(ref root, ref strOut, true);

// Write the string to a file.
System.IO.StreamWriter outfile = 
new System.IO.StreamWriter("HtlTestArch_XDL_Obj02Nested.out");

outfile.Write(strOut);
outfile.Close();
 
//clear the values
obj.m_myBool = false;
obj.m_myInt01 = -1;
obj.m_myDouble04 = -1.0f;
obj.m_myString = "null";
obj.m_myTestObj.Reset();
//now read it back in and deserialize
HtlElementIndex xelem = new HtlElementIndex();
HtlXDLReader reader = new HtlXDLReader();
HtlElement readroot = new HtlElement();

reader.LoadXDLTree(ref readroot, ref strOut, ref xelem);
obj.Load(ref readroot, ref strTopName);

HtlContainer Package

The decision was made to provide wrappers for the Vector (List), Map (Dictionary), and Queue classes in the C#.NET library. With these three basic containers, you can cover most of your needs. However, if there is a need for another thread-safe wrapping, they provide a good roadmap to the user on how to create one. As mentioned before, the main intention of the containers (aside from multithreading support) was to integrate it with the archiving system. The included unit tests in the HtlTestSuite provide sample XML and XDL output. JSON is in the works and should be added soon. Please see the unit tests for the multithreading testing and validation.

HtlRandNumGen Package

There are two random number generators (LCG and Mersenne Twister) and five distributions (HtlUniform, HtlGamma, HtlGaussian, HtlPoisson, HtlExponential). Provided are unit tests for Uniform, Exponential, and Gaussian. The RNGs are simple to use. Just create the object, call initialize() to get your seed, and then call next() to get the next RNG. HtlUniform also has the ability to generate RNGs over a range using the intGetNextAB() or sngGetNextAB() functions.

HtlGUID Package

There are 64, 128 and 256 bit global unique identifiers available. They inherit from HtlBase so they are directly serializable. One thing that should be noted is that they are symmetric unlike the windows GUID class. All segments are equal width. Here is an example of a HtlGUID128:

975D3F24-F81FF9EB-2F556151-5F9D2204

This makes them simpler to work with and its presentation is neater.

HtlTest Package

The HtlNode package has a node based architecture similar to the HtlElement class in the archive package. HtlTestNode can contain other test nodes and the root node fires all of the children. Refer to the HtlTestSuite for a good example of its use. Each HtlTestNode has the following virtual functions that get implemented on demand in child classes. The methods are fired in order in the public PerformTest() method.

C#
public virtual int SetupTest() { return 0; }
public virtual int PreProcessTest() { return 0; }
public virtual int RunTest() { return 0; }
public virtual int PostProcessTest() { return 0; }
public virtual int ClearTest() { return 0; }

License

This article, along with any associated source code and files, is licensed under The MIT License


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
-- There are no messages in this forum --