Master commit of OpenFace.

This commit is contained in:
unknown
2016-04-28 15:40:36 -04:00
parent 5346d303ab
commit 57e58a6949
4406 changed files with 1441342 additions and 0 deletions

View File

@@ -0,0 +1,738 @@
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_CONFIG_READER_KERNEl_1_
#define DLIB_CONFIG_READER_KERNEl_1_
#include "config_reader_kernel_abstract.h"
#include <string>
#include <iostream>
#include <sstream>
#include <fstream>
#include "../algs.h"
#include "../stl_checked/std_vector_c.h"
#ifndef DLIB_ISO_CPP_ONLY
#include "config_reader_thread_safe_1.h"
#endif
namespace dlib
{
template <
typename map_string_string,
typename map_string_void,
typename tokenizer
>
class config_reader_kernel_1
{
/*!
REQUIREMENTS ON map_string_string
is an implementation of map/map_kernel_abstract.h that maps std::string to std::string
REQUIREMENTS ON map_string_void
is an implementation of map/map_kernel_abstract.h that maps std::string to void*
REQUIREMENTS ON tokenizer
is an implementation of tokenizer/tokenizer_kernel_abstract.h
CONVENTION
key_table.is_in_domain(x) == is_key_defined(x)
block_table.is_in_domain(x) == is_block_defined(x)
key_table[x] == operator[](x)
block_table[x] == (void*)&block(x)
!*/
public:
// These two typedefs are defined for backwards compatibility with older versions of dlib.
typedef config_reader_kernel_1 kernel_1a;
#ifndef DLIB_ISO_CPP_ONLY
typedef config_reader_thread_safe_1<
config_reader_kernel_1,
map_string_void
> thread_safe_1a;
#endif // DLIB_ISO_CPP_ONLY
config_reader_kernel_1();
class config_reader_error : public dlib::error
{
friend class config_reader_kernel_1;
config_reader_error(
unsigned long ln,
bool r = false
) :
dlib::error(ECONFIG_READER),
line_number(ln),
redefinition(r)
{
std::ostringstream sout;
sout << "Error in config_reader while parsing at line number " << line_number << ".";
if (redefinition)
sout << "\nThe identifier on this line has already been defined in this scope.";
const_cast<std::string&>(info) = sout.str();
}
public:
const unsigned long line_number;
const bool redefinition;
};
class file_not_found : public dlib::error
{
friend class config_reader_kernel_1;
file_not_found(
const std::string& file_name_
) :
dlib::error(ECONFIG_READER, "Error in config_reader, unable to open file " + file_name_),
file_name(file_name_)
{}
~file_not_found() throw() {}
public:
const std::string file_name;
};
class config_reader_access_error : public dlib::error
{
public:
config_reader_access_error(
const std::string& block_name_,
const std::string& key_name_
) :
dlib::error(ECONFIG_READER),
block_name(block_name_),
key_name(key_name_)
{
std::ostringstream sout;
sout << "Error in config_reader.\n";
if (block_name.size() > 0)
sout << " A block with the name '" << block_name << "' was expected but not found.";
else if (key_name.size() > 0)
sout << " A key with the name '" << key_name << "' was expected but not found.";
const_cast<std::string&>(info) = sout.str();
}
~config_reader_access_error() throw() {}
const std::string block_name;
const std::string key_name;
};
config_reader_kernel_1(
const std::string& config_file
);
config_reader_kernel_1(
std::istream& in
);
virtual ~config_reader_kernel_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_kernel_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 alloc
>
void get_keys (
std::vector<std::string,alloc>& keys
) const;
template <
typename alloc
>
void get_keys (
std_vector_c<std::string,alloc>& keys
) const;
template <
typename queue_of_strings
>
void get_blocks (
queue_of_strings& blocks
) const;
template <
typename alloc
>
void get_blocks (
std::vector<std::string,alloc>& blocks
) const;
template <
typename alloc
>
void get_blocks (
std_vector_c<std::string,alloc>& blocks
) const;
private:
static void parse_config_file (
config_reader_kernel_1& cr,
tokenizer& tok,
unsigned long& line_number,
const bool top_of_recursion = true
);
/*!
requires
- line_number == 1
- cr == *this
- top_of_recursion == true
ensures
- parses the data coming from tok and puts it into cr.
throws
- config_reader_error
!*/
map_string_string key_table;
map_string_void block_table;
// restricted functions
config_reader_kernel_1(config_reader_kernel_1&);
config_reader_kernel_1& operator=(config_reader_kernel_1&);
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename map_string_string,
typename map_string_void,
typename tokenizer
>
config_reader_kernel_1<map_string_string,map_string_void,tokenizer>::
config_reader_kernel_1(
)
{
}
// ----------------------------------------------------------------------------------------
template <
typename map_string_string,
typename map_string_void,
typename tokenizer
>
void config_reader_kernel_1<map_string_string,map_string_void,tokenizer>::
clear(
)
{
// free all our blocks
block_table.reset();
while (block_table.move_next())
{
delete static_cast<config_reader_kernel_1*>(block_table.element().value());
}
block_table.clear();
key_table.clear();
}
// ----------------------------------------------------------------------------------------
template <
typename map_string_string,
typename map_string_void,
typename tokenizer
>
void config_reader_kernel_1<map_string_string,map_string_void,tokenizer>::
load_from(
std::istream& in
)
{
clear();
tokenizer tok;
tok.set_stream(in);
tok.set_identifier_token(
tok.lowercase_letters() + tok.uppercase_letters(),
tok.lowercase_letters() + tok.uppercase_letters() + tok.numbers() + "_-."
);
unsigned long line_number = 1;
try
{
parse_config_file(*this,tok,line_number);
}
catch (...)
{
clear();
throw;
}
}
// ----------------------------------------------------------------------------------------
template <
typename map_string_string,
typename map_string_void,
typename tokenizer
>
void config_reader_kernel_1<map_string_string,map_string_void,tokenizer>::
load_from(
const std::string& config_file
)
{
clear();
std::ifstream fin(config_file.c_str());
if (!fin)
throw file_not_found(config_file);
load_from(fin);
}
// ----------------------------------------------------------------------------------------
template <
typename map_string_string,
typename map_string_void,
typename tokenizer
>
config_reader_kernel_1<map_string_string,map_string_void,tokenizer>::
config_reader_kernel_1(
std::istream& in
)
{
load_from(in);
}
// ----------------------------------------------------------------------------------------
template <
typename map_string_string,
typename map_string_void,
typename tokenizer
>
config_reader_kernel_1<map_string_string,map_string_void,tokenizer>::
config_reader_kernel_1(
const std::string& config_file
)
{
load_from(config_file);
}
// ----------------------------------------------------------------------------------------
template <
typename map_string_string,
typename map_string_void,
typename tokenizer
>
void config_reader_kernel_1<map_string_string,map_string_void,tokenizer>::
parse_config_file(
config_reader_kernel_1<map_string_string,map_string_void,tokenizer>& cr,
tokenizer& tok,
unsigned long& line_number,
const bool top_of_recursion
)
{
int type;
std::string token;
bool in_comment = false;
bool seen_identifier = false;
std::string identifier;
while (true)
{
tok.get_token(type,token);
// ignore white space
if (type == tokenizer::WHITE_SPACE)
continue;
// basically ignore end of lines
if (type == tokenizer::END_OF_LINE)
{
++line_number;
in_comment = false;
continue;
}
// we are in a comment still so ignore this
if (in_comment)
continue;
// if this is the start of a comment
if (type == tokenizer::CHAR && token[0] == '#')
{
in_comment = true;
continue;
}
// if this is the case then we have just finished parsing a block so we should
// quit this function
if ( (type == tokenizer::CHAR && token[0] == '}' && !top_of_recursion) ||
(type == tokenizer::END_OF_FILE && top_of_recursion) )
{
break;
}
if (seen_identifier)
{
seen_identifier = false;
// the next character should be either a '=' or a '{'
if (type != tokenizer::CHAR || (token[0] != '=' && token[0] != '{'))
throw config_reader_error(line_number);
if (token[0] == '=')
{
// we should parse the value out now
// first discard any white space
if (tok.peek_type() == tokenizer::WHITE_SPACE)
tok.get_token(type,token);
std::string value;
type = tok.peek_type();
token = tok.peek_token();
while (true)
{
if (type == tokenizer::END_OF_FILE || type == tokenizer::END_OF_LINE)
break;
if (type == tokenizer::CHAR && token[0] == '\\')
{
tok.get_token(type,token);
if (tok.peek_type() == tokenizer::CHAR &&
tok.peek_token()[0] == '#')
{
tok.get_token(type,token);
value += '#';
}
else if (tok.peek_type() == tokenizer::CHAR &&
tok.peek_token()[0] == '}')
{
tok.get_token(type,token);
value += '}';
}
else
{
value += '\\';
}
}
else if (type == tokenizer::CHAR &&
(token[0] == '#' || token[0] == '}'))
{
break;
}
else
{
value += token;
tok.get_token(type,token);
}
type = tok.peek_type();
token = tok.peek_token();
} // while(true)
// strip of any tailing white space from value
std::string::size_type pos = value.find_last_not_of(" \t\r\n");
if (pos == std::string::npos)
value.clear();
else
value.erase(pos+1);
// make sure this key isn't already in the key_table
if (cr.key_table.is_in_domain(identifier))
throw config_reader_error(line_number,true);
// add this key/value pair to the key_table
cr.key_table.add(identifier,value);
}
else // when token[0] == '{'
{
// make sure this identifier isn't already in the block_table
if (cr.block_table.is_in_domain(identifier))
throw config_reader_error(line_number,true);
config_reader_kernel_1* new_cr = new config_reader_kernel_1;
void* vtemp = new_cr;
try { cr.block_table.add(identifier,vtemp); }
catch (...) { delete new_cr; throw; }
// now parse this block
parse_config_file(*new_cr,tok,line_number,false);
}
}
else
{
// the next thing should be an identifier but if it isn't this is an error
if (type != tokenizer::IDENTIFIER)
throw config_reader_error(line_number);
seen_identifier = true;
identifier = token;
}
} // while (true)
}
// ----------------------------------------------------------------------------------------
template <
typename map_string_string,
typename map_string_void,
typename tokenizer
>
config_reader_kernel_1<map_string_string,map_string_void,tokenizer>::
~config_reader_kernel_1(
)
{
clear();
}
// ----------------------------------------------------------------------------------------
template <
typename map_string_string,
typename map_string_void,
typename tokenizer
>
bool config_reader_kernel_1<map_string_string,map_string_void,tokenizer>::
is_key_defined (
const std::string& key
) const
{
return key_table.is_in_domain(key);
}
// ----------------------------------------------------------------------------------------
template <
typename map_string_string,
typename map_string_void,
typename tokenizer
>
bool config_reader_kernel_1<map_string_string,map_string_void,tokenizer>::
is_block_defined (
const std::string& name
) const
{
return block_table.is_in_domain(name);
}
// ----------------------------------------------------------------------------------------
template <
typename mss,
typename msv,
typename tokenizer
>
const config_reader_kernel_1<mss,msv,tokenizer>& config_reader_kernel_1<mss,msv,tokenizer>::
block (
const std::string& name
) const
{
if (is_block_defined(name) == false)
{
throw config_reader_access_error(name,"");
}
return *static_cast<config_reader_kernel_1*>(block_table[name]);
}
// ----------------------------------------------------------------------------------------
template <
typename map_string_string,
typename map_string_void,
typename tokenizer
>
const std::string& config_reader_kernel_1<map_string_string,map_string_void,tokenizer>::
operator[] (
const std::string& key
) const
{
if (is_key_defined(key) == false)
{
throw config_reader_access_error("",key);
}
return key_table[key];
}
// ----------------------------------------------------------------------------------------
template <
typename map_string_string,
typename map_string_void,
typename tokenizer
>
template <
typename queue_of_strings
>
void config_reader_kernel_1<map_string_string,map_string_void,tokenizer>::
get_keys (
queue_of_strings& keys
) const
{
keys.clear();
key_table.reset();
std::string temp;
while (key_table.move_next())
{
temp = key_table.element().key();
keys.enqueue(temp);
}
}
// ----------------------------------------------------------------------------------------
template <
typename map_string_string,
typename map_string_void,
typename tokenizer
>
template <
typename alloc
>
void config_reader_kernel_1<map_string_string,map_string_void,tokenizer>::
get_keys (
std::vector<std::string,alloc>& keys
) const
{
keys.clear();
key_table.reset();
while (key_table.move_next())
{
keys.push_back(key_table.element().key());
}
}
// ----------------------------------------------------------------------------------------
template <
typename map_string_string,
typename map_string_void,
typename tokenizer
>
template <
typename alloc
>
void config_reader_kernel_1<map_string_string,map_string_void,tokenizer>::
get_keys (
std_vector_c<std::string,alloc>& keys
) const
{
keys.clear();
key_table.reset();
while (key_table.move_next())
{
keys.push_back(key_table.element().key());
}
}
// ----------------------------------------------------------------------------------------
template <
typename map_string_string,
typename map_string_void,
typename tokenizer
>
template <
typename queue_of_strings
>
void config_reader_kernel_1<map_string_string,map_string_void,tokenizer>::
get_blocks (
queue_of_strings& blocks
) const
{
blocks.clear();
block_table.reset();
std::string temp;
while (block_table.move_next())
{
temp = block_table.element().key();
blocks.enqueue(temp);
}
}
// ----------------------------------------------------------------------------------------
template <
typename map_string_string,
typename map_string_void,
typename tokenizer
>
template <
typename alloc
>
void config_reader_kernel_1<map_string_string,map_string_void,tokenizer>::
get_blocks (
std::vector<std::string,alloc>& blocks
) const
{
blocks.clear();
block_table.reset();
while (block_table.move_next())
{
blocks.push_back(block_table.element().key());
}
}
// ----------------------------------------------------------------------------------------
template <
typename map_string_string,
typename map_string_void,
typename tokenizer
>
template <
typename alloc
>
void config_reader_kernel_1<map_string_string,map_string_void,tokenizer>::
get_blocks (
std_vector_c<std::string,alloc>& blocks
) const
{
blocks.clear();
block_table.reset();
while (block_table.move_next())
{
blocks.push_back(block_table.element().key());
}
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_CONFIG_READER_KERNEl_1_

View File

@@ -0,0 +1,363 @@
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_CONFIG_READER_KERNEl_ABSTRACT_
#ifdef DLIB_CONFIG_READER_KERNEl_ABSTRACT_
#include <string>
#include <iosfwd>
namespace dlib
{
class config_reader
{
/*!
INITIAL VALUE
- there aren't any keys defined for this object
- there aren't any blocks defined for this object
POINTERS AND REFERENCES TO INTERNAL DATA
The destructor, clear(), and load_from() invalidate pointers
and references to internal data. All other functions are guaranteed
to NOT invalidate pointers or references to internal data.
WHAT THIS OBJECT REPRESENTS
This object represents something which is intended to be used to read
text configuration files that are defined by the following EBNF (with
config_file as the starting symbol):
config_file = block;
block = { key_value_pair | sub_block };
key_value_pair = key_name, "=", value;
sub_block = block_name, "{", block, "}";
key_name = identifier;
block_name = identifier;
value = matches any string of text that ends with a newline character, # or }.
note that the trailing newline, # or } is not part of the value though.
identifier = Any string that matches the following regular expression:
[a-zA-Z][a-zA-Z0-9_-\.]*
i.e. Any string that starts with a letter and then is continued
with any number of letters, numbers, _ . or - characters.
Whitespace and comments are ignored. A comment is text that starts with # (but not \#
since the \ escapes the # so that you can have a # symbol in a value if you want) and
ends in a new line. You can also escape a } (e.g. "\}") if you want to have one in a
value.
Note that in a value the leading and trailing white spaces are stripped off but any
white space inside the value is preserved.
Also note that all key_names and block_names within a block syntax group must be unique
but don't have to be globally unique. I.e. different blocks can reuse names.
EXAMPLE CONFIG FILES:
Example 1:
#comment. This line is ignored because it starts with #
#here we have key1 which will have the value of "my value"
key1 = my value
another_key= another value # this is another key called "another_key" with
# a value of "another value"
# this key's value is the empty string. I.e. ""
key2=
Example 2:
#this example illustrates the use of blocks
some_key = blah blah
# now here is a block
our_block
{
# here we can define some keys and values that are local to this block.
a_key = something
foo = bar
some_key = more stuff # note that it is ok to name our key this even though
# there is a key called some_key above. This is because
# we are doing so inside a different block
}
another_block { foo = bar2 } # this block has only one key and is all on a single line
!*/
public:
// exception classes
class config_reader_error : public dlib::error
{
/*!
GENERAL
This exception is thrown if there is an error while parsing the
config file. The type member of this exception will be set
to ECONFIG_READER.
INTERPRETING THIS EXCEPTION
- line_number == the line number the parser was at when the
error occurred.
- if (redefinition) then
- The key or block name on line line_number has already
been defined in this scope which is an error.
- else
- Some other general syntax error was detected
!*/
public:
const unsigned long line_number;
const bool redefinition;
};
class file_not_found : public dlib::error
{
/*!
GENERAL
This exception is thrown if the config file can't be opened for
some reason. The type member of this exception will be set
to ECONFIG_READER.
INTERPRETING THIS EXCEPTION
- file_name == the name of the config file which we failed to open
!*/
public:
const std::string file_name;
};
class config_reader_access_error : public dlib::error
{
/*!
GENERAL
This exception is thrown if you try to access a key or
block that doesn't exist inside a config reader. The type
member of this exception will be set to ECONFIG_READER.
!*/
public:
config_reader_access_error(
const std::string& block_name_,
const std::string& key_name_
);
/*!
ensures
- #block_name == block_name_
- #key_name == key_name_
!*/
const std::string block_name;
const std::string key_name;
};
// --------------------------
config_reader(
);
/*!
ensures
- #*this is properly initialized
- This object will not have any keys or blocks defined in it.
throws
- std::bad_alloc
- config_reader_error
!*/
config_reader(
std::istream& in
);
/*!
ensures
- #*this is properly initialized
- reads the config file to parse from the given input stream,
parses it and loads this object up with all the sub blocks and
key/value pairs it finds.
- before the load is performed, the previous state of the config file
reader is erased. So after the load the config file reader will contain
only information from the given config file.
- This object will represent the top most block of the config file.
throws
- std::bad_alloc
- config_reader_error
!*/
config_reader(
const std::string& config_file
);
/*!
ensures
- #*this is properly initialized
- parses the config file named by the config_file string. Specifically,
parses it and loads this object up with all the sub blocks and
key/value pairs it finds in the file.
- before the load is performed, the previous state of the config file
reader is erased. So after the load the config file reader will contain
only information from the given config file.
- This object will represent the top most block of the config file.
throws
- std::bad_alloc
- config_reader_error
- file_not_found
!*/
virtual ~config_reader(
);
/*!
ensures
- all memory associated with *this has been released
!*/
void clear(
);
/*!
ensures
- #*this has its initial value
throws
- std::bad_alloc
If this exception is thrown then *this is unusable
until clear() is called and succeeds
!*/
void load_from (
std::istream& in
);
/*!
ensures
- reads the config file to parse from the given input stream,
parses it and loads this object up with all the sub blocks and
key/value pairs it finds.
- before the load is performed, the previous state of the config file
reader is erased. So after the load the config file reader will contain
only information from the given config file.
- *this will represent the top most block of the config file contained
in the input stream in.
throws
- std::bad_alloc
If this exception is thrown then *this is unusable
until clear() is called and succeeds
- config_reader_error
If this exception is thrown then this object will
revert to its initial value.
!*/
void load_from (
const std::string& config_file
);
/*!
ensures
- parses the config file named by the config_file string. Specifically,
parses it and loads this object up with all the sub blocks and
key/value pairs it finds in the file.
- before the load is performed, the previous state of the config file
reader is erased. So after the load the config file reader will contain
only information from the given config file.
- This object will represent the top most block of the config file.
throws
- std::bad_alloc
If this exception is thrown then *this is unusable
until clear() is called and succeeds
- config_reader_error
If this exception is thrown then this object will
revert to its initial value.
- file_not_found
If this exception is thrown then this object will
revert to its initial value.
!*/
bool is_key_defined (
const std::string& key_name
) const;
/*!
ensures
- if (there is a key with the given name defined within this config_reader's block) then
- returns true
- else
- returns false
!*/
bool is_block_defined (
const std::string& block_name
) const;
/*!
ensures
- if (there is a sub block with the given name defined within this config_reader's block) then
- returns true
- else
- returns false
!*/
typedef config_reader this_type;
const this_type& block (
const std::string& block_name
) const;
/*!
ensures
- if (is_block_defined(block_name) == true) then
- returns a const reference to the config_reader that represents the given named sub block
- else
- throws config_reader_access_error
throws
- config_reader_access_error
if this exception is thrown then its block_name field will be set to the
given block_name string.
!*/
const std::string& operator[] (
const std::string& key_name
) const;
/*!
ensures
- if (is_key_defined(key_name) == true) then
- returns a const reference to the value string associated with the given key in
this config_reader's block.
- else
- throws config_reader_access_error
throws
- config_reader_access_error
if this exception is thrown then its key_name field will be set to the
given key_name string.
!*/
template <
typename queue_of_strings
>
void get_keys (
queue_of_strings& keys
) const;
/*!
requires
- queue_of_strings is an implementation of queue/queue_kernel_abstract.h
with T set to std::string, or std::vector<std::string>, or
dlib::std_vector_c<std::string>
ensures
- #keys == a collection containing all the keys defined in this config_reader's block.
(i.e. for all strings str in keys it is the case that is_key_defined(str) == true)
!*/
template <
typename queue_of_strings
>
void get_blocks (
queue_of_strings& blocks
) const;
/*!
requires
- queue_of_strings is an implementation of queue/queue_kernel_abstract.h
with T set to std::string, or std::vector<std::string>, or
dlib::std_vector_c<std::string>
ensures
- #blocks == a collection containing the names of all the blocks defined in this
config_reader's block.
(i.e. for all strings str in blocks it is the case that is_block_defined(str) == true)
!*/
private:
// restricted functions
config_reader(config_reader&); // copy constructor
config_reader& operator=(config_reader&); // assignment operator
};
}
#endif // DLIB_CONFIG_READER_KERNEl_ABSTRACT_

View File

@@ -0,0 +1,456 @@
// 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_

View File

@@ -0,0 +1,45 @@
// Copyright (C) 2007 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_CONFIG_READER_THREAD_SAFe_ABSTRACT_
#ifdef DLIB_CONFIG_READER_THREAD_SAFe_ABSTRACT_
#include <string>
#include <iosfwd>
#include "config_reader_kernel_abstract.h"
#include "../threads/threads_kernel_abstract.h"
namespace dlib
{
class config_reader_thread_safe
{
/*!
WHAT THIS EXTENSION DOES FOR config_reader
This object extends a normal config_reader by simply wrapping all
its member functions inside mutex locks to make it safe to use
in a threaded program.
So this object provides an interface identical to the one defined
in the config_reader/config_reader_kernel_abstract.h file except that
the rmutex returned by get_mutex() is always locked when this
object's member functions are called.
!*/
public:
const rmutex& get_mutex (
) const;
/*!
ensures
- returns the rmutex used to make this object thread safe. i.e. returns
the rmutex that is locked when this object's functions are called.
!*/
};
}
#endif // DLIB_CONFIG_READER_THREAD_SAFe_ABSTRACT_