dlib C++ Library - config_reader_thread_safe_1.h

    // Copyright (C) 2007  Davis E. King (davisking@users.sourceforge.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,
            bool checking
            >
        class config_reader_thread_safe_1 : public enumerable<config_reader_thread_safe_1<config_reader_base,map_string_void,checking> >
        {

            /*!
                CONVENTION
                    - get_mutex() == m
                    - *cr == the config reader being extended
                    - block_table[x] == (void*)&block(x)
                    - cr->size == block_table.size()
                    - 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;

            config_reader_thread_safe_1(
                std::istream& in
            );

            virtual ~config_reader_thread_safe_1(
            );

            void clear (
            );

            void load_from (
                std::istream& in
            );

            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;

            inline bool at_start (
            ) const ;

            inline void reset (
            ) const ;

            inline bool current_element_valid (
            ) const ;

            inline const this_type& element (
            ) const ;

            inline this_type& element (
            ) ;

            inline bool move_next (
            ) const ;

            inline unsigned long size (
            ) const ;

            inline const std::string& current_block_name (
            ) const;

            inline const rmutex& get_mutex (
            ) const;

        private:

            void fill_block_table (
            );
            /*!
                ensures
                    - block_table.size() == cr->size()
                    - 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&);

        };

    // ----------------------------------------------------------------------------------------

        /*
            This is a bunch of crap so we can enable and disable the DLIB_CASSERT statements
            without getting warnings about conditions always being true or false.
        */
        namespace config_reader_thread_safe_1_helpers
        {
            template <typename cr_type, bool do_check>
            struct helper;

            template <typename cr_type>
            struct helper<cr_type,false>
            {
                static void check_block_precondition (const cr_type&,  const std::string& ) {}
                static void check_current_block_name_precondition (const cr_type& cr) {}
                static void check_element_precondition (const cr_type& cr) {}
            };

            template <typename cr_type>
            struct helper<cr_type,true>
            {
                static void check_block_precondition (const cr_type& cr, const std::string& name)
                {
                    DLIB_CASSERT ( cr.is_block_defined(name) == true ,
                              "\tconst this_type& config_reader_thread_safe::block(name)"
                              << "\n\tTo access a sub block in the config_reader the block must actually exist."
                              << "\n\tname == " << name
                              << "\n\t&cr:   " << &cr
                    );
                }

                static void check_current_block_name_precondition (const cr_type& cr)
                {
                    DLIB_CASSERT ( cr.current_element_valid() == true ,
                              "\tconst std::string& config_reader_thread_safe::current_block_name()"
                              << "\n\tYou can't call current_block_name() if the current element isn't valid."
                              << "\n\t&cr: " << &cr
                    );
                }

                static void check_element_precondition (const cr_type& cr)
                {
                    DLIB_CASSERT ( cr.current_element_valid() == true ,
                              "\tthis_type& config_reader_thread_safe::element()"
                              << "\n\tYou can't call element() if the current element isn't valid."
                              << "\n\t&cr: " << &cr
                    );
                }
            };
        }

    // ----------------------------------------------------------------------------------------
    // ----------------------------------------------------------------------------------------
        // member function definitions
    // ----------------------------------------------------------------------------------------
    // ----------------------------------------------------------------------------------------

        template <
            typename config_reader_base,
            typename map_string_void,
            bool checking
            >
        config_reader_thread_safe_1<config_reader_base,map_string_void,checking>::
        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,
            bool checking
            >
        config_reader_thread_safe_1<config_reader_base,map_string_void,checking>::
        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,
            bool checking
            >
        void config_reader_thread_safe_1<config_reader_base,map_string_void,checking>::
        clear(
        )
        {
            auto_mutex M(*m);
            cr->clear();
            fill_block_table();
        }

    // ----------------------------------------------------------------------------------------

        template <
            typename config_reader_base,
            typename map_string_void,
            bool checking
            >
        void config_reader_thread_safe_1<config_reader_base,map_string_void,checking>::
        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,
            bool checking
            >
        config_reader_thread_safe_1<config_reader_base,map_string_void,checking>::
        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,
            bool checking
            >
        config_reader_thread_safe_1<config_reader_base,map_string_void,checking>::
        ~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 reinterpret_cast<config_reader_thread_safe_1*>(block_table.element().value());
            }
            block_table.clear();
        }

    // ----------------------------------------------------------------------------------------

        template <
            typename config_reader_base,
            typename map_string_void,
            bool checking
            >
        bool config_reader_thread_safe_1<config_reader_base,map_string_void,checking>::
        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 checking
            >
        bool config_reader_thread_safe_1<config_reader_base,map_string_void,checking>::
        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,
            bool checking
            >
        const config_reader_thread_safe_1<config_reader_base,map_string_void,checking>& config_reader_thread_safe_1<config_reader_base,map_string_void,checking>::
        block (
            const std::string& name
        ) const
        {
            auto_mutex M(*m);
            config_reader_thread_safe_1_helpers::helper<config_reader_thread_safe_1,checking>::
                check_block_precondition(*this,name);
            return *reinterpret_cast<config_reader_thread_safe_1*>(block_table[name]);
        }

    // ----------------------------------------------------------------------------------------

        template <
            typename config_reader_base,
            typename map_string_void,
            bool checking
            >
        const std::string& config_reader_thread_safe_1<config_reader_base,map_string_void,checking>::
        operator[] (
            const std::string& key
        ) const
        {
            auto_mutex M(*m);
            return (*cr)[key];
        }

    // ----------------------------------------------------------------------------------------

        template <
            typename config_reader_base,
            typename map_string_void,
            bool checking
            >
        template <
            typename queue_of_strings
            >
        void config_reader_thread_safe_1<config_reader_base,map_string_void,checking>::
        get_keys (
            queue_of_strings& keys
        ) const
        {
            auto_mutex M(*m);
            cr->get_keys(keys);
        }

    // ----------------------------------------------------------------------------------------

        template <
            typename config_reader_base,
            typename map_string_void,
            bool checking
            >
        bool config_reader_thread_safe_1<config_reader_base,map_string_void,checking>::
        at_start (
        ) const
        {
            auto_mutex M(*m);
            return block_table.at_start();
        }

    // ----------------------------------------------------------------------------------------

        template <
            typename config_reader_base,
            typename map_string_void,
            bool checking
            >
        void config_reader_thread_safe_1<config_reader_base,map_string_void,checking>::
        reset (
        ) const
        {
            auto_mutex M(*m);
            block_table.reset();
        }

    // ----------------------------------------------------------------------------------------

        template <
            typename config_reader_base,
            typename map_string_void,
            bool checking
            >
        bool config_reader_thread_safe_1<config_reader_base,map_string_void,checking>::
        current_element_valid (
        ) const
        {
            auto_mutex M(*m);
            return block_table.current_element_valid();
        }

    // ----------------------------------------------------------------------------------------

        template <
            typename config_reader_base,
            typename map_string_void,
            bool checking
            >
        const config_reader_thread_safe_1<config_reader_base,map_string_void,checking>& config_reader_thread_safe_1<config_reader_base,map_string_void,checking>::
        element (
        ) const
        {
            auto_mutex M(*m);
            config_reader_thread_safe_1_helpers::helper<config_reader_thread_safe_1,checking>::
                check_element_precondition(*this);
            return *reinterpret_cast<config_reader_thread_safe_1*>(block_table.element().value());
        }

    // ----------------------------------------------------------------------------------------

        template <
            typename config_reader_base,
            typename map_string_void,
            bool checking
            >
        config_reader_thread_safe_1<config_reader_base,map_string_void,checking>& config_reader_thread_safe_1<config_reader_base,map_string_void,checking>::
        element (
        )
        {
            auto_mutex M(*m);
            config_reader_thread_safe_1_helpers::helper<config_reader_thread_safe_1,checking>::
                check_element_precondition(*this);
            return *reinterpret_cast<config_reader_thread_safe_1*>(block_table.element().value());
        }

    // ----------------------------------------------------------------------------------------

        template <
            typename config_reader_base,
            typename map_string_void,
            bool checking
            >
        bool config_reader_thread_safe_1<config_reader_base,map_string_void,checking>::
        move_next (
        ) const
        {
            auto_mutex M(*m);
            return block_table.move_next();
        }

    // ----------------------------------------------------------------------------------------

        template <
            typename config_reader_base,
            typename map_string_void,
            bool checking
            >
        unsigned long config_reader_thread_safe_1<config_reader_base,map_string_void,checking>::
        size (
        ) const
        {
            auto_mutex M(*m);
            return block_table.size();
        }

    // ----------------------------------------------------------------------------------------

        template <
            typename config_reader_base,
            typename map_string_void,
            bool checking
            >
        const std::string& config_reader_thread_safe_1<config_reader_base,map_string_void,checking>::
        current_block_name (
        ) const
        {
            auto_mutex M(*m);
            config_reader_thread_safe_1_helpers::helper<config_reader_thread_safe_1,checking>::
                check_current_block_name_precondition(*this);
            return block_table.element().key();
        }

    // ----------------------------------------------------------------------------------------

        template <
            typename config_reader_base,
            typename map_string_void,
            bool checking
            >
        const rmutex& config_reader_thread_safe_1<config_reader_base,map_string_void,checking>::
        get_mutex (
        ) const
        {
            return *m;
        }

    // ----------------------------------------------------------------------------------------
    // ----------------------------------------------------------------------------------------
    //      private member functions
    // ----------------------------------------------------------------------------------------
    // ----------------------------------------------------------------------------------------

        template <
            typename config_reader_base,
            typename map_string_void,
            bool checking
            >
        void config_reader_thread_safe_1<config_reader_base,map_string_void,checking>::
        fill_block_table (
        )
        {
            using namespace std;
            // first empty out the block table
            block_table.reset();
            while (block_table.move_next())
            {
                delete reinterpret_cast<config_reader_thread_safe_1*>(block_table.element().value());
            }
            block_table.clear();

            // now fill the block table up to match what is in cr
            cr->reset();
            while (cr->move_next())
            {
                config_reader_thread_safe_1* block = new config_reader_thread_safe_1(&cr->element(),m);
                void* temp = block;
                std::string key(cr->current_block_name());
                block_table.add(key,temp);
            }
        }

    // ----------------------------------------------------------------------------------------

    }

    #endif // DLIB_CONFIG_READER_THREAD_SAFe_