// Copyright (C) 2007 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_CONFIG_READER_THREAD_SAFe_ #define DLIB_CONFIG_READER_THREAD_SAFe_ #include "config_reader_kernel_abstract.h" #include <string> #include <iostream> #include <sstream> #include "../algs.h" #include "../interfaces/enumerable.h" #include "../threads.h" #include "config_reader_thread_safe_abstract.h" namespace dlib { template < typename config_reader_base, typename map_string_void > class config_reader_thread_safe_1 { /*! CONVENTION - get_mutex() == *m - *cr == the config reader being extended - block_table[x] == (void*)&block(x) - block_table.size() == the number of blocks in *cr - block_table[key] == a config_reader_thread_safe_1 that contains &cr.block(key) - if (own_pointers) then - this object owns the m and cr pointers and should delete them when destructed !*/ public: config_reader_thread_safe_1 ( const config_reader_base* base, rmutex* m_ ); config_reader_thread_safe_1(); typedef typename config_reader_base::config_reader_error config_reader_error; typedef typename config_reader_base::config_reader_access_error config_reader_access_error; config_reader_thread_safe_1( std::istream& in ); config_reader_thread_safe_1( const std::string& config_file ); virtual ~config_reader_thread_safe_1( ); void clear ( ); void load_from ( std::istream& in ); void load_from ( const std::string& config_file ); bool is_key_defined ( const std::string& key ) const; bool is_block_defined ( const std::string& name ) const; typedef config_reader_thread_safe_1 this_type; const this_type& block ( const std::string& name ) const; const std::string& operator[] ( const std::string& key ) const; template < typename queue_of_strings > void get_keys ( queue_of_strings& keys ) const; template < typename queue_of_strings > void get_blocks ( queue_of_strings& blocks ) const; inline const rmutex& get_mutex ( ) const; private: void fill_block_table ( ); /*! ensures - block_table.size() == the number of blocks in cr - block_table[key] == a config_reader_thread_safe_1 that contains &cr.block(key) !*/ rmutex* m; config_reader_base* cr; map_string_void block_table; const bool own_pointers; // restricted functions config_reader_thread_safe_1(config_reader_thread_safe_1&); config_reader_thread_safe_1& operator=(config_reader_thread_safe_1&); }; // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- // member function definitions // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- template < typename config_reader_base, typename map_string_void > config_reader_thread_safe_1<config_reader_base,map_string_void>:: config_reader_thread_safe_1( const config_reader_base* base, rmutex* m_ ) : m(m_), cr(const_cast<config_reader_base*>(base)), own_pointers(false) { fill_block_table(); } // ---------------------------------------------------------------------------------------- template < typename config_reader_base, typename map_string_void > config_reader_thread_safe_1<config_reader_base,map_string_void>:: config_reader_thread_safe_1( ) : m(0), cr(0), own_pointers(true) { try { m = new rmutex; cr = new config_reader_base; } catch (...) { if (m) delete m; if (cr) delete cr; throw; } } // ---------------------------------------------------------------------------------------- template < typename config_reader_base, typename map_string_void > void config_reader_thread_safe_1<config_reader_base,map_string_void>:: clear( ) { auto_mutex M(*m); cr->clear(); fill_block_table(); } // ---------------------------------------------------------------------------------------- template < typename config_reader_base, typename map_string_void > void config_reader_thread_safe_1<config_reader_base,map_string_void>:: load_from( std::istream& in ) { auto_mutex M(*m); cr->load_from(in); fill_block_table(); } // ---------------------------------------------------------------------------------------- template < typename config_reader_base, typename map_string_void > void config_reader_thread_safe_1<config_reader_base,map_string_void>:: load_from( const std::string& config_file ) { auto_mutex M(*m); cr->load_from(config_file); fill_block_table(); } // ---------------------------------------------------------------------------------------- template < typename config_reader_base, typename map_string_void > config_reader_thread_safe_1<config_reader_base,map_string_void>:: config_reader_thread_safe_1( std::istream& in ) : m(0), cr(0), own_pointers(true) { try { m = new rmutex; cr = new config_reader_base(in); fill_block_table(); } catch (...) { if (m) delete m; if (cr) delete cr; throw; } } // ---------------------------------------------------------------------------------------- template < typename config_reader_base, typename map_string_void > config_reader_thread_safe_1<config_reader_base,map_string_void>:: config_reader_thread_safe_1( const std::string& config_file ) : m(0), cr(0), own_pointers(true) { try { m = new rmutex; cr = new config_reader_base(config_file); fill_block_table(); } catch (...) { if (m) delete m; if (cr) delete cr; throw; } } // ---------------------------------------------------------------------------------------- template < typename config_reader_base, typename map_string_void > config_reader_thread_safe_1<config_reader_base,map_string_void>:: ~config_reader_thread_safe_1( ) { if (own_pointers) { delete m; delete cr; } // clear out the block table block_table.reset(); while (block_table.move_next()) { delete static_cast<config_reader_thread_safe_1*>(block_table.element().value()); } block_table.clear(); } // ---------------------------------------------------------------------------------------- template < typename config_reader_base, typename map_string_void > bool config_reader_thread_safe_1<config_reader_base,map_string_void>:: is_key_defined ( const std::string& key ) const { auto_mutex M(*m); return cr->is_key_defined(key); } // ---------------------------------------------------------------------------------------- template < typename config_reader_base, typename map_string_void > bool config_reader_thread_safe_1<config_reader_base,map_string_void>:: is_block_defined ( const std::string& name ) const { auto_mutex M(*m); return cr->is_block_defined(name); } // ---------------------------------------------------------------------------------------- template < typename config_reader_base, typename map_string_void > const config_reader_thread_safe_1<config_reader_base,map_string_void>& config_reader_thread_safe_1<config_reader_base,map_string_void>:: block ( const std::string& name ) const { auto_mutex M(*m); if (block_table.is_in_domain(name) == false) { throw config_reader_access_error(name,""); } return *static_cast<config_reader_thread_safe_1*>(block_table[name]); } // ---------------------------------------------------------------------------------------- template < typename config_reader_base, typename map_string_void > const std::string& config_reader_thread_safe_1<config_reader_base,map_string_void>:: operator[] ( const std::string& key ) const { auto_mutex M(*m); return (*cr)[key]; } // ---------------------------------------------------------------------------------------- template < typename config_reader_base, typename map_string_void > template < typename queue_of_strings > void config_reader_thread_safe_1<config_reader_base,map_string_void>:: get_keys ( queue_of_strings& keys ) const { auto_mutex M(*m); cr->get_keys(keys); } // ---------------------------------------------------------------------------------------- template < typename config_reader_base, typename map_string_void > template < typename queue_of_strings > void config_reader_thread_safe_1<config_reader_base,map_string_void>:: get_blocks ( queue_of_strings& blocks ) const { auto_mutex M(*m); cr->get_blocks(blocks); } // ---------------------------------------------------------------------------------------- template < typename config_reader_base, typename map_string_void > const rmutex& config_reader_thread_safe_1<config_reader_base,map_string_void>:: get_mutex ( ) const { return *m; } // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- // private member functions // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- template < typename config_reader_base, typename map_string_void > void config_reader_thread_safe_1<config_reader_base,map_string_void>:: fill_block_table ( ) { using namespace std; // first empty out the block table block_table.reset(); while (block_table.move_next()) { delete static_cast<config_reader_thread_safe_1*>(block_table.element().value()); } block_table.clear(); std::vector<std::string> blocks; cr->get_blocks(blocks); // now fill the block table up to match what is in cr for (unsigned long i = 0; i < blocks.size(); ++i) { config_reader_thread_safe_1* block = new config_reader_thread_safe_1(&cr->block(blocks[i]),m); void* temp = block; block_table.add(blocks[i],temp); } } // ---------------------------------------------------------------------------------------- } #endif // DLIB_CONFIG_READER_THREAD_SAFe_