XML configuration settings file access can be handled by creating a thread-safe singleton XMLParser class. Boost library has got a Property Tree library, boost::property_tree , which populates a tree data structure that is representing the existing XML file content.
boost::property_tree makes it easy to load an existing XML file into application. In order to provide thread safety for singleton XMLParser , QT application development framework supplied QMutex class can be used.
Following sample project created by qt creator and contains following files :
1-SingletonXMLParser.pro
2-XmlParser.h
3-XmlParser.cpp
4-main.cpp
SingletonXMLParser.pro file contains project configuration :
QT += core TARGET = SingletonXMLParser CONFIG += console CONFIG -= app_bundle TEMPLATE = app SOURCES += main.cpp \ XmlParser.cpp HEADERS += XmlParser.h
In this example project, XMLParser.h header file contains the Settings struct which is going to hold data loaded from XML file. Also the name of the XML file is declared in the header file with a #define directive.
Requirements to make XMLParser class a Thread-Safe Singleton is handled by
1- Making constructor private
2- Adding a static XMLParser variable
3- Static Instance creator method
4- QMutex variable for locking
Example ConfSettings.xml file contains following data and placed under an accessible folder :
#ifndef XMLPARSER_H #define XMLPARSER_H #define CONF_SETTINGS_FILE "ConfSettings.xml" #include <boost/property_tree/ptree.hpp> #include <boost/property_tree/xml_parser.hpp> #include <QMutex> struct Settings { std::string ipAddress; std::string userName; }; class XMLParser { public: static XMLParser& instance(); ~XMLParser(); Settings getSettings(); private: XMLParser(); Settings configSettings; static std::auto_ptr<XMLParser> mInstance; static QMutex mMutex; }; #endif // XMLPARSER_H
XMLParser.cpp file contains implementation details for
1- private constructor
2- static instance creator method
3- static variables
#include "XmlParser.h" std::auto_ptr<XMLParser> XMLParser::mInstance; QMutex XMLParser::mMutex(QMutex::Recursive); XMLParser::XMLParser() { boost::property_tree::ptree config; read_xml(CONF_SETTINGS_FILE, config); configSettings.ipAddress = config.get<std::string>("ftp.ipAddress"); configSettings.userName = config.get<std::string>("ftp.userName"); } XMLParser::~XMLParser() { } XMLParser& XMLParser::instance() { mMutex.lock(); if (mInstance.get() == 0) { try { mInstance.reset(new XMLParser); } catch (std::bad_alloc&) { throw; } } mMutex.unlock(); return *mInstance; } Settings XMLParser::getSettings() { return configSettings; }
In the constructor of the XMLParser class CONF_SETTINGS_FILE is loaded into boost::property_tree::ptree type config variable. Then by applying the get method of boost::property_tree::ptree required elements from the XML document are retrieved into the application.
Static instance() method of XMLParser provides thread safety by calling lock() and unlock() methods of QMutex instance.
Main method in the main.cpp file calls the static instance() method of thread-safe singleton XMLParser class and then loads the config settings into to Settings struct.
#include "XmlParser.h" int main() { Settings confSettings = XMLParser::instance().getSettings(); std::cout << confSettings.ipAddress << std::endl; std::cout << confSettings.userName << std::endl; return 0; }Output of the execution of this program shows ipAddress and userName element values from ConfSettings.xml file on the terminal.