Lesson 35 - Get Compute Auth Token Working

This commit is contained in:
Norman Lansing
2026-02-28 12:32:28 -05:00
parent 1d477ee42a
commit 4fde462bce
7743 changed files with 1397833 additions and 18 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,10 @@
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_ARRAy_
#define DLIB_ARRAy_
#include "array/array_kernel.h"
#include "array/array_tools.h"
#endif // DLIB_ARRAy_

View File

@@ -0,0 +1,809 @@
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_ARRAY_KERNEl_2_
#define DLIB_ARRAY_KERNEl_2_
#include "array_kernel_abstract.h"
#include "../interfaces/enumerable.h"
#include "../algs.h"
#include "../serialize.h"
#include "../sort.h"
#include "../is_kind.h"
namespace dlib
{
template <
typename T,
typename mem_manager = default_memory_manager
>
class array : public enumerable<T>
{
/*!
INITIAL VALUE
- array_size == 0
- max_array_size == 0
- array_elements == 0
- pos == 0
- last_pos == 0
- _at_start == true
CONVENTION
- array_size == size()
- max_array_size == max_size()
- if (max_array_size > 0)
- array_elements == pointer to max_array_size elements of type T
- else
- array_elements == 0
- if (array_size > 0)
- last_pos == array_elements + array_size - 1
- else
- last_pos == 0
- at_start() == _at_start
- current_element_valid() == pos != 0
- if (current_element_valid()) then
- *pos == element()
!*/
public:
// These typedefs are here for backwards compatibility with old versions of dlib.
typedef array kernel_1a;
typedef array kernel_1a_c;
typedef array kernel_2a;
typedef array kernel_2a_c;
typedef array sort_1a;
typedef array sort_1a_c;
typedef array sort_1b;
typedef array sort_1b_c;
typedef array sort_2a;
typedef array sort_2a_c;
typedef array sort_2b;
typedef array sort_2b_c;
typedef array expand_1a;
typedef array expand_1a_c;
typedef array expand_1b;
typedef array expand_1b_c;
typedef array expand_1c;
typedef array expand_1c_c;
typedef array expand_1d;
typedef array expand_1d_c;
typedef T type;
typedef T value_type;
typedef mem_manager mem_manager_type;
array (
) :
array_size(0),
max_array_size(0),
array_elements(0),
pos(0),
last_pos(0),
_at_start(true)
{}
array(const array&) = delete;
array& operator=(array&) = delete;
array(
array&& item
) : array()
{
swap(item);
}
array& operator=(
array&& item
)
{
swap(item);
return *this;
}
explicit array (
size_t new_size
) :
array_size(0),
max_array_size(0),
array_elements(0),
pos(0),
last_pos(0),
_at_start(true)
{
resize(new_size);
}
~array (
);
void clear (
);
inline const T& operator[] (
size_t pos
) const;
inline T& operator[] (
size_t pos
);
void set_size (
size_t size
);
inline size_t max_size(
) const;
void set_max_size(
size_t max
);
void swap (
array& item
);
// functions from the enumerable interface
inline size_t size (
) const;
inline bool at_start (
) const;
inline void reset (
) const;
bool current_element_valid (
) const;
inline const T& element (
) const;
inline T& element (
);
bool move_next (
) const;
void sort (
);
void resize (
size_t new_size
);
const T& back (
) const;
T& back (
);
void pop_back (
);
void pop_back (
T& item
);
void push_back (
T& item
);
void push_back (
T&& item
);
typedef T* iterator;
typedef const T* const_iterator;
iterator begin() { return array_elements; }
const_iterator begin() const { return array_elements; }
iterator end() { return array_elements+array_size; }
const_iterator end() const { return array_elements+array_size; }
private:
typename mem_manager::template rebind<T>::other pool;
// data members
size_t array_size;
size_t max_array_size;
T* array_elements;
mutable T* pos;
T* last_pos;
mutable bool _at_start;
};
template <
typename T,
typename mem_manager
>
inline void swap (
array<T,mem_manager>& a,
array<T,mem_manager>& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
void serialize (
const array<T,mem_manager>& item,
std::ostream& out
)
{
try
{
serialize(item.max_size(),out);
serialize(item.size(),out);
for (size_t i = 0; i < item.size(); ++i)
serialize(item[i],out);
}
catch (serialization_error& e)
{
throw serialization_error(e.info + "\n while serializing object of type array");
}
}
template <
typename T,
typename mem_manager
>
void deserialize (
array<T,mem_manager>& item,
std::istream& in
)
{
try
{
size_t max_size, size;
deserialize(max_size,in);
deserialize(size,in);
item.set_max_size(max_size);
item.set_size(size);
for (size_t i = 0; i < size; ++i)
deserialize(item[i],in);
}
catch (serialization_error& e)
{
item.clear();
throw serialization_error(e.info + "\n while deserializing object of type array");
}
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
array<T,mem_manager>::
~array (
)
{
if (array_elements)
{
pool.deallocate_array(array_elements);
}
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
void array<T,mem_manager>::
clear (
)
{
reset();
last_pos = 0;
array_size = 0;
if (array_elements)
{
pool.deallocate_array(array_elements);
}
array_elements = 0;
max_array_size = 0;
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
const T& array<T,mem_manager>::
operator[] (
size_t pos
) const
{
// make sure requires clause is not broken
DLIB_ASSERT( pos < this->size() ,
"\tconst T& array::operator[]"
<< "\n\tpos must < size()"
<< "\n\tpos: " << pos
<< "\n\tsize(): " << this->size()
<< "\n\tthis: " << this
);
return array_elements[pos];
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
T& array<T,mem_manager>::
operator[] (
size_t pos
)
{
// make sure requires clause is not broken
DLIB_ASSERT( pos < this->size() ,
"\tT& array::operator[]"
<< "\n\tpos must be < size()"
<< "\n\tpos: " << pos
<< "\n\tsize(): " << this->size()
<< "\n\tthis: " << this
);
return array_elements[pos];
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
void array<T,mem_manager>::
set_size (
size_t size
)
{
// make sure requires clause is not broken
DLIB_CASSERT(( size <= this->max_size() ),
"\tvoid array::set_size"
<< "\n\tsize must be <= max_size()"
<< "\n\tsize: " << size
<< "\n\tmax size: " << this->max_size()
<< "\n\tthis: " << this
);
reset();
array_size = size;
if (size > 0)
last_pos = array_elements + size - 1;
else
last_pos = 0;
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
size_t array<T,mem_manager>::
size (
) const
{
return array_size;
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
void array<T,mem_manager>::
set_max_size(
size_t max
)
{
reset();
array_size = 0;
last_pos = 0;
if (max != 0)
{
// if new max size is different
if (max != max_array_size)
{
if (array_elements)
{
pool.deallocate_array(array_elements);
}
// try to get more memroy
try { array_elements = pool.allocate_array(max); }
catch (...) { array_elements = 0; max_array_size = 0; throw; }
max_array_size = max;
}
}
// if the array is being made to be zero
else
{
if (array_elements)
pool.deallocate_array(array_elements);
max_array_size = 0;
array_elements = 0;
}
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
size_t array<T,mem_manager>::
max_size (
) const
{
return max_array_size;
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
void array<T,mem_manager>::
swap (
array<T,mem_manager>& item
)
{
auto array_size_temp = item.array_size;
auto max_array_size_temp = item.max_array_size;
T* array_elements_temp = item.array_elements;
item.array_size = array_size;
item.max_array_size = max_array_size;
item.array_elements = array_elements;
array_size = array_size_temp;
max_array_size = max_array_size_temp;
array_elements = array_elements_temp;
exchange(_at_start,item._at_start);
exchange(pos,item.pos);
exchange(last_pos,item.last_pos);
pool.swap(item.pool);
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// enumerable function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
bool array<T,mem_manager>::
at_start (
) const
{
return _at_start;
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
void array<T,mem_manager>::
reset (
) const
{
_at_start = true;
pos = 0;
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
bool array<T,mem_manager>::
current_element_valid (
) const
{
return pos != 0;
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
const T& array<T,mem_manager>::
element (
) const
{
// make sure requires clause is not broken
DLIB_ASSERT(this->current_element_valid(),
"\tconst T& array::element()"
<< "\n\tThe current element must be valid if you are to access it."
<< "\n\tthis: " << this
);
return *pos;
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
T& array<T,mem_manager>::
element (
)
{
// make sure requires clause is not broken
DLIB_ASSERT(this->current_element_valid(),
"\tT& array::element()"
<< "\n\tThe current element must be valid if you are to access it."
<< "\n\tthis: " << this
);
return *pos;
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
bool array<T,mem_manager>::
move_next (
) const
{
if (!_at_start)
{
if (pos < last_pos)
{
++pos;
return true;
}
else
{
pos = 0;
return false;
}
}
else
{
_at_start = false;
if (array_size > 0)
{
pos = array_elements;
return true;
}
else
{
return false;
}
}
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// Yet more functions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
void array<T,mem_manager>::
sort (
)
{
if (this->size() > 1)
{
// call the quick sort function for arrays that is in algs.h
dlib::qsort_array(*this,0,this->size()-1);
}
this->reset();
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
void array<T,mem_manager>::
resize (
size_t new_size
)
{
if (this->max_size() < new_size)
{
array temp;
temp.set_max_size(new_size);
temp.set_size(new_size);
for (size_t i = 0; i < this->size(); ++i)
{
exchange((*this)[i],temp[i]);
}
temp.swap(*this);
}
else
{
this->set_size(new_size);
}
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
T& array<T,mem_manager>::
back (
)
{
// make sure requires clause is not broken
DLIB_ASSERT( this->size() > 0 ,
"\tT& array::back()"
<< "\n\tsize() must be bigger than 0"
<< "\n\tsize(): " << this->size()
<< "\n\tthis: " << this
);
return (*this)[this->size()-1];
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
const T& array<T,mem_manager>::
back (
) const
{
// make sure requires clause is not broken
DLIB_ASSERT( this->size() > 0 ,
"\tconst T& array::back()"
<< "\n\tsize() must be bigger than 0"
<< "\n\tsize(): " << this->size()
<< "\n\tthis: " << this
);
return (*this)[this->size()-1];
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
void array<T,mem_manager>::
pop_back (
T& item
)
{
// make sure requires clause is not broken
DLIB_ASSERT( this->size() > 0 ,
"\tvoid array::pop_back()"
<< "\n\tsize() must be bigger than 0"
<< "\n\tsize(): " << this->size()
<< "\n\tthis: " << this
);
exchange(item,(*this)[this->size()-1]);
this->set_size(this->size()-1);
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
void array<T,mem_manager>::
pop_back (
)
{
// make sure requires clause is not broken
DLIB_ASSERT( this->size() > 0 ,
"\tvoid array::pop_back()"
<< "\n\tsize() must be bigger than 0"
<< "\n\tsize(): " << this->size()
<< "\n\tthis: " << this
);
this->set_size(this->size()-1);
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
void array<T,mem_manager>::
push_back (
T& item
)
{
if (this->max_size() == this->size())
{
// double the size of the array
array temp;
temp.set_max_size(this->size()*2 + 1);
temp.set_size(this->size()+1);
for (size_t i = 0; i < this->size(); ++i)
{
exchange((*this)[i],temp[i]);
}
exchange(item,temp[temp.size()-1]);
temp.swap(*this);
}
else
{
this->set_size(this->size()+1);
exchange(item,(*this)[this->size()-1]);
}
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
void array<T,mem_manager>::
push_back (
T&& item
) { push_back(item); }
// ----------------------------------------------------------------------------------------
template <typename T, typename MM>
struct is_array <array<T,MM> >
{
const static bool value = true;
};
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_ARRAY_KERNEl_2_

View File

@@ -0,0 +1,360 @@
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_ARRAY_KERNEl_ABSTRACT_
#ifdef DLIB_ARRAY_KERNEl_ABSTRACT_
#include "../interfaces/enumerable.h"
#include "../serialize.h"
#include "../algs.h"
namespace dlib
{
template <
typename T,
typename mem_manager = default_memory_manager
>
class array : public enumerable<T>
{
/*!
REQUIREMENTS ON T
T must have a default constructor.
REQUIREMENTS ON mem_manager
must be an implementation of memory_manager/memory_manager_kernel_abstract.h or
must be an implementation of memory_manager_global/memory_manager_global_kernel_abstract.h or
must be an implementation of memory_manager_stateless/memory_manager_stateless_kernel_abstract.h
mem_manager::type can be set to anything.
POINTERS AND REFERENCES TO INTERNAL DATA
front(), back(), swap(), max_size(), set_size(), and operator[]
functions do not invalidate pointers or references to internal data.
All other functions have no such guarantee.
INITIAL VALUE
size() == 0
max_size() == 0
ENUMERATION ORDER
The enumerator will iterate over the elements of the array in the
order (*this)[0], (*this)[1], (*this)[2], ...
WHAT THIS OBJECT REPRESENTS
This object represents an ordered 1-dimensional array of items,
each item is associated with an integer value. The items are
numbered from 0 though size() - 1 and the operator[] functions
run in constant time.
Also note that unless specified otherwise, no member functions
of this object throw exceptions.
!*/
public:
typedef T type;
typedef T value_type;
typedef mem_manager mem_manager_type;
array (
);
/*!
ensures
- #*this is properly initialized
throws
- std::bad_alloc or any exception thrown by T's constructor
!*/
explicit array (
size_t new_size
);
/*!
ensures
- #*this is properly initialized
- #size() == new_size
- #max_size() == new_size
- All elements of the array will have initial values for their type.
throws
- std::bad_alloc or any exception thrown by T's constructor
!*/
~array (
);
/*!
ensures
- all memory associated with *this has been released
!*/
array(
array&& item
);
/*!
ensures
- move constructs *this from item. Therefore, the state of item is
moved into *this and #item has a valid but unspecified state.
!*/
array& operator=(
array&& item
);
/*!
ensures
- move assigns *this from item. Therefore, the state of item is
moved into *this and #item has a valid but unspecified state.
- returns a reference to #*this
!*/
void clear (
);
/*!
ensures
- #*this has its initial value
throws
- std::bad_alloc or any exception thrown by T's constructor
if this exception is thrown then the array object is unusable
until clear() is called and succeeds
!*/
const T& operator[] (
size_t pos
) const;
/*!
requires
- pos < size()
ensures
- returns a const reference to the element at position pos
!*/
T& operator[] (
size_t pos
);
/*!
requires
- pos < size()
ensures
- returns a non-const reference to the element at position pos
!*/
void set_size (
size_t size
);
/*!
requires
- size <= max_size()
ensures
- #size() == size
- any element with index between 0 and size - 1 which was in the
array before the call to set_size() retains its value and index.
All other elements have undetermined (but valid for their type)
values. (e.g. this object might buffer old T objects and reuse
them without reinitializing them between calls to set_size())
- #at_start() == true
throws
- std::bad_alloc or any exception thrown by T's constructor
may throw this exception if there is not enough memory and
if it does throw then the call to set_size() has no effect
!*/
size_t max_size(
) const;
/*!
ensures
- returns the maximum size of *this
!*/
void set_max_size(
size_t max
);
/*!
ensures
- #max_size() == max
- #size() == 0
- #at_start() == true
throws
- std::bad_alloc or any exception thrown by T's constructor
may throw this exception if there is not enough
memory and if it does throw then max_size() == 0
!*/
void swap (
array<T>& item
);
/*!
ensures
- swaps *this and item
!*/
void sort (
);
/*!
requires
- T must be a type with that is comparable via operator<
ensures
- for all elements in #*this the ith element is <= the i+1 element
- #at_start() == true
throws
- std::bad_alloc or any exception thrown by T's constructor
data may be lost if sort() throws
!*/
void resize (
size_t new_size
);
/*!
ensures
- #size() == new_size
- #max_size() == max(new_size,max_size())
- for all i < size() && i < new_size:
- #(*this)[i] == (*this)[i]
(i.e. All the original elements of *this which were at index
values less than new_size are unmodified.)
- for all valid i >= size():
- #(*this)[i] has an undefined value
(i.e. any new elements of the array have an undefined value)
throws
- std::bad_alloc or any exception thrown by T's constructor.
If an exception is thrown then it has no effect on *this.
!*/
const T& back (
) const;
/*!
requires
- size() != 0
ensures
- returns a const reference to (*this)[size()-1]
!*/
T& back (
);
/*!
requires
- size() != 0
ensures
- returns a non-const reference to (*this)[size()-1]
!*/
void pop_back (
T& item
);
/*!
requires
- size() != 0
ensures
- #size() == size() - 1
- swaps (*this)[size()-1] into item
- All elements with an index less than size()-1 are
unmodified by this operation.
!*/
void pop_back (
);
/*!
requires
- size() != 0
ensures
- #size() == size() - 1
- All elements with an index less than size()-1 are
unmodified by this operation.
!*/
void push_back (
T& item
);
/*!
ensures
- #size() == size()+1
- swaps item into (*this)[#size()-1]
- #back() == item
- #item has some undefined value (whatever happens to
get swapped out of the array)
throws
- std::bad_alloc or any exception thrown by T's constructor.
If an exception is thrown then it has no effect on *this.
!*/
void push_back (T&& item) { push_back(item); }
/*!
enable push_back from rvalues
!*/
typedef T* iterator;
typedef const T* const_iterator;
iterator begin(
);
/*!
ensures
- returns an iterator that points to the first element in this array or
end() if the array is empty.
!*/
const_iterator begin(
) const;
/*!
ensures
- returns a const iterator that points to the first element in this
array or end() if the array is empty.
!*/
iterator end(
);
/*!
ensures
- returns an iterator that points to one past the end of the array.
!*/
const_iterator end(
) const;
/*!
ensures
- returns a const iterator that points to one past the end of the
array.
!*/
private:
// restricted functions
array(array<T>&); // copy constructor
array<T>& operator=(array<T>&); // assignment operator
};
template <
typename T
>
inline void swap (
array<T>& a,
array<T>& b
) { a.swap(b); }
/*!
provides a global swap function
!*/
template <
typename T
>
void serialize (
const array<T>& item,
std::ostream& out
);
/*!
provides serialization support
!*/
template <
typename T
>
void deserialize (
array<T>& item,
std::istream& in
);
/*!
provides deserialization support
!*/
}
#endif // DLIB_ARRAY_KERNEl_ABSTRACT_

View File

@@ -0,0 +1,38 @@
// Copyright (C) 2013 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_ARRAY_tOOLS_H_
#define DLIB_ARRAY_tOOLS_H_
#include "../assert.h"
#include "array_tools_abstract.h"
namespace dlib
{
template <typename T>
void split_array (
T& a,
T& b,
double frac
)
{
// make sure requires clause is not broken
DLIB_ASSERT(0 <= frac && frac <= 1,
"\t void split_array()"
<< "\n\t frac must be between 0 and 1."
<< "\n\t frac: " << frac
);
const unsigned long asize = static_cast<unsigned long>(a.size()*frac);
const unsigned long bsize = a.size()-asize;
b.resize(bsize);
for (unsigned long i = 0; i < b.size(); ++i)
{
swap(b[i], a[i+asize]);
}
a.resize(asize);
}
}
#endif // DLIB_ARRAY_tOOLS_H_

View File

@@ -0,0 +1,33 @@
// Copyright (C) 2013 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_ARRAY_tOOLS_ABSTRACT_H_
#ifdef DLIB_ARRAY_tOOLS_ABSTRACT_H_
#include "array_kernel_abstract.h"
namespace dlib
{
template <typename T>
void split_array (
T& a,
T& b,
double frac
);
/*!
requires
- 0 <= frac <= 1
- T must be an array type such as dlib::array or std::vector
ensures
- This function takes the elements of a and splits them into two groups. The
first group remains in a and the second group is put into b. The ordering of
elements in a is preserved. In particular, concatenating #a with #b will
reproduce the original contents of a.
- The elements in a are moved around using global swap(). So they must be
swappable, but do not need to be copyable.
- #a.size() == floor(a.size()*frac)
- #b.size() == a.size()-#a.size()
!*/
}
#endif // DLIB_ARRAY_tOOLS_ABSTRACT_H_

View File

@@ -0,0 +1,217 @@
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_ASSERt_
#define DLIB_ASSERt_
#include "config.h"
#include <sstream>
#include <iosfwd>
#include "error.h"
// -----------------------------
// Use some stuff from boost here
// (C) Copyright John Maddock 2001 - 2003.
// (C) Copyright Darin Adler 2001.
// (C) Copyright Peter Dimov 2001.
// (C) Copyright Bill Kempf 2002.
// (C) Copyright Jens Maurer 2002.
// (C) Copyright David Abrahams 2002 - 2003.
// (C) Copyright Gennaro Prota 2003.
// (C) Copyright Eric Friedman 2003.
// License: Boost Software License See LICENSE.txt for the full license.
//
#ifndef DLIB_BOOST_JOIN
#define DLIB_BOOST_JOIN( X, Y ) DLIB_BOOST_DO_JOIN( X, Y )
#define DLIB_BOOST_DO_JOIN( X, Y ) DLIB_BOOST_DO_JOIN2(X,Y)
#define DLIB_BOOST_DO_JOIN2( X, Y ) X##Y
#endif
// figure out if the compiler has rvalue references.
#if defined(__clang__)
# if __has_feature(cxx_rvalue_references)
# define DLIB_HAS_RVALUE_REFERENCES
# endif
# if __has_feature(cxx_generalized_initializers)
# define DLIB_HAS_INITIALIZER_LISTS
# endif
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) && defined(__GXX_EXPERIMENTAL_CXX0X__)
# define DLIB_HAS_RVALUE_REFERENCES
# define DLIB_HAS_INITIALIZER_LISTS
#elif defined(_MSC_VER) && _MSC_VER >= 1800
# define DLIB_HAS_INITIALIZER_LISTS
# define DLIB_HAS_RVALUE_REFERENCES
#elif defined(_MSC_VER) && _MSC_VER >= 1600
# define DLIB_HAS_RVALUE_REFERENCES
#elif defined(__INTEL_COMPILER) && defined(BOOST_INTEL_STDCXX0X)
# define DLIB_HAS_RVALUE_REFERENCES
# define DLIB_HAS_INITIALIZER_LISTS
#endif
#if defined(__APPLE__) && defined(__GNUC_LIBSTD__) && ((__GNUC_LIBSTD__-0) * 100 + __GNUC_LIBSTD_MINOR__-0 <= 402)
// Apple has not updated libstdc++ in some time and anything under 4.02 does not have <initializer_list> for sure.
# undef DLIB_HAS_INITIALIZER_LISTS
#endif
// figure out if the compiler has static_assert.
#if defined(__clang__)
# if __has_feature(cxx_static_assert)
# define DLIB_HAS_STATIC_ASSERT
# endif
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) && defined(__GXX_EXPERIMENTAL_CXX0X__)
# define DLIB_HAS_STATIC_ASSERT
#elif defined(_MSC_VER) && _MSC_VER >= 1600
# define DLIB_HAS_STATIC_ASSERT
#elif defined(__INTEL_COMPILER) && defined(BOOST_INTEL_STDCXX0X)
# define DLIB_HAS_STATIC_ASSERT
#endif
// -----------------------------
namespace dlib
{
template <bool value> struct compile_time_assert;
template <> struct compile_time_assert<true> { enum {value=1}; };
template <typename T, typename U> struct assert_are_same_type;
template <typename T> struct assert_are_same_type<T,T> {enum{value=1};};
template <typename T, typename U> struct assert_are_not_same_type {enum{value=1}; };
template <typename T> struct assert_are_not_same_type<T,T> {};
template <typename T, typename U> struct assert_types_match {enum{value=0};};
template <typename T> struct assert_types_match<T,T> {enum{value=1};};
}
// gcc 4.8 will warn about unused typedefs. But we use typedefs in some of the compile
// time assert macros so we need to make it not complain about them "not being used".
#ifdef __GNUC__
#define DLIB_NO_WARN_UNUSED __attribute__ ((unused))
#else
#define DLIB_NO_WARN_UNUSED
#endif
// Use the newer static_assert if it's available since it produces much more readable error
// messages.
#ifdef DLIB_HAS_STATIC_ASSERT
#define COMPILE_TIME_ASSERT(expression) static_assert(expression, "Failed assertion")
#define ASSERT_ARE_SAME_TYPE(type1, type2) static_assert(::dlib::assert_types_match<type1,type2>::value, "These types should be the same but aren't.")
#define ASSERT_ARE_NOT_SAME_TYPE(type1, type2) static_assert(!::dlib::assert_types_match<type1,type2>::value, "These types should NOT be the same.")
#else
#define COMPILE_TIME_ASSERT(expression) \
DLIB_NO_WARN_UNUSED typedef char DLIB_BOOST_JOIN(DLIB_CTA, __LINE__)[::dlib::compile_time_assert<(bool)(expression)>::value]
#define ASSERT_ARE_SAME_TYPE(type1, type2) \
DLIB_NO_WARN_UNUSED typedef char DLIB_BOOST_JOIN(DLIB_AAST, __LINE__)[::dlib::assert_are_same_type<type1,type2>::value]
#define ASSERT_ARE_NOT_SAME_TYPE(type1, type2) \
DLIB_NO_WARN_UNUSED typedef char DLIB_BOOST_JOIN(DLIB_AANST, __LINE__)[::dlib::assert_are_not_same_type<type1,type2>::value]
#endif
// -----------------------------
#if defined DLIB_DISABLE_ASSERTS
// if DLIB_DISABLE_ASSERTS is on then never enable DLIB_ASSERT no matter what.
#undef ENABLE_ASSERTS
#endif
#if !defined(DLIB_DISABLE_ASSERTS) && ( defined DEBUG || defined _DEBUG)
// make sure ENABLE_ASSERTS is defined if we are indeed using them.
#ifndef ENABLE_ASSERTS
#define ENABLE_ASSERTS
#endif
#endif
// -----------------------------
#ifdef __GNUC__
// There is a bug in version 4.4.5 of GCC on Ubuntu which causes GCC to segfault
// when __PRETTY_FUNCTION__ is used within certain templated functions. So just
// don't use it with this version of GCC.
# if !(__GNUC__ == 4 && __GNUC_MINOR__ == 4 && __GNUC_PATCHLEVEL__ == 5)
# define DLIB_FUNCTION_NAME __PRETTY_FUNCTION__
# else
# define DLIB_FUNCTION_NAME "unknown function"
# endif
#elif defined(_MSC_VER)
#define DLIB_FUNCTION_NAME __FUNCSIG__
#else
#define DLIB_FUNCTION_NAME "unknown function"
#endif
#define DLIBM_CASSERT(_exp,_message) \
{if ( !(_exp) ) \
{ \
dlib_assert_breakpoint(); \
std::ostringstream dlib_o_out; \
dlib_o_out << "\n\nError detected at line " << __LINE__ << ".\n"; \
dlib_o_out << "Error detected in file " << __FILE__ << ".\n"; \
dlib_o_out << "Error detected in function " << DLIB_FUNCTION_NAME << ".\n\n"; \
dlib_o_out << "Failing expression was " << #_exp << ".\n"; \
dlib_o_out << std::boolalpha << _message << "\n"; \
throw dlib::fatal_error(dlib::EBROKEN_ASSERT,dlib_o_out.str()); \
}}
// This macro is not needed if you have a real C++ compiler. It's here to work around bugs in Visual Studio's preprocessor.
#define DLIB_WORKAROUND_VISUAL_STUDIO_BUGS(x) x
// Make it so the 2nd argument of DLIB_CASSERT is optional. That is, you can call it like
// DLIB_CASSERT(exp) or DLIB_CASSERT(exp,message).
#define DLIBM_CASSERT_1_ARGS(exp) DLIBM_CASSERT(exp,"")
#define DLIBM_CASSERT_2_ARGS(exp,message) DLIBM_CASSERT(exp,message)
#define DLIBM_GET_3TH_ARG(arg1, arg2, arg3, ...) arg3
#define DLIBM_CASSERT_CHOOSER(...) DLIB_WORKAROUND_VISUAL_STUDIO_BUGS(DLIBM_GET_3TH_ARG(__VA_ARGS__, DLIBM_CASSERT_2_ARGS, DLIBM_CASSERT_1_ARGS, DLIB_CASSERT_NEVER_USED))
#define DLIB_CASSERT(...) DLIB_WORKAROUND_VISUAL_STUDIO_BUGS(DLIBM_CASSERT_CHOOSER(__VA_ARGS__)(__VA_ARGS__))
#ifdef ENABLE_ASSERTS
#define DLIB_ASSERT(...) DLIB_CASSERT(__VA_ARGS__)
#define DLIB_IF_ASSERT(exp) exp
#else
#define DLIB_ASSERT(...) {}
#define DLIB_IF_ASSERT(exp)
#endif
// ----------------------------------------------------------------------------------------
/*!A DLIB_ASSERT_HAS_STANDARD_LAYOUT
This macro is meant to cause a compiler error if a type doesn't have a simple
memory layout (like a C struct). In particular, types with simple layouts are
ones which can be copied via memcpy().
This was called a POD type in C++03 and in C++0x we are looking to check if
it is a "standard layout type". Once we can use C++0x we can change this macro
to something that uses the std::is_standard_layout type_traits class.
See: http://www2.research.att.com/~bs/C++0xFAQ.html#PODs
!*/
// Use the fact that in C++03 you can't put non-PODs into a union.
#define DLIB_ASSERT_HAS_STANDARD_LAYOUT(type) \
union DLIB_BOOST_JOIN(DAHSL_,__LINE__) { type TYPE_NOT_STANDARD_LAYOUT; }; \
DLIB_NO_WARN_UNUSED typedef char DLIB_BOOST_JOIN(DAHSL2_,__LINE__)[sizeof(DLIB_BOOST_JOIN(DAHSL_,__LINE__))];
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// breakpoints
extern "C"
{
inline void dlib_assert_breakpoint(
) {}
/*!
ensures
- this function does nothing
It exists just so you can put breakpoints on it in a debugging tool.
It is called only when an DLIB_ASSERT or DLIB_CASSERT fails and is about to
throw an exception.
!*/
}
// -----------------------------
#include "stack_trace.h"
#endif // DLIB_ASSERt_

View File

@@ -0,0 +1,50 @@
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_BINARY_SEARCH_TREe_
#define DLIB_BINARY_SEARCH_TREe_
#include "binary_search_tree/binary_search_tree_kernel_1.h"
#include "binary_search_tree/binary_search_tree_kernel_2.h"
#include "binary_search_tree/binary_search_tree_kernel_c.h"
#include "algs.h"
#include <functional>
namespace dlib
{
template <
typename domain,
typename range,
typename mem_manager = default_memory_manager,
typename compare = std::less<domain>
>
class binary_search_tree
{
binary_search_tree() {}
public:
//----------- kernels ---------------
// kernel_1a
typedef binary_search_tree_kernel_1<domain,range,mem_manager,compare>
kernel_1a;
typedef binary_search_tree_kernel_c<kernel_1a>
kernel_1a_c;
// kernel_2a
typedef binary_search_tree_kernel_2<domain,range,mem_manager,compare>
kernel_2a;
typedef binary_search_tree_kernel_c<kernel_2a>
kernel_2a_c;
};
}
#endif // DLIB_BINARY_SEARCH_TREe_

View File

@@ -0,0 +1,311 @@
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_BINARY_SEARCH_TREE_KERNEl_ABSTRACT_
#ifdef DLIB_BINARY_SEARCH_TREE_KERNEl_ABSTRACT_
#include "../interfaces/map_pair.h"
#include "../interfaces/enumerable.h"
#include "../interfaces/remover.h"
#include "../serialize.h"
#include "../algs.h"
#include <functional>
namespace dlib
{
template <
typename domain,
typename range,
typename mem_manager = default_memory_manager,
typename compare = std::less<domain>
>
class binary_search_tree : public enumerable<map_pair<domain,range> >,
public asc_pair_remover<domain,range,compare>
{
/*!
REQUIREMENTS ON domain
domain must be comparable by compare where compare is a functor compatible with std::less and
domain is swappable by a global swap() and
domain must have a default constructor
REQUIREMENTS ON range
range is swappable by a global swap() and
range must have a default constructor
REQUIREMENTS ON mem_manager
must be an implementation of memory_manager/memory_manager_kernel_abstract.h or
must be an implementation of memory_manager_global/memory_manager_global_kernel_abstract.h or
must be an implementation of memory_manager_stateless/memory_manager_stateless_kernel_abstract.h
mem_manager::type can be set to anything.
POINTERS AND REFERENCES TO INTERNAL DATA
swap(), count(), height(), and operator[] functions
do not invalidate pointers or references to internal data.
position_enumerator() invalidates pointers or references to
data returned by element() and only by element() (i.e. pointers and
references returned by operator[] are still valid).
All other functions have no such guarantees.
INITIAL VALUE
size() == 0
height() == 0
ENUMERATION ORDER
The enumerator will iterate over the domain (and each associated
range element) elements in ascending order according to the compare functor.
(i.e. the elements are enumerated in sorted order)
WHAT THIS OBJECT REPRESENTS
this object represents a data dictionary that is built on top of some
kind of binary search tree. It maps objects of type domain to objects
of type range.
Also note that unless specified otherwise, no member functions
of this object throw exceptions.
NOTE:
definition of equivalent:
a is equivalent to b if
a < b == false and
b < a == false
!*/
public:
typedef domain domain_type;
typedef range range_type;
typedef compare compare_type;
typedef mem_manager mem_manager_type;
binary_search_tree(
);
/*!
ensures
- #*this is properly initialized
throws
- std::bad_alloc or any exception thrown by domain's or range's
constructor.
!*/
virtual ~binary_search_tree(
);
/*!
ensures
- all memory associated with *this has been released
!*/
void clear(
);
/*!
ensures
- #*this has its initial value
throws
- std::bad_alloc or any exception thrown by domain's or range's
constructor.
if this exception is thrown then *this is unusable
until clear() is called and succeeds
!*/
short height (
) const;
/*!
ensures
- returns the number of elements in the longest path from the root
of the tree to a leaf
!*/
unsigned long count (
const domain& d
) const;
/*!
ensures
- returns the number of elements in the domain of *this that are
equivalent to d
!*/
void add (
domain& d,
range& r
);
/*!
requires
- &d != &r (i.e. d and r cannot be the same variable)
ensures
- adds a mapping between d and r to *this
- if (count(d) == 0) then
- #*(*this)[d] == r
- else
- #(*this)[d] != 0
- #d and #r have initial values for their types
- #count(d) == count(d) + 1
- #at_start() == true
- #size() == size() + 1
throws
- std::bad_alloc or any exception thrown by domain's or range's
constructor.
if add() throws then it has no effect
!*/
void remove (
const domain& d,
domain& d_copy,
range& r
);
/*!
requires
- (*this)[d] != 0
- &d != &r (i.e. d and r cannot be the same variable)
- &d != &d_copy (i.e. d and d_copy cannot be the same variable)
- &r != &d_copy (i.e. r and d_copy cannot be the same variable)
ensures
- some element in the domain of *this that is equivalent to d has
been removed and swapped into #d_copy. Additionally, its
associated range element has been removed and swapped into #r.
- #count(d) == count(d) - 1
- #size() == size() - 1
- #at_start() == true
!*/
void destroy (
const domain& d
);
/*!
requires
- (*this)[d] != 0
ensures
- an element in the domain of *this equivalent to d has been removed.
The element in the range of *this associated with d has also been
removed.
- #count(d) == count(d) - 1
- #size() == size() - 1
- #at_start() == true
!*/
void remove_last_in_order (
domain& d,
range& r
);
/*!
requires
- size() > 0
ensures
- the last/biggest (according to the compare functor) element in the domain of *this has
been removed and swapped into #d. The element in the range of *this
associated with #d has also been removed and swapped into #r.
- #count(#d) == count(#d) - 1
- #size() == size() - 1
- #at_start() == true
!*/
void remove_current_element (
domain& d,
range& r
);
/*!
requires
- current_element_valid() == true
ensures
- the current element given by element() has been removed and swapped into d and r.
- #d == element().key()
- #r == element().value()
- #count(#d) == count(#d) - 1
- #size() == size() - 1
- moves the enumerator to the next element. If element() was the last
element in enumeration order then #current_element_valid() == false
and #at_start() == false.
!*/
void position_enumerator (
const domain& d
) const;
/*!
ensures
- #at_start() == false
- if (count(d) > 0) then
- #element().key() == d
- else if (there are any items in the domain of *this that are bigger than
d according to the compare functor) then
- #element().key() == the smallest item in the domain of *this that is
bigger than d according to the compare functor.
- else
- #current_element_valid() == false
!*/
const range* operator[] (
const domain& d
) const;
/*!
ensures
- if (there is an element in the domain equivalent to d) then
- returns a pointer to an element in the range of *this that
is associated with an element in the domain of *this
equivalent to d.
- else
- returns 0
!*/
range* operator[] (
const domain& d
);
/*!
ensures
- if (there is an element in the domain equivalent to d) then
- returns a pointer to an element in the range of *this that
is associated with an element in the domain of *this
equivalent to d.
- else
- returns 0
!*/
void swap (
binary_search_tree& item
);
/*!
ensures
- swaps *this and item
!*/
private:
// restricted functions
binary_search_tree(binary_search_tree&);
binary_search_tree& operator=(binary_search_tree&);
};
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
inline void swap (
binary_search_tree<domain,range,mem_manager,compare>& a,
binary_search_tree<domain,range,mem_manager,compare>& b
) { a.swap(b); }
/*!
provides a global swap function
!*/
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void deserialize (
binary_search_tree<domain,range,mem_manager,compare>& item,
std::istream& in
);
/*!
provides deserialization support
!*/
}
#endif // DLIB_BINARY_SEARCH_TREE_KERNEl_ABSTRACT_

View File

@@ -0,0 +1,235 @@
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_BINARY_SEARCH_TREE_KERNEl_C_
#define DLIB_BINARY_SEARCH_TREE_KERNEl_C_
#include "../interfaces/map_pair.h"
#include "binary_search_tree_kernel_abstract.h"
#include "../algs.h"
#include "../assert.h"
namespace dlib
{
template <
typename bst_base
>
class binary_search_tree_kernel_c : public bst_base
{
typedef typename bst_base::domain_type domain;
typedef typename bst_base::range_type range;
public:
binary_search_tree_kernel_c () {}
void remove (
const domain& d,
domain& d_copy,
range& r
);
void destroy (
const domain& d
);
void add (
domain& d,
range& r
);
void remove_any (
domain& d,
range& r
);
const map_pair<domain, range>& element(
) const
{
DLIB_CASSERT(this->current_element_valid() == true,
"\tconst map_pair<domain,range>& binary_search_tree::element() const"
<< "\n\tyou can't access the current element if it doesn't exist"
<< "\n\tthis: " << this
);
return bst_base::element();
}
map_pair<domain, range>& element(
)
{
DLIB_CASSERT(this->current_element_valid() == true,
"\tmap_pair<domain,range>& binary_search_tree::element()"
<< "\n\tyou can't access the current element if it doesn't exist"
<< "\n\tthis: " << this
);
return bst_base::element();
}
void remove_last_in_order (
domain& d,
range& r
);
void remove_current_element (
domain& d,
range& r
);
};
template <
typename bst_base
>
inline void swap (
binary_search_tree_kernel_c<bst_base>& a,
binary_search_tree_kernel_c<bst_base>& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename bst_base
>
void binary_search_tree_kernel_c<bst_base>::
add (
domain& d,
range& r
)
{
DLIB_CASSERT( static_cast<const void*>(&d) != static_cast<void*>(&r),
"\tvoid binary_search_tree::add"
<< "\n\tyou can't call add() and give the same object to both parameters."
<< "\n\tthis: " << this
<< "\n\t&d: " << &d
<< "\n\t&r: " << &r
<< "\n\tsize(): " << this->size()
);
bst_base::add(d,r);
}
// ----------------------------------------------------------------------------------------
template <
typename bst_base
>
void binary_search_tree_kernel_c<bst_base>::
destroy (
const domain& d
)
{
DLIB_CASSERT(this->operator[](d) != 0,
"\tvoid binary_search_tree::destroy"
<< "\n\tthe element must be in the tree for it to be removed"
<< "\n\tthis: " << this
<< "\n\t&d: " << &d
);
bst_base::destroy(d);
}
// ----------------------------------------------------------------------------------------
template <
typename bst_base
>
void binary_search_tree_kernel_c<bst_base>::
remove (
const domain& d,
domain& d_copy,
range& r
)
{
DLIB_CASSERT(this->operator[](d) != 0 &&
(static_cast<const void*>(&d) != static_cast<void*>(&d_copy)) &&
(static_cast<const void*>(&d) != static_cast<void*>(&r)) &&
(static_cast<const void*>(&r) != static_cast<void*>(&d_copy)),
"\tvoid binary_search_tree::remove"
<< "\n\tthe element must be in the tree for it to be removed"
<< "\n\tthis: " << this
<< "\n\t&d: " << &d
<< "\n\t&d_copy: " << &d_copy
<< "\n\t&r: " << &r
);
bst_base::remove(d,d_copy,r);
}
// ----------------------------------------------------------------------------------------
template <
typename bst_base
>
void binary_search_tree_kernel_c<bst_base>::
remove_any(
domain& d,
range& r
)
{
DLIB_CASSERT(this->size() != 0 &&
(static_cast<const void*>(&d) != static_cast<void*>(&r)),
"\tvoid binary_search_tree::remove_any"
<< "\n\ttree must not be empty if something is going to be removed"
<< "\n\tthis: " << this
<< "\n\t&d: " << &d
<< "\n\t&r: " << &r
);
bst_base::remove_any(d,r);
}
// ----------------------------------------------------------------------------------------
template <
typename bst_base
>
void binary_search_tree_kernel_c<bst_base>::
remove_last_in_order (
domain& d,
range& r
)
{
DLIB_CASSERT(this->size() > 0,
"\tvoid binary_search_tree::remove_last_in_order()"
<< "\n\tyou can't remove an element if it doesn't exist"
<< "\n\tthis: " << this
);
bst_base::remove_last_in_order(d,r);
}
// ----------------------------------------------------------------------------------------
template <
typename bst_base
>
void binary_search_tree_kernel_c<bst_base>::
remove_current_element (
domain& d,
range& r
)
{
DLIB_CASSERT(this->current_element_valid() == true,
"\tvoid binary_search_tree::remove_current_element()"
<< "\n\tyou can't remove the current element if it doesn't exist"
<< "\n\tthis: " << this
);
bst_base::remove_current_element(d,r);
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_BINARY_SEARCH_TREE_KERNEl_C_

View File

@@ -0,0 +1,10 @@
// Copyright (C) 2008 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_BOUND_FUNCTION_POINTEr_
#define DLIB_BOUND_FUNCTION_POINTEr_
#include "bound_function_pointer/bound_function_pointer_kernel_1.h"
#endif // DLIB_BOUND_FUNCTION_POINTEr_

View File

@@ -0,0 +1,774 @@
// Copyright (C) 2008 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_BOUND_FUNCTION_POINTER_KERNEl_1_
#define DLIB_BOUND_FUNCTION_POINTER_KERNEl_1_
#include "../algs.h"
#include "../member_function_pointer.h"
#include "bound_function_pointer_kernel_abstract.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
namespace bfp1_helpers
{
template <typename T> struct strip { typedef T type; };
template <typename T> struct strip<T&> { typedef T type; };
// ------------------------------------------------------------------------------------
class bound_function_helper_base_base
{
public:
virtual ~bound_function_helper_base_base(){}
virtual void call() const = 0;
virtual bool is_set() const = 0;
virtual void clone(void* ptr) const = 0;
};
// ------------------------------------------------------------------------------------
template <typename T1, typename T2, typename T3, typename T4>
class bound_function_helper_base : public bound_function_helper_base_base
{
public:
bound_function_helper_base():arg1(0), arg2(0), arg3(0), arg4(0) {}
typename strip<T1>::type* arg1;
typename strip<T2>::type* arg2;
typename strip<T3>::type* arg3;
typename strip<T4>::type* arg4;
member_function_pointer<T1,T2,T3,T4> mfp;
};
// ----------------
template <typename F, typename T1 = void, typename T2 = void, typename T3 = void, typename T4 = void>
class bound_function_helper : public bound_function_helper_base<T1,T2,T3,T4>
{
public:
void call() const
{
(*fp)(*this->arg1, *this->arg2, *this->arg3, *this->arg4);
}
typename strip<F>::type* fp;
};
template <typename T1, typename T2, typename T3, typename T4>
class bound_function_helper<void,T1,T2,T3,T4> : public bound_function_helper_base<T1,T2,T3,T4>
{
public:
void call() const
{
if (this->mfp) this->mfp(*this->arg1, *this->arg2, *this->arg3, *this->arg4);
else if (fp) fp(*this->arg1, *this->arg2, *this->arg3, *this->arg4);
}
void (*fp)(T1, T2, T3, T4);
};
// ----------------
template <typename F>
class bound_function_helper<F,void,void,void,void> : public bound_function_helper_base<void,void,void,void>
{
public:
void call() const
{
(*fp)();
}
typename strip<F>::type* fp;
};
template <>
class bound_function_helper<void,void,void,void,void> : public bound_function_helper_base<void,void,void,void>
{
public:
void call() const
{
if (this->mfp) this->mfp();
else if (fp) fp();
}
void (*fp)();
};
// ----------------
template <typename F, typename T1>
class bound_function_helper<F,T1,void,void,void> : public bound_function_helper_base<T1,void,void,void>
{
public:
void call() const
{
(*fp)(*this->arg1);
}
typename strip<F>::type* fp;
};
template <typename T1>
class bound_function_helper<void,T1,void,void,void> : public bound_function_helper_base<T1,void,void,void>
{
public:
void call() const
{
if (this->mfp) this->mfp(*this->arg1);
else if (fp) fp(*this->arg1);
}
void (*fp)(T1);
};
// ----------------
template <typename F, typename T1, typename T2>
class bound_function_helper<F,T1,T2,void,void> : public bound_function_helper_base<T1,T2,void,void>
{
public:
void call() const
{
(*fp)(*this->arg1, *this->arg2);
}
typename strip<F>::type* fp;
};
template <typename T1, typename T2>
class bound_function_helper<void,T1,T2,void,void> : public bound_function_helper_base<T1,T2,void,void>
{
public:
void call() const
{
if (this->mfp) this->mfp(*this->arg1, *this->arg2);
else if (fp) fp(*this->arg1, *this->arg2);
}
void (*fp)(T1, T2);
};
// ----------------
template <typename F, typename T1, typename T2, typename T3>
class bound_function_helper<F,T1,T2,T3,void> : public bound_function_helper_base<T1,T2,T3,void>
{
public:
void call() const
{
(*fp)(*this->arg1, *this->arg2, *this->arg3);
}
typename strip<F>::type* fp;
};
template <typename T1, typename T2, typename T3>
class bound_function_helper<void,T1,T2,T3,void> : public bound_function_helper_base<T1,T2,T3,void>
{
public:
void call() const
{
if (this->mfp) this->mfp(*this->arg1, *this->arg2, *this->arg3);
else if (fp) fp(*this->arg1, *this->arg2, *this->arg3);
}
void (*fp)(T1, T2, T3);
};
// ------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------
template <typename T>
class bound_function_helper_T : public T
{
public:
bound_function_helper_T(){ this->fp = 0;}
bool is_set() const
{
return this->fp != 0 || this->mfp.is_set();
}
template <unsigned long mem_size>
void safe_clone(stack_based_memory_block<mem_size>& buf)
{
// This is here just to validate the assumption that our block of memory we have made
// in bf_memory is the right size to store the data for this object. If you
// get a compiler error on this line then email me :)
COMPILE_TIME_ASSERT(sizeof(bound_function_helper_T) <= mem_size);
clone(buf.get());
}
void clone (void* ptr) const
{
bound_function_helper_T* p = new(ptr) bound_function_helper_T();
p->arg1 = this->arg1;
p->arg2 = this->arg2;
p->arg3 = this->arg3;
p->arg4 = this->arg4;
p->fp = this->fp;
p->mfp = this->mfp;
}
};
}
// ----------------------------------------------------------------------------------------
class bound_function_pointer
{
typedef bfp1_helpers::bound_function_helper_T<bfp1_helpers::bound_function_helper<void,int> > bf_null_type;
public:
// These typedefs are here for backwards compatibility with previous versions of
// dlib.
typedef bound_function_pointer kernel_1a;
typedef bound_function_pointer kernel_1a_c;
bound_function_pointer (
) { bf_null_type().safe_clone(bf_memory); }
bound_function_pointer (
const bound_function_pointer& item
) { item.bf()->clone(bf_memory.get()); }
~bound_function_pointer()
{ destroy_bf_memory(); }
bound_function_pointer& operator= (
const bound_function_pointer& item
) { bound_function_pointer(item).swap(*this); return *this; }
void clear (
) { bound_function_pointer().swap(*this); }
bool is_set (
) const
{
return bf()->is_set();
}
void swap (
bound_function_pointer& item
)
{
// make a temp copy of item
bound_function_pointer temp(item);
// destory the stuff in item
item.destroy_bf_memory();
// copy *this into item
bf()->clone(item.bf_memory.get());
// destory the stuff in this
destroy_bf_memory();
// copy temp into *this
temp.bf()->clone(bf_memory.get());
}
void operator() (
) const
{
// make sure requires clause is not broken
DLIB_ASSERT(is_set() == true ,
"\tvoid bound_function_pointer::operator()"
<< "\n\tYou must call set() before you can use this function"
<< "\n\tthis: " << this
);
bf()->call();
}
private:
struct dummy{ void nonnull() {}};
typedef void (dummy::*safe_bool)();
public:
operator safe_bool () const { return is_set() ? &dummy::nonnull : 0; }
bool operator!() const { return !is_set(); }
// -------------------------------------------
// set function object overloads
// -------------------------------------------
template <typename F>
void set (
F& function_object
)
{
COMPILE_TIME_ASSERT(is_function<F>::value == false);
COMPILE_TIME_ASSERT(is_pointer_type<F>::value == false);
using namespace bfp1_helpers;
destroy_bf_memory();
typedef bound_function_helper_T<bound_function_helper<F> > bf_helper_type;
bf_helper_type temp;
temp.fp = &function_object;
temp.safe_clone(bf_memory);
}
template <typename F, typename A1 >
void set (
F& function_object,
A1& arg1
)
{
COMPILE_TIME_ASSERT(is_function<F>::value == false);
COMPILE_TIME_ASSERT(is_pointer_type<F>::value == false);
using namespace bfp1_helpers;
destroy_bf_memory();
typedef bound_function_helper_T<bound_function_helper<F,A1> > bf_helper_type;
bf_helper_type temp;
temp.arg1 = &arg1;
temp.fp = &function_object;
temp.safe_clone(bf_memory);
}
template <typename F, typename A1, typename A2 >
void set (
F& function_object,
A1& arg1,
A2& arg2
)
{
COMPILE_TIME_ASSERT(is_function<F>::value == false);
COMPILE_TIME_ASSERT(is_pointer_type<F>::value == false);
using namespace bfp1_helpers;
destroy_bf_memory();
typedef bound_function_helper_T<bound_function_helper<F,A1,A2> > bf_helper_type;
bf_helper_type temp;
temp.arg1 = &arg1;
temp.arg2 = &arg2;
temp.fp = &function_object;
temp.safe_clone(bf_memory);
}
template <typename F, typename A1, typename A2, typename A3 >
void set (
F& function_object,
A1& arg1,
A2& arg2,
A3& arg3
)
{
COMPILE_TIME_ASSERT(is_function<F>::value == false);
COMPILE_TIME_ASSERT(is_pointer_type<F>::value == false);
using namespace bfp1_helpers;
destroy_bf_memory();
typedef bound_function_helper_T<bound_function_helper<F,A1,A2,A3> > bf_helper_type;
bf_helper_type temp;
temp.arg1 = &arg1;
temp.arg2 = &arg2;
temp.arg3 = &arg3;
temp.fp = &function_object;
temp.safe_clone(bf_memory);
}
template <typename F, typename A1, typename A2, typename A3, typename A4>
void set (
F& function_object,
A1& arg1,
A2& arg2,
A3& arg3,
A4& arg4
)
{
COMPILE_TIME_ASSERT(is_function<F>::value == false);
COMPILE_TIME_ASSERT(is_pointer_type<F>::value == false);
using namespace bfp1_helpers;
destroy_bf_memory();
typedef bound_function_helper_T<bound_function_helper<F,A1,A2,A3,A4> > bf_helper_type;
bf_helper_type temp;
temp.arg1 = &arg1;
temp.arg2 = &arg2;
temp.arg3 = &arg3;
temp.arg4 = &arg4;
temp.fp = &function_object;
temp.safe_clone(bf_memory);
}
// -------------------------------------------
// set mfp overloads
// -------------------------------------------
template <typename T>
void set (
T& object,
void (T::*funct)()
)
{
using namespace bfp1_helpers;
destroy_bf_memory();
typedef bound_function_helper_T<bound_function_helper<void> > bf_helper_type;
bf_helper_type temp;
temp.mfp.set(object,funct);
temp.safe_clone(bf_memory);
}
template <typename T >
void set (
const T& object,
void (T::*funct)()const
)
{
using namespace bfp1_helpers;
destroy_bf_memory();
typedef bound_function_helper_T<bound_function_helper<void> > bf_helper_type;
bf_helper_type temp;
temp.mfp.set(object,funct);
temp.safe_clone(bf_memory);
}
// -------------------------------------------
template <typename T, typename T1, typename A1 >
void set (
T& object,
void (T::*funct)(T1),
A1& arg1
)
{
using namespace bfp1_helpers;
destroy_bf_memory();
typedef bound_function_helper_T<bound_function_helper<void,T1> > bf_helper_type;
bf_helper_type temp;
temp.arg1 = &arg1;
temp.mfp.set(object,funct);
temp.safe_clone(bf_memory);
}
template <typename T, typename T1, typename A1 >
void set (
const T& object,
void (T::*funct)(T1)const,
A1& arg1
)
{
using namespace bfp1_helpers;
destroy_bf_memory();
typedef bound_function_helper_T<bound_function_helper<void,T1> > bf_helper_type;
bf_helper_type temp;
temp.arg1 = &arg1;
temp.mfp.set(object,funct);
temp.safe_clone(bf_memory);
}
// ----------------
template <typename T, typename T1, typename A1,
typename T2, typename A2>
void set (
T& object,
void (T::*funct)(T1, T2),
A1& arg1,
A2& arg2
)
{
using namespace bfp1_helpers;
destroy_bf_memory();
typedef bound_function_helper_T<bound_function_helper<void,T1,T2> > bf_helper_type;
bf_helper_type temp;
temp.arg1 = &arg1;
temp.arg2 = &arg2;
temp.mfp.set(object,funct);
temp.safe_clone(bf_memory);
}
template <typename T, typename T1, typename A1,
typename T2, typename A2>
void set (
const T& object,
void (T::*funct)(T1, T2)const,
A1& arg1,
A2& arg2
)
{
using namespace bfp1_helpers;
destroy_bf_memory();
typedef bound_function_helper_T<bound_function_helper<void,T1,T2> > bf_helper_type;
bf_helper_type temp;
temp.arg1 = &arg1;
temp.arg2 = &arg2;
temp.mfp.set(object,funct);
temp.safe_clone(bf_memory);
}
// ----------------
template <typename T, typename T1, typename A1,
typename T2, typename A2,
typename T3, typename A3>
void set (
T& object,
void (T::*funct)(T1, T2, T3),
A1& arg1,
A2& arg2,
A3& arg3
)
{
using namespace bfp1_helpers;
destroy_bf_memory();
typedef bound_function_helper_T<bound_function_helper<void,T1,T2,T3> > bf_helper_type;
bf_helper_type temp;
temp.arg1 = &arg1;
temp.arg2 = &arg2;
temp.arg3 = &arg3;
temp.mfp.set(object,funct);
temp.safe_clone(bf_memory);
}
template <typename T, typename T1, typename A1,
typename T2, typename A2,
typename T3, typename A3>
void set (
const T& object,
void (T::*funct)(T1, T2, T3)const,
A1& arg1,
A2& arg2,
A3& arg3
)
{
using namespace bfp1_helpers;
destroy_bf_memory();
typedef bound_function_helper_T<bound_function_helper<void,T1,T2,T3> > bf_helper_type;
bf_helper_type temp;
temp.arg1 = &arg1;
temp.arg2 = &arg2;
temp.arg3 = &arg3;
temp.mfp.set(object,funct);
temp.safe_clone(bf_memory);
}
// ----------------
template <typename T, typename T1, typename A1,
typename T2, typename A2,
typename T3, typename A3,
typename T4, typename A4>
void set (
T& object,
void (T::*funct)(T1, T2, T3, T4),
A1& arg1,
A2& arg2,
A3& arg3,
A4& arg4
)
{
using namespace bfp1_helpers;
destroy_bf_memory();
typedef bound_function_helper_T<bound_function_helper<void,T1,T2,T3,T4> > bf_helper_type;
bf_helper_type temp;
temp.arg1 = &arg1;
temp.arg2 = &arg2;
temp.arg3 = &arg3;
temp.arg4 = &arg4;
temp.mfp.set(object,funct);
temp.safe_clone(bf_memory);
}
template <typename T, typename T1, typename A1,
typename T2, typename A2,
typename T3, typename A3,
typename T4, typename A4>
void set (
const T& object,
void (T::*funct)(T1, T2, T3, T4)const,
A1& arg1,
A2& arg2,
A3& arg3,
A4& arg4
)
{
using namespace bfp1_helpers;
destroy_bf_memory();
typedef bound_function_helper_T<bound_function_helper<void,T1,T2,T3,T4> > bf_helper_type;
bf_helper_type temp;
temp.arg1 = &arg1;
temp.arg2 = &arg2;
temp.arg3 = &arg3;
temp.arg4 = &arg4;
temp.mfp.set(object,funct);
temp.safe_clone(bf_memory);
}
// -------------------------------------------
// set fp overloads
// -------------------------------------------
void set (
void (*funct)()
)
{
using namespace bfp1_helpers;
destroy_bf_memory();
typedef bound_function_helper_T<bound_function_helper<void> > bf_helper_type;
bf_helper_type temp;
temp.fp = funct;
temp.safe_clone(bf_memory);
}
template <typename T1, typename A1>
void set (
void (*funct)(T1),
A1& arg1
)
{
using namespace bfp1_helpers;
destroy_bf_memory();
typedef bound_function_helper_T<bound_function_helper<void,T1> > bf_helper_type;
bf_helper_type temp;
temp.arg1 = &arg1;
temp.fp = funct;
temp.safe_clone(bf_memory);
}
template <typename T1, typename A1,
typename T2, typename A2>
void set (
void (*funct)(T1, T2),
A1& arg1,
A2& arg2
)
{
using namespace bfp1_helpers;
destroy_bf_memory();
typedef bound_function_helper_T<bound_function_helper<void,T1,T2> > bf_helper_type;
bf_helper_type temp;
temp.arg1 = &arg1;
temp.arg2 = &arg2;
temp.fp = funct;
temp.safe_clone(bf_memory);
}
template <typename T1, typename A1,
typename T2, typename A2,
typename T3, typename A3>
void set (
void (*funct)(T1, T2, T3),
A1& arg1,
A2& arg2,
A3& arg3
)
{
using namespace bfp1_helpers;
destroy_bf_memory();
typedef bound_function_helper_T<bound_function_helper<void,T1,T2,T3> > bf_helper_type;
bf_helper_type temp;
temp.arg1 = &arg1;
temp.arg2 = &arg2;
temp.arg3 = &arg3;
temp.fp = funct;
temp.safe_clone(bf_memory);
}
template <typename T1, typename A1,
typename T2, typename A2,
typename T3, typename A3,
typename T4, typename A4>
void set (
void (*funct)(T1, T2, T3, T4),
A1& arg1,
A2& arg2,
A3& arg3,
A4& arg4
)
{
using namespace bfp1_helpers;
destroy_bf_memory();
typedef bound_function_helper_T<bound_function_helper<void,T1,T2,T3,T4> > bf_helper_type;
bf_helper_type temp;
temp.arg1 = &arg1;
temp.arg2 = &arg2;
temp.arg3 = &arg3;
temp.arg4 = &arg4;
temp.fp = funct;
temp.safe_clone(bf_memory);
}
// -------------------------------------------
private:
stack_based_memory_block<sizeof(bf_null_type)> bf_memory;
void destroy_bf_memory (
)
{
// Honestly, this probably doesn't even do anything but I'm putting
// it here just for good measure.
bf()->~bound_function_helper_base_base();
}
bfp1_helpers::bound_function_helper_base_base* bf ()
{ return static_cast<bfp1_helpers::bound_function_helper_base_base*>(bf_memory.get()); }
const bfp1_helpers::bound_function_helper_base_base* bf () const
{ return static_cast<const bfp1_helpers::bound_function_helper_base_base*>(bf_memory.get()); }
};
// ----------------------------------------------------------------------------------------
inline void swap (
bound_function_pointer& a,
bound_function_pointer& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_BOUND_FUNCTION_POINTER_KERNEl_1_

View File

@@ -0,0 +1,456 @@
// Copyright (C) 2008 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_BOUND_FUNCTION_POINTER_KERNEl_ABSTRACT_
#ifdef DLIB_BOUND_FUNCTION_POINTER_KERNEl_ABSTRACT_
namespace dlib
{
// ----------------------------------------------------------------------------------------
class bound_function_pointer
{
/*!
INITIAL VALUE
is_set() == false
WHAT THIS OBJECT REPRESENTS
This object represents a function with all its arguments bound to
specific objects. For example:
void test(int& var) { var = var+1; }
bound_function_pointer funct;
int a = 4;
funct.set(test,a); // bind the variable a to the first argument of the test() function
// at this point a == 4
funct();
// after funct() is called a == 5
!*/
public:
bound_function_pointer (
);
/*!
ensures
- #*this is properly initialized
!*/
bound_function_pointer(
const bound_function_pointer& item
);
/*!
ensures
- *this == item
!*/
~bound_function_pointer (
);
/*!
ensures
- any resources associated with *this have been released
!*/
bound_function_pointer& operator=(
const bound_function_pointer& item
);
/*!
ensures
- *this == item
!*/
void clear(
);
/*!
ensures
- #*this has its initial value
!*/
bool is_set (
) const;
/*!
ensures
- if (this->set() has been called) then
- returns true
- else
- returns false
!*/
operator some_undefined_pointer_type (
) const;
/*!
ensures
- if (is_set()) then
- returns a non 0 value
- else
- returns a 0 value
!*/
bool operator! (
) const;
/*!
ensures
- returns !is_set()
!*/
void operator () (
) const;
/*!
requires
- is_set() == true
ensures
- calls the bound function on the object(s) specified by the last
call to this->set()
throws
- any exception thrown by the function specified by
the previous call to this->set().
If any of these exceptions are thrown then the call to this
function will have no effect on *this.
!*/
void swap (
bound_function_pointer& item
);
/*!
ensures
- swaps *this and item
!*/
// ----------------------
template <typename F>
void set (
F& function_object
);
/*!
requires
- function_object() is a valid expression
ensures
- #is_set() == true
- calls to this->operator() will call function_object()
(This seems pointless but it is a useful base case)
!*/
template < typename T>
void set (
T& object,
void (T::*funct)()
);
/*!
requires
- funct == a valid member function pointer for class T
ensures
- #is_set() == true
- calls to this->operator() will call (object.*funct)()
!*/
template < typename T>
void set (
const T& object,
void (T::*funct)()const
);
/*!
requires
- funct == a valid bound function pointer for class T
ensures
- #is_set() == true
- calls to this->operator() will call (object.*funct)()
!*/
void set (
void (*funct)()
);
/*!
requires
- funct == a valid function pointer
ensures
- #is_set() == true
- calls to this->operator() will call funct()
!*/
// ----------------------
template <typename F, typename A1 >
void set (
F& function_object,
A1& arg1
);
/*!
requires
- function_object(arg1) is a valid expression
ensures
- #is_set() == true
- calls to this->operator() will call function_object(arg1)
!*/
template < typename T, typename T1, typename A1 >
void set (
T& object,
void (T::*funct)(T1),
A1& arg1
);
/*!
requires
- funct == a valid member function pointer for class T
ensures
- #is_set() == true
- calls to this->operator() will call (object.*funct)(arg1)
!*/
template < typename T, typename T1, typename A1 >
void set (
const T& object,
void (T::*funct)(T1)const,
A1& arg1
);
/*!
requires
- funct == a valid bound function pointer for class T
ensures
- #is_set() == true
- calls to this->operator() will call (object.*funct)(arg1)
!*/
template <typename T1, typename A1>
void set (
void (*funct)(T1),
A1& arg1
);
/*!
requires
- funct == a valid function pointer
ensures
- #is_set() == true
- calls to this->operator() will call funct(arg1)
!*/
// ----------------------
template <typename F, typename A1, typename A2 >
void set (
F& function_object,
A1& arg1,
A2& arg2
);
/*!
requires
- function_object(arg1,arg2) is a valid expression
ensures
- #is_set() == true
- calls to this->operator() will call function_object(arg1,arg2)
!*/
template < typename T, typename T1, typename A1,
typename T2, typename A2>
void set (
T& object,
void (T::*funct)(T1,T2),
A1& arg1,
A2& arg2
);
/*!
requires
- funct == a valid member function pointer for class T
ensures
- #is_set() == true
- calls to this->operator() will call (object.*funct)(arg1,arg2)
!*/
template < typename T, typename T1, typename A1,
typename T2, typename A2>
void set (
const T& object,
void (T::*funct)(T1,T2)const,
A1& arg1,
A2& arg2
);
/*!
requires
- funct == a valid bound function pointer for class T
ensures
- #is_set() == true
- calls to this->operator() will call (object.*funct)(arg1,arg2)
!*/
template <typename T1, typename A1,
typename T2, typename A2>
void set (
void (*funct)(T1,T2),
A1& arg1,
A2& arg2
);
/*!
requires
- funct == a valid function pointer
ensures
- #is_set() == true
- calls to this->operator() will call funct(arg1,arg2)
!*/
// ----------------------
template <typename F, typename A1, typename A2, typename A3 >
void set (
F& function_object,
A1& arg1,
A2& arg2,
A3& arg3
);
/*!
requires
- function_object(arg1,arg2,arg3) is a valid expression
ensures
- #is_set() == true
- calls to this->operator() will call function_object(arg1,arg2,arg3)
!*/
template < typename T, typename T1, typename A1,
typename T2, typename A2,
typename T3, typename A3>
void set (
T& object,
void (T::*funct)(T1,T2,T3),
A1& arg1,
A2& arg2,
A3& arg3
);
/*!
requires
- funct == a valid member function pointer for class T
ensures
- #is_set() == true
- calls to this->operator() will call (object.*funct)(arg1,arg2,arg3)
!*/
template < typename T, typename T1, typename A1,
typename T2, typename A2,
typename T3, typename A3>
void set (
const T& object,
void (T::*funct)(T1,T2,T3)const,
A1& arg1,
A2& arg2,
A3& arg3
);
/*!
requires
- funct == a valid bound function pointer for class T
ensures
- #is_set() == true
- calls to this->operator() will call (object.*funct)(arg1,arg2,arg3)
!*/
template <typename T1, typename A1,
typename T2, typename A2,
typename T3, typename A3>
void set (
void (*funct)(T1,T2,T3),
A1& arg1,
A2& arg2,
A3& arg3
);
/*!
requires
- funct == a valid function pointer
ensures
- #is_set() == true
- calls to this->operator() will call funct(arg1,arg2,arg3)
!*/
// ----------------------
template <typename F, typename A1, typename A2, typename A3, typename A4>
void set (
F& function_object,
A1& arg1,
A2& arg2,
A3& arg3,
A4& arg4
);
/*!
requires
- function_object(arg1,arg2,arg3,arg4) is a valid expression
ensures
- #is_set() == true
- calls to this->operator() will call function_object(arg1,arg2,arg3,arg4)
!*/
template < typename T, typename T1, typename A1,
typename T2, typename A2,
typename T3, typename A3,
typename T4, typename A4>
void set (
T& object,
void (T::*funct)(T1,T2,T3,T4),
A1& arg1,
A2& arg2,
A3& arg3,
A4& arg4
);
/*!
requires
- funct == a valid member function pointer for class T
ensures
- #is_set() == true
- calls to this->operator() will call (object.*funct)(arg1,arg2,arg3,arg4)
!*/
template < typename T, typename T1, typename A1,
typename T2, typename A2,
typename T3, typename A3,
typename T4, typename A4>
void set (
const T& object,
void (T::*funct)(T1,T2,T3,T4)const,
A1& arg1,
A2& arg2,
A3& arg3,
A4& arg4
);
/*!
requires
- funct == a valid bound function pointer for class T
ensures
- #is_set() == true
- calls to this->operator() will call (object.*funct)(arg1,arg2,arg3,arg4)
!*/
template <typename T1, typename A1,
typename T2, typename A2,
typename T3, typename A3,
typename T4, typename A4>
void set (
void (*funct)(T1,T2,T3,T4),
A1& arg1,
A2& arg2,
A3& arg3,
A4& arg4
);
/*!
requires
- funct == a valid function pointer
ensures
- #is_set() == true
- calls to this->operator() will call funct(arg1,arg2,arg3,arg4)
!*/
};
// ----------------------------------------------------------------------------------------
inline void swap (
bound_function_pointer& a,
bound_function_pointer& b
) { a.swap(b); }
/*!
provides a global swap function
!*/
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_BOUND_FUNCTION_POINTER_KERNEl_ABSTRACT_

View File

@@ -0,0 +1,10 @@
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_BYTE_ORDEREr_
#define DLIB_BYTE_ORDEREr_
#include "byte_orderer/byte_orderer_kernel_1.h"
#endif // DLIB_BYTE_ORDEREr_

View File

@@ -0,0 +1,176 @@
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_BYTE_ORDEREr_KERNEL_1_
#define DLIB_BYTE_ORDEREr_KERNEL_1_
#include "byte_orderer_kernel_abstract.h"
#include "../algs.h"
#include "../assert.h"
namespace dlib
{
class byte_orderer
{
/*!
INITIAL VALUE
- if (this machine is little endian) then
- little_endian == true
- else
- little_endian == false
CONVENTION
- host_is_big_endian() == !little_endian
- host_is_little_endian() == little_endian
- if (this machine is little endian) then
- little_endian == true
- else
- little_endian == false
!*/
public:
// this is here for backwards compatibility with older versions of dlib.
typedef byte_orderer kernel_1a;
byte_orderer (
)
{
// This will probably never be false but if it is then it means chars are not 8bits
// on this system. Which is a problem for this object.
COMPILE_TIME_ASSERT(sizeof(short) >= 2);
unsigned long temp = 1;
unsigned char* ptr = reinterpret_cast<unsigned char*>(&temp);
if (*ptr == 1)
little_endian = true;
else
little_endian = false;
}
virtual ~byte_orderer (
){}
bool host_is_big_endian (
) const { return !little_endian; }
bool host_is_little_endian (
) const { return little_endian; }
template <
typename T
>
inline void host_to_network (
T& item
) const
{ if (little_endian) flip(item); }
template <
typename T
>
inline void network_to_host (
T& item
) const { if (little_endian) flip(item); }
template <
typename T
>
void host_to_big (
T& item
) const { if (little_endian) flip(item); }
template <
typename T
>
void big_to_host (
T& item
) const { if (little_endian) flip(item); }
template <
typename T
>
void host_to_little (
T& item
) const { if (!little_endian) flip(item); }
template <
typename T
>
void little_to_host (
T& item
) const { if (!little_endian) flip(item); }
private:
template <
typename T,
size_t size
>
inline void flip (
T (&array)[size]
) const
/*!
ensures
- flips the bytes in every element of this array
!*/
{
for (size_t i = 0; i < size; ++i)
{
flip(array[i]);
}
}
template <
typename T
>
inline void flip (
T& item
) const
/*!
ensures
- reverses the byte ordering in item
!*/
{
DLIB_ASSERT_HAS_STANDARD_LAYOUT(T);
T value;
// If you are getting this as an error then you are probably using
// this object wrong. If you think you aren't then send me (Davis) an
// email and I'll either set you straight or change/remove this check so
// your stuff works :)
COMPILE_TIME_ASSERT(sizeof(T) <= sizeof(long double));
// If you are getting a compile error on this line then it means T is
// a pointer type. It doesn't make any sense to byte swap pointers
// since they have no meaning outside the context of their own process.
// So you probably just forgot to dereference that pointer before passing
// it to this function :)
COMPILE_TIME_ASSERT(is_pointer_type<T>::value == false);
const size_t size = sizeof(T);
unsigned char* const ptr = reinterpret_cast<unsigned char*>(&item);
unsigned char* const ptr_temp = reinterpret_cast<unsigned char*>(&value);
for (size_t i = 0; i < size; ++i)
ptr_temp[size-i-1] = ptr[i];
item = value;
}
bool little_endian;
};
// make flip not do anything at all for chars
template <> inline void byte_orderer::flip<char> ( char& ) const {}
template <> inline void byte_orderer::flip<unsigned char> ( unsigned char& ) const {}
template <> inline void byte_orderer::flip<signed char> ( signed char& ) const {}
}
#endif // DLIB_BYTE_ORDEREr_KERNEL_1_

View File

@@ -0,0 +1,149 @@
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_BYTE_ORDEREr_ABSTRACT_
#ifdef DLIB_BYTE_ORDEREr_ABSTRACT_
#include "../algs.h"
namespace dlib
{
class byte_orderer
{
/*!
INITIAL VALUE
This object has no state.
WHAT THIS OBJECT REPRESENTS
This object simply provides a mechanism to convert data from a
host machine's own byte ordering to big or little endian and to
also do the reverse.
It also provides a pair of functions to convert to/from network byte
order where network byte order is big endian byte order. This pair of
functions does the exact same thing as the host_to_big() and big_to_host()
functions and is provided simply so that client code can use the most
self documenting name appropriate.
Also note that this object is capable of correctly flipping the contents
of arrays when the arrays are declared on the stack. e.g. You can
say things like:
int array[10];
bo.host_to_network(array);
!*/
public:
byte_orderer (
);
/*!
ensures
- #*this is properly initialized
throws
- std::bad_alloc
!*/
virtual ~byte_orderer (
);
/*!
ensures
- any resources associated with *this have been released
!*/
bool host_is_big_endian (
) const;
/*!
ensures
- if (the host computer is a big endian machine) then
- returns true
- else
- returns false
!*/
bool host_is_little_endian (
) const;
/*!
ensures
- if (the host computer is a little endian machine) then
- returns true
- else
- returns false
!*/
template <
typename T
>
void host_to_network (
T& item
) const;
/*!
ensures
- #item == the value of item converted from host byte order
to network byte order.
!*/
template <
typename T
>
void network_to_host (
T& item
) const;
/*!
ensures
- #item == the value of item converted from network byte order
to host byte order.
!*/
template <
typename T
>
void host_to_big (
T& item
) const;
/*!
ensures
- #item == the value of item converted from host byte order
to big endian byte order.
!*/
template <
typename T
>
void big_to_host (
T& item
) const;
/*!
ensures
- #item == the value of item converted from big endian byte order
to host byte order.
!*/
template <
typename T
>
void host_to_little (
T& item
) const;
/*!
ensures
- #item == the value of item converted from host byte order
to little endian byte order.
!*/
template <
typename T
>
void little_to_host (
T& item
) const;
/*!
ensures
- #item == the value of item converted from little endian byte order
to host byte order.
!*/
};
}
#endif // DLIB_BYTE_ORDEREr_ABSTRACT_

View File

@@ -0,0 +1 @@
#include "dlib_include_path_tutorial.txt"

View File

@@ -0,0 +1,34 @@
// If you are compiling dlib as a shared library and installing it somewhere on your system
// then it is important that any programs that use dlib agree on the state of the
// DLIB_ASSERT statements (i.e. they are either always on or always off). Therefore,
// uncomment one of the following lines to force all DLIB_ASSERTs to either always on or
// always off. If you don't define one of these two macros then DLIB_ASSERT will toggle
// automatically depending on the state of certain other macros, which is not what you want
// when creating a shared library.
// #define ENABLE_ASSERTS // asserts always enabled
/* #undef DLIB_DISABLE_ASSERTS */
/* #undef DLIB_ISO_CPP_ONLY */
/* #undef DLIB_NO_GUI_SUPPORT */
#define DLIB_ENABLE_STACK_TRACE
#define LAPACK_FORCE_UNDERSCORE
/* #undef LAPACK_FORCE_NOUNDERSCORE */
// You should also consider telling dlib to link against libjpeg, libpng, libgif, fftw, CUDA,
// and a BLAS and LAPACK library. To do this you need to uncomment the following #defines.
#define DLIB_JPEG_SUPPORT
#define DLIB_PNG_SUPPORT
/* #undef DLIB_GIF_SUPPORT */
/* #undef DLIB_USE_FFTW */
#define DLIB_USE_BLAS
#define DLIB_USE_LAPACK
/* #undef DLIB_USE_CUDA */
/* #undef DLIB_USE_MKL_FFT */
// This variable allows dlib/test_for_odr_violations.h to catch people who mistakenly use
// headers from one version of dlib with a compiled dlib binary from a different dlib version.
// #define DLIB_CHECK_FOR_VERSION_MISMATCH DLIB_VERSION_MISMATCH_CHECK__EXPECTED_VERSION_19_21_99

View File

@@ -0,0 +1,207 @@
// Copyright (C) 2010 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_CONSOLE_PROGRESS_INDiCATOR_Hh_
#define DLIB_CONSOLE_PROGRESS_INDiCATOR_Hh_
#include <ctime>
#include <cmath>
#include <limits>
#include <iostream>
namespace dlib
{
// ----------------------------------------------------------------------------------------
class console_progress_indicator
{
/*!
WHAT THIS OBJECT REPRESENTS
This object is a tool for reporting how long a task will take
to complete.
For example, consider the following bit of code:
console_progress_indicator pbar(100)
for (int i = 1; i <= 100; ++i)
{
pbar.print_status(i);
long_running_operation();
}
The above code will print a message to the console each iteration
which shows how much time is remaining until the loop terminates.
!*/
public:
inline explicit console_progress_indicator (
double target_value
);
/*!
ensures
- #target() == target_value
!*/
inline void reset (
double target_value
);
/*!
ensures
- #target() == target_value
- performs the equivalent of:
*this = console_progress_indicator(target_value)
(i.e. resets this object with a new target value)
!*/
inline double target (
) const;
/*!
ensures
- This object attempts to measure how much time is
left until we reach a certain targeted value. This
function returns that targeted value.
!*/
inline bool print_status (
double cur,
bool always_print = false
);
/*!
ensures
- print_status() assumes it is called with values which are linearly
approaching target(). It will attempt to predict how much time is
remaining until cur becomes equal to target().
- prints a status message to the screen which indicates how much
more time is left until cur is equal to target()
- if (always_print) then
- This function prints to the screen each time it is called.
- else
- This function throttles the printing so that at most 1 message is
printed each second. Note that it won't print anything to the screen
until about one second has elapsed. This means that the first call
to print_status() never prints to the screen.
- This function returns true if it prints to the screen and false
otherwise.
!*/
private:
double target_val;
time_t start_time;
double first_val;
double seen_first_val;
time_t last_time;
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// IMPLEMENTATION DETAILS
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
console_progress_indicator::
console_progress_indicator (
double target_value
) :
target_val(target_value),
start_time(0),
first_val(0),
seen_first_val(false),
last_time(0)
{
}
// ----------------------------------------------------------------------------------------
bool console_progress_indicator::
print_status (
double cur,
bool always_print
)
{
const time_t cur_time = std::time(0);
// if this is the first time print_status has been called
// then collect some information and exit. We will print status
// on the next call.
if (!seen_first_val)
{
start_time = cur_time;
last_time = cur_time;
first_val = cur;
seen_first_val = true;
return false;
}
if (cur_time != last_time || always_print)
{
last_time = cur_time;
double delta_t = static_cast<double>(cur_time - start_time);
double delta_val = std::abs(cur - first_val);
// don't do anything if cur is equal to first_val
if (delta_val < std::numeric_limits<double>::epsilon())
return false;
double seconds = delta_t/delta_val * std::abs(target_val - cur);
std::ios::fmtflags oldflags = std::cout.flags();
std::cout.setf(std::ios::fixed,std::ios::floatfield);
std::streamsize ss;
if (seconds < 60)
{
ss = std::cout.precision(0);
std::cout << "Time remaining: " << seconds << " seconds. \r" << std::flush;
}
else if (seconds < 60*60)
{
ss = std::cout.precision(2);
std::cout << "Time remaining: " << seconds/60 << " minutes. \r" << std::flush;
}
else
{
ss = std::cout.precision(2);
std::cout << "Time remaining: " << seconds/60/60 << " hours. \r" << std::flush;
}
// restore previous output flags and precision settings
std::cout.flags(oldflags);
std::cout.precision(ss);
return true;
}
return false;
}
// ----------------------------------------------------------------------------------------
double console_progress_indicator::
target (
) const
{
return target_val;
}
// ----------------------------------------------------------------------------------------
void console_progress_indicator::
reset (
double target_value
)
{
*this = console_progress_indicator(target_value);
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_CONSOLE_PROGRESS_INDiCATOR_Hh_

View File

@@ -0,0 +1 @@
#include "dlib_include_path_tutorial.txt"

View File

@@ -0,0 +1,13 @@
#error "Don't write #include <dlib/all/source.cpp> in your code."
/*
In C++, it is generally an error to #include .cpp files. This is because it
can lead to what are called multiply defined symbol errors. Therefore, you
should compile dlib/all/source.cpp into your application just like you would
compile any other .cpp file.
If you are using Visual Studio you add .cpp files to your application using
the solution explorer window. Specifically, right click on Source Files,
then select Add -> Existing Item and select the .cpp files you want to add.
For general information on compiling dlib see http://dlib.net/compile.html
*/

View File

@@ -0,0 +1,20 @@
#error "Don't put the dlib folder in your include path"
/*
You are getting this error because you have added the dlib folder to your
compiler's include search path.
You should *NOT* add the dlib folder itself to your compiler's include path.
Doing so will cause the build to fail because of name collisions (such as
dlib/string.h and string.h from the standard library). Instead you should
add the folder that contains the dlib folder to your include search path
and then use include statements of the form #include <dlib/queue.h> or
#include "dlib/queue.h". This will ensure that everything builds correctly.
XCode:
The XCode IDE often puts all folders that it knows about into
the compiler search path. So if you are using XCode then either
don't drag the whole dlib folder into the project or alternatively
modify your XCode project settings to not auto-add all folders to
the include path. Instead just make sure that the dlib folder is
itself inside a folder in your include path.
*/

View File

@@ -0,0 +1,62 @@
// Copyright 2003 (C) The Trustees of Indiana University.
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Authors: Jaakko Jarvi (jajarvi at osl.iu.edu)
// Jeremiah Willcock (jewillco at osl.iu.edu)
// Andrew Lumsdaine (lums at osl.iu.edu)
#ifndef DLIB_BOOST_UTILITY_ENABLE_IF_HPP
#define DLIB_BOOST_UTILITY_ENABLE_IF_HPP
namespace dlib
{
template <bool B, class T = void>
struct enable_if_c {
typedef T type;
};
template <class T>
struct enable_if_c<false, T> {};
template <class Cond, class T = void>
struct enable_if : public enable_if_c<Cond::value, T> {};
template <bool B, class T>
struct lazy_enable_if_c {
typedef typename T::type type;
};
template <class T>
struct lazy_enable_if_c<false, T> {};
template <class Cond, class T>
struct lazy_enable_if : public lazy_enable_if_c<Cond::value, T> {};
template <bool B, class T = void>
struct disable_if_c {
typedef T type;
};
template <class T>
struct disable_if_c<true, T> {};
template <class Cond, class T = void>
struct disable_if : public disable_if_c<Cond::value, T> {};
template <bool B, class T>
struct lazy_disable_if_c {
typedef typename T::type type;
};
template <class T>
struct lazy_disable_if_c<true, T> {};
template <class Cond, class T>
struct lazy_disable_if : public lazy_disable_if_c<Cond::value, T> {};
} // namespace dlib
#endif // DLIB_BOOST_UTILITY_ENABLE_IF_HPP

View File

@@ -0,0 +1,449 @@
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_ERROr_
#define DLIB_ERROr_
#include <string>
#include <new> // for std::bad_alloc
#include <iostream>
#include <cassert>
#include <cstdlib>
#include <exception>
// -------------------------------
// ------ exception classes ------
// -------------------------------
namespace dlib
{
// ----------------------------------------------------------------------------------------
enum error_type
{
EPORT_IN_USE,
ETIMEOUT,
ECONNECTION,
ELISTENER,
ERESOLVE,
EMONITOR,
ECREATE_THREAD,
ECREATE_MUTEX,
ECREATE_SIGNALER,
EUNSPECIFIED,
EGENERAL_TYPE1,
EGENERAL_TYPE2,
EGENERAL_TYPE3,
EINVALID_OPTION,
ETOO_FEW_ARGS,
ETOO_MANY_ARGS,
ESOCKET,
ETHREAD,
EGUI,
EFATAL,
EBROKEN_ASSERT,
EIMAGE_LOAD,
EDIR_CREATE,
EINCOMPATIBLE_OPTIONS,
EMISSING_REQUIRED_OPTION,
EINVALID_OPTION_ARG,
EMULTIPLE_OCCURANCES,
ECONFIG_READER,
EIMAGE_SAVE,
ECAST_TO_STRING,
ESTRING_CAST,
EUTF8_TO_UTF32,
EOPTION_PARSE
};
// ----------------------------------------------------------------------------------------
// the base exception class
class error : public std::exception
{
/*!
WHAT THIS OBJECT REPRESENTS
This is the base exception class for the dlib library. i.e. all
exceptions in this library inherit from this class.
!*/
public:
error(
error_type t,
const std::string& a
): info(a), type(t) {}
/*!
ensures
- #type == t
- #info == a
!*/
error(
error_type t
): type(t) {}
/*!
ensures
- #type == t
- #info == ""
!*/
error(
const std::string& a
): info(a), type(EUNSPECIFIED) {}
/*!
ensures
- #type == EUNSPECIFIED
- #info == a
!*/
error(
): type(EUNSPECIFIED) {}
/*!
ensures
- #type == EUNSPECIFIED
- #info == ""
!*/
virtual ~error(
) throw() {}
/*!
ensures
- does nothing
!*/
const char* what(
) const throw()
/*!
ensures
- if (info.size() != 0) then
- returns info.c_str()
- else
- returns type_to_string(type)
!*/
{
if (info.size() > 0)
return info.c_str();
else
return type_to_string();
}
const char* type_to_string (
) const throw()
/*!
ensures
- returns a string that names the contents of the type member.
!*/
{
if ( type == EPORT_IN_USE) return "EPORT_IN_USE";
else if ( type == ETIMEOUT) return "ETIMEOUT";
else if ( type == ECONNECTION) return "ECONNECTION";
else if ( type == ELISTENER) return "ELISTENER";
else if ( type == ERESOLVE) return "ERESOLVE";
else if ( type == EMONITOR) return "EMONITOR";
else if ( type == ECREATE_THREAD) return "ECREATE_THREAD";
else if ( type == ECREATE_MUTEX) return "ECREATE_MUTEX";
else if ( type == ECREATE_SIGNALER) return "ECREATE_SIGNALER";
else if ( type == EUNSPECIFIED) return "EUNSPECIFIED";
else if ( type == EGENERAL_TYPE1) return "EGENERAL_TYPE1";
else if ( type == EGENERAL_TYPE2) return "EGENERAL_TYPE2";
else if ( type == EGENERAL_TYPE3) return "EGENERAL_TYPE3";
else if ( type == EINVALID_OPTION) return "EINVALID_OPTION";
else if ( type == ETOO_FEW_ARGS) return "ETOO_FEW_ARGS";
else if ( type == ETOO_MANY_ARGS) return "ETOO_MANY_ARGS";
else if ( type == ESOCKET) return "ESOCKET";
else if ( type == ETHREAD) return "ETHREAD";
else if ( type == EGUI) return "EGUI";
else if ( type == EFATAL) return "EFATAL";
else if ( type == EBROKEN_ASSERT) return "EBROKEN_ASSERT";
else if ( type == EIMAGE_LOAD) return "EIMAGE_LOAD";
else if ( type == EDIR_CREATE) return "EDIR_CREATE";
else if ( type == EINCOMPATIBLE_OPTIONS) return "EINCOMPATIBLE_OPTIONS";
else if ( type == EMISSING_REQUIRED_OPTION) return "EMISSING_REQUIRED_OPTION";
else if ( type == EINVALID_OPTION_ARG) return "EINVALID_OPTION_ARG";
else if ( type == EMULTIPLE_OCCURANCES) return "EMULTIPLE_OCCURANCES";
else if ( type == ECONFIG_READER) return "ECONFIG_READER";
else if ( type == EIMAGE_SAVE) return "EIMAGE_SAVE";
else if ( type == ECAST_TO_STRING) return "ECAST_TO_STRING";
else if ( type == ESTRING_CAST) return "ESTRING_CAST";
else if ( type == EUTF8_TO_UTF32) return "EUTF8_TO_UTF32";
else if ( type == EOPTION_PARSE) return "EOPTION_PARSE";
else return "undefined error type";
}
const std::string info; // info about the error
const error_type type; // the type of the error
private:
const error& operator=(const error&);
};
// ----------------------------------------------------------------------------------------
class fatal_error : public error
{
/*!
WHAT THIS OBJECT REPRESENTS
As the name says, this object represents some kind of fatal error.
That is, it represents an unrecoverable error and any program that
throws this exception is, by definition, buggy and needs to be fixed.
Note that a fatal_error exception can only be thrown once. The second
time an application attempts to construct a fatal_error it will be
immediately aborted and an error message will be printed to std::cerr.
The reason for this is because the first fatal_error was apparently ignored
so the second fatal_error is going to make itself impossible to ignore
by calling abort. The lesson here is that you should not try to ignore
fatal errors.
This is also the exception thrown by the DLIB_ASSERT and DLIB_CASSERT macros.
!*/
public:
fatal_error(
error_type t,
const std::string& a
): error(t,a) {check_for_previous_fatal_errors();}
/*!
ensures
- #type == t
- #info == a
!*/
fatal_error(
error_type t
): error(t) {check_for_previous_fatal_errors();}
/*!
ensures
- #type == t
- #info == ""
!*/
fatal_error(
const std::string& a
): error(EFATAL,a) {check_for_previous_fatal_errors();}
/*!
ensures
- #type == EFATAL
- #info == a
!*/
fatal_error(
): error(EFATAL) {check_for_previous_fatal_errors();}
/*!
ensures
- #type == EFATAL
- #info == ""
!*/
private:
static inline char* message ()
{
static char buf[2000];
buf[1999] = '\0'; // just to be extra safe
return buf;
}
static inline void dlib_fatal_error_terminate (
)
{
std::cerr << "\n**************************** FATAL ERROR DETECTED ****************************";
std::cerr << message() << std::endl;
std::cerr << "******************************************************************************\n" << std::endl;
}
void check_for_previous_fatal_errors()
{
// If dlib is being use to create plugins for some other application, like
// MATLAB, then don't do these checks since it terminates the over arching
// system. Just let the errors go to the plugin handler and it will deal with
// them.
#if defined(MATLAB_MEX_FILE) || defined(DLIB_NO_ABORT_ON_2ND_FATAL_ERROR)
return;
#else
static bool is_first_fatal_error = true;
if (is_first_fatal_error == false)
{
std::cerr << "\n\n ************************** FATAL ERROR DETECTED ************************** " << std::endl;
std::cerr << " ************************** FATAL ERROR DETECTED ************************** " << std::endl;
std::cerr << " ************************** FATAL ERROR DETECTED ************************** \n" << std::endl;
std::cerr << "Two fatal errors have been detected, the first was inappropriately ignored. \n"
<< "To prevent further fatal errors from being ignored this application will be \n"
<< "terminated immediately and you should go fix this buggy program.\n\n"
<< "The error message from this fatal error was:\n" << this->what() << "\n\n" << std::endl;
using namespace std;
assert(false);
abort();
}
else
{
// copy the message into the fixed message buffer so that it can be recalled by dlib_fatal_error_terminate
// if needed.
char* msg = message();
unsigned long i;
for (i = 0; i < 2000-1 && i < this->info.size(); ++i)
msg[i] = info[i];
msg[i] = '\0';
// set this termination handler so that if the user doesn't catch this dlib::fatal_error that is being
// thrown then it will eventually be printed to standard error
std::set_terminate(&dlib_fatal_error_terminate);
}
is_first_fatal_error = false;
#endif
}
};
// ----------------------------------------------------------------------------------------
class gui_error : public error
{
public:
gui_error(
error_type t,
const std::string& a
): error(t,a) {}
/*!
ensures
- #type == t
- #info == a
!*/
gui_error(
error_type t
): error(t) {}
/*!
ensures
- #type == t
- #info == ""
!*/
gui_error(
const std::string& a
): error(EGUI,a) {}
/*!
ensures
- #type == EGUI
- #info == a
!*/
gui_error(
): error(EGUI) {}
/*!
ensures
- #type == EGUI
- #info == ""
!*/
};
// ----------------------------------------------------------------------------------------
class socket_error : public error
{
public:
socket_error(
error_type t,
const std::string& a
): error(t,a) {}
/*!
ensures
- #type == t
- #info == a
!*/
socket_error(
error_type t
): error(t) {}
/*!
ensures
- #type == t
- #info == ""
!*/
socket_error(
const std::string& a
): error(ESOCKET,a) {}
/*!
ensures
- #type == ESOCKET
- #info == a
!*/
socket_error(
): error(ESOCKET) {}
/*!
ensures
- #type == ESOCKET
- #info == ""
!*/
};
// ----------------------------------------------------------------------------------------
class thread_error : public error
{
public:
thread_error(
error_type t,
const std::string& a
): error(t,a) {}
/*!
ensures
- #type == t
- #info == a
!*/
thread_error(
error_type t
): error(t) {}
/*!
ensures
- #type == t
- #info == ""
!*/
thread_error(
const std::string& a
): error(ETHREAD,a) {}
/*!
ensures
- #type == ETHREAD
- #info == a
!*/
thread_error(
): error(ETHREAD) {}
/*!
ensures
- #type == ETHREAD
- #info == ""
!*/
};
// ----------------------------------------------------------------------------------------
class impossible_labeling_error : public dlib::error
{
/*!
WHAT THIS OBJECT REPRESENTS
This is the exception thrown by code that trains object detectors (e.g.
structural_svm_object_detection_problem) when they detect that the set of
truth boxes given to the training algorithm contains some impossible to
obtain outputs.
This kind of problem can happen when the set of image positions scanned by
the underlying object detection method doesn't include the truth rectangle
as a possible output. Another possibility is when two truth boxes are very
close together and hard coded non-max suppression logic would prevent two
boxes in such close proximity from being output.
!*/
public:
impossible_labeling_error(const std::string& msg) : dlib::error(msg) {};
};
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_ERROr_

View File

@@ -0,0 +1,161 @@
// Copyright (C) 2013 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_FLOAT_DEtAILS_Hh_
#define DLIB_FLOAT_DEtAILS_Hh_
#include <cmath>
#include "algs.h"
#include <limits>
namespace dlib
{
struct float_details
{
/*!
WHAT THIS OBJECT REPRESENTS
This object is a tool for converting floating point numbers into an
explicit integer representation and then also converting back. In
particular, a float_details object represents a floating point number with
a 64 bit mantissa and 16 bit exponent. These are stored in the public
fields of the same names.
The main use of this object is to convert floating point values into a
known uniform representation so they can be serialized to an output stream.
This allows dlib serialization code to work on any system, regardless of
the floating point representation used by the hardware. It also means
that, for example, a double can be serialized and then deserialized into a
float and it will perform the appropriate conversion.
In more detail, this object represents a floating point value equal to
mantissa*pow(2,exponent), except when exponent takes on any of the
following special values:
- is_inf
- is_ninf
- is_nan
These values are used to indicate that the floating point value should be
either infinity, negative infinity, or not-a-number respectively.
!*/
float_details(
int64 man,
int16 exp
) : mantissa(man), exponent(exp) {}
/*!
ensures
- #mantissa == man
- #exponent == exp
!*/
float_details() :
mantissa(0), exponent(0)
{}
/*!
ensures
- this object represents a floating point value of 0
!*/
float_details ( const double& val) { *this = val; }
float_details ( const float& val) { *this = val; }
float_details ( const long double& val) { *this = val; }
/*!
ensures
- converts the given value into a float_details representation. This
means that converting #*this back into a floating point number should
recover the input val.
!*/
float_details& operator= ( const double& val) { convert_from_T(val); return *this; }
float_details& operator= ( const float& val) { convert_from_T(val); return *this; }
float_details& operator= ( const long double& val) { convert_from_T(val); return *this; }
/*!
ensures
- converts the given value into a float_details representation. This
means that converting #*this back into a floating point number should
recover the input val.
!*/
operator double () const { return convert_to_T<double>(); }
operator float () const { return convert_to_T<float>(); }
operator long double () const { return convert_to_T<long double>(); }
/*!
ensures
- converts the contents of this float_details object into a floating point number.
!*/
const static int16 is_inf = 32000;
const static int16 is_ninf = 32001;
const static int16 is_nan = 32002;
int64 mantissa;
int16 exponent;
private:
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// IMPLEMENTATION DETAILS
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <typename T>
void convert_from_T (
const T& val
)
{
mantissa = 0;
const int digits = dlib::tmin<std::numeric_limits<T>::digits, 63>::value;
if (val == std::numeric_limits<T>::infinity())
{
exponent = is_inf;
}
else if (val == -std::numeric_limits<T>::infinity())
{
exponent = is_ninf;
}
else if (val < std::numeric_limits<T>::infinity())
{
int exp;
mantissa = static_cast<int64>(std::frexp(val, &exp)*(((uint64)1)<<digits));
exponent = exp - digits;
// Compact the representation a bit by shifting off any low order bytes
// which are zero in the mantissa. This makes the numbers in mantissa and
// exponent generally smaller which can make serialization and other things
// more efficient in some cases.
for (int i = 0; i < 8 && ((mantissa&0xFF)==0); ++i)
{
mantissa >>= 8;
exponent += 8;
}
}
else
{
exponent = is_nan;
}
}
template <typename T>
T convert_to_T (
) const
{
if (exponent < is_inf)
return std::ldexp((T)mantissa, exponent);
else if (exponent == is_inf)
return std::numeric_limits<T>::infinity();
else if (exponent == is_ninf)
return -std::numeric_limits<T>::infinity();
else
return std::numeric_limits<T>::quiet_NaN();
}
};
}
#endif // DLIB_FLOAT_DEtAILS_Hh_

View File

@@ -0,0 +1 @@
#include "dlib_include_path_tutorial.txt"

View File

@@ -0,0 +1,14 @@
// Copyright (C) 2011 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_HASh_
#define DLIB_HASh_
#include "general_hash/hash.h"
#include "general_hash/random_hashing.h"
#include "general_hash/count_bits.h"
#endif // DLIB_HASh_

View File

@@ -0,0 +1,107 @@
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_CMD_LINE_PARSER_OPTIOn_
#define DLIB_CMD_LINE_PARSER_OPTIOn_
#include <string>
namespace dlib
{
// ----------------------------------------------------------------------------------------
template <
typename charT
>
class cmd_line_parser_option
{
/*!
POINTERS AND REFERENCES TO INTERNAL DATA
None of the functions in cmd_line_parser_option will invalidate
pointers or references to internal data when called.
WHAT THIS OBJECT REPRESENTS
This object represents a command line option.
!*/
public:
typedef charT char_type;
typedef std::basic_string<charT> string_type;
virtual ~cmd_line_parser_option (
) = 0;
virtual const string_type& name (
) const = 0;
/*!
ensures
- returns the name of this option
!*/
virtual const string_type& group_name (
) const = 0;
/*!
ensures
- returns the name of the group this option is in. If no group was set for
this option then this function returns "".
!*/
virtual const string_type& description (
) const = 0;
/*!
ensures
- returns the description for this option
!*/
virtual unsigned long number_of_arguments(
) const = 0;
/*!
ensures
- returns the number of arguments for this option
!*/
virtual unsigned long count(
) const = 0;
/*!
ensures
- returns the number of times this option appears on the command line.
!*/
virtual const string_type& argument (
unsigned long arg = 0,
unsigned long N = 0
) const = 0;
/*!
requires
- arg < number_of_arguments()
- N < count()
ensures
- returns the arg-th argument to the Nth occurrence of this
option on the command line.
!*/
inline operator bool (
) const { return count() > 0; }
/*!
ensures
- returns true if this option appears on the command line at all
!*/
protected:
// restricted functions
cmd_line_parser_option& operator=(const cmd_line_parser_option&){return *this;}
};
// destructor does nothing
template < typename charT >
cmd_line_parser_option<charT>::~cmd_line_parser_option() {}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_CMD_LINE_PARSER_OPTIOn_

View File

@@ -0,0 +1,130 @@
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_ENUMERABLe_INTERFACE_
#define DLIB_ENUMERABLe_INTERFACE_
namespace dlib
{
// ----------------------------------------------------------------------------------------
template <
typename T
>
class enumerable
{
/*!
POINTERS AND REFERENCES TO INTERNAL DATA
- if (at_start()) then
- all pointers and references to data returned via element() are
invalid.
- calling move_next() or reset() invalidates pointers and references to
data returned via element() and only data returned via element().
- calling at_start(), current_element_valid(), size(), or element()
does NOT invalidate pointers or references to any internal data.
INITIAL VALUE
current_element_valid() == false
at_start() == true
WHAT THIS OBJECT REPRESENTS
This object represent an interface for iterating through the
elements in a container. It starts out one before the first element
in the container.
EXAMPLE: The following loops though all elements in the container
and prints them to cout.
container.reset();
while(container.move_next()) {
cout << container.element();
}
!*/
public:
typedef T type;
inline virtual ~enumerable(
) = 0;
virtual bool at_start (
) const = 0;
/*!
ensures
- returns true if *this represents one position before the first element
in the container (this would also make the current element invalid)
else returns false
!*/
virtual void reset (
) const = 0;
/*!
ensures
- #current_element_valid() == false
- #at_start() == true
!*/
virtual bool current_element_valid (
) const = 0;
/*!
ensures
- returns true if we are currently at a valid element else
returns false
!*/
virtual const T& element (
) const = 0;
/*!
requires
- current_element_valid() == true
ensures
- returns a const reference to the current element
!*/
virtual T& element (
) = 0;
/*!
requires
- current_element_valid() == true
ensures
- returns a non-const reference to the current element
!*/
virtual bool move_next (
) const = 0;
/*!
ensures
- moves to the next element. i.e. #element() will now
return the next element in the container
- the return value will be equal to #current_element_valid()
- #at_start() == false
- returns true if there is another element
- returns false if there are no more elements in the container
!*/
virtual size_t size (
) const = 0;
/*!
ensures
- returns the number of elements in *this
!*/
protected:
// restricted functions
enumerable& operator=(const enumerable&) {return *this;} // no assignment operator
};
// destructor does nothing
template <typename T>
enumerable<T>::~enumerable() {}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_ENUMERABLe_INTERFACE_

View File

@@ -0,0 +1,74 @@
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_MAP_PAIr_INTERFACE_
#define DLIB_MAP_PAIr_INTERFACE_
namespace dlib
{
// ----------------------------------------------------------------------------------------
template <
typename T1,
typename T2
>
class map_pair
{
/*!
POINTERS AND REFERENCES TO INTERNAL DATA
None of the functions in map_pair will invalidate
pointers or references to internal data when called.
WHAT THIS OBJECT REPRESENTS
this object is used to return the key/value pair used in the
map and hash_map containers when using the enumerable interface.
note that the enumerable interface is defined in
interfaces/enumerable.h
!*/
public:
typedef T1 key_type;
typedef T2 value_type;
virtual ~map_pair(
)=0;
virtual const T1& key(
) const =0;
/*!
ensures
- returns a const reference to the key
!*/
virtual const T2& value(
) const =0;
/*!
ensures
- returns a const reference to the value associated with key
!*/
virtual T2& value(
)=0;
/*!
ensures
- returns a non-const reference to the value associated with key
!*/
protected:
// restricted functions
map_pair<T1,T2>& operator=(const map_pair<T1,T2>&) {return *this;} // no assignment operator
};
// destructor does nothing
template <typename T1,typename T2>
map_pair<T1,T2>::~map_pair () {}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_MAP_PAIr_INTERFACE_

View File

@@ -0,0 +1,220 @@
// Copyright (C) 2005 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_REMOVER_KERNEl_INTERFACE_
#define DLIB_REMOVER_KERNEl_INTERFACE_
#include <functional>
namespace dlib
{
template <
typename T
>
class remover
{
/*!
REQUIREMENTS ON T
T is swappable by a global swap() and
T must have a default constructor
POINTERS AND REFERENCES TO INTERNAL DATA
The size() function does not invalidate pointers or
references to internal data. All other functions have no such
guarantee.
WHAT THIS OBJECT REPRESENTS
This object represents some generalized interface for removing
single items from container classes.
!*/
public:
typedef T type;
virtual ~remover(
);
/*!
ensures
- all resources associated with *this have been released.
!*/
virtual void remove_any (
T& item
) = 0;
/*!
requires
- size() != 0
ensures
- #size() == size() - 1
- removes an element from *this and swaps it into item.
- if (*this implements the enumerable interface) then
- #at_start() == true
!*/
virtual size_t size (
) const = 0;
/*!
ensures
- returns the number of elements in *this
!*/
protected:
// restricted functions
remover& operator=(const remover&) {return *this;} // assignment operator
};
// ----------------------------------------------------------------------------------------
template <
typename T,
typename compare
>
class asc_remover : public remover<T>
{
/*!
REQUIREMENTS ON T
T is swappable by a global swap() and
T must have a default constructor and
T must be comparable by compare where compare is a functor compatible with std::less
WHAT THIS OBJECT REPRESENTS
This object represents the same thing as remover except
that remove_any() will remove elements in ascending order
according to the compare functor.
!*/
public:
typedef compare compare_type;
protected:
// restricted functions
asc_remover& operator=(const asc_remover&) {return *this;} // assignment operator
};
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range
>
class pair_remover
{
/*!
REQUIREMENTS ON domain
domain is swappable by a global swap() and
domain must have a default constructor
REQUIREMENTS ON range
range is swappable by a global swap() and
range must have a default constructor
POINTERS AND REFERENCES TO INTERNAL DATA
The size() function does not invalidate pointers or
references to internal data. All other functions have no such
guarantee.
WHAT THIS OBJECT REPRESENTS
This object represents some generalized interface for removing
pairs from container classes which enforce some kind of pairing on
the elements that they contain.
!*/
public:
typedef domain domain_type;
typedef range range_type;
virtual ~pair_remover(
);
/*!
ensures
- all resources associated with *this have been released.
!*/
virtual void remove_any (
domain& d,
range& r
) = 0;
/*!
requires
- &d != &r (i.e. d and r cannot be the same variable)
- size() != 0
ensures
- #size() == size() - 1
- removes an element from the domain of *this and swaps it
into d.
- removes the element in *this's range that is associated
with #d and swaps it into r.
- if (*this implements the enumerable interface) then
- #at_start() == true
!*/
virtual size_t size (
) const = 0;
/*!
ensures
- returns the number of elements in *this
!*/
protected:
// restricted functions
pair_remover& operator=(const pair_remover&) {return *this;} // assignment operator
};
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename compare
>
class asc_pair_remover : public pair_remover<domain,range>
{
/*!
REQUIREMENTS ON domain
domain is swappable by a global swap() and
domain must have a default constructor and
domain must be comparable by compare where compare is a functor compatible with std::less
REQUIREMENTS ON range
range is swappable by a global swap() and
range must have a default constructor
WHAT THIS OBJECT REPRESENTS
This object represents the same thing as pair_remover except
that remove_any() will remove domain elements in ascending
order according to the compare functor.
!*/
public:
typedef compare compare_type;
protected:
// restricted functions
asc_pair_remover& operator=(const asc_pair_remover&) {return *this;} // assignment operator
};
// ----------------------------------------------------------------------------------------
// destructor does nothing
template <typename T>
remover<T>::~remover() {}
// destructor does nothing
template <typename domain, typename range>
pair_remover<domain,range>::~pair_remover() {}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_REMOVER_KERNEl_INTERFACE_

View File

@@ -0,0 +1 @@
#include "dlib_include_path_tutorial.txt"

View File

@@ -0,0 +1 @@
#include "dlib_include_path_tutorial.txt"

View File

@@ -0,0 +1 @@
#include "dlib_include_path_tutorial.txt"

View File

@@ -0,0 +1,162 @@
// Copyright (C) 2007 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_IS_KINd_H_
#define DLIB_IS_KINd_H_
#include <vector>
namespace dlib
{
/*!
This file contains a set of templates that enable you to determine if
a given type implements an abstract interface defined in one of the
dlib *_abstract.h files.
!*/
// ----------------------------------------------------------------------------------------
struct default_is_kind_value { static const bool value = false; };
// ----------------------------------------------------------------------------------------
template <typename T>
struct is_graph : public default_is_kind_value
{
/*!
- if (T is an implementation of graph/graph_kernel_abstract.h) then
- is_graph<T>::value == true
- else
- is_graph<T>::value == false
!*/
};
// ----------------------------------------------------------------------------------------
template <typename T>
struct is_directed_graph : public default_is_kind_value
{
/*!
- if (T is an implementation of directed_graph/directed_graph_kernel_abstract.h) then
- is_directed_graph<T>::value == true
- else
- is_directed_graph<T>::value == false
!*/
};
// ----------------------------------------------------------------------------------------
template <typename T, typename helper = void>
struct is_matrix : public default_is_kind_value
{
/*!
- if (T is some kind of matrix expression from the matrix/matrix_exp_abstract.h component) then
- is_matrix<T>::value == true
- else
- is_matrix<T>::value == false
!*/
// Don't set the helper to anything. Just let it be void.
ASSERT_ARE_SAME_TYPE(helper,void);
};
// ----------------------------------------------------------------------------------------
template <typename T>
struct is_array2d : public default_is_kind_value
{
/*!
- if (T is an implementation of array2d/array2d_kernel_abstract.h) then
- is_array2d<T>::value == true
- else
- is_array2d<T>::value == false
!*/
};
// ----------------------------------------------------------------------------------------
template <typename T>
struct is_array : public default_is_kind_value
{
/*!
- if (T is an implementation of array/array_kernel_abstract.h) then
- is_array<T>::value == true
- else
- is_array<T>::value == false
!*/
};
// ----------------------------------------------------------------------------------------
template <typename T>
struct is_std_vector : public default_is_kind_value
{
/*!
- if (T is an implementation of the standard C++ std::vector object) then
- is_std_vector<T>::value == true
- else
- is_std_vector<T>::value == false
!*/
};
// ----------------------------------------------------------------------------------------
template <typename T>
struct is_pair : public default_is_kind_value
{
/*!
- if (T is a std::pair object) then
- is_std_vector<T>::value == true
- else
- is_std_vector<T>::value == false
!*/
};
// ----------------------------------------------------------------------------------------
template <typename T>
struct is_rand : public default_is_kind_value
{
/*!
- if (T is an implementation of rand/rand_kernel_abstract.h) then
- is_rand<T>::value == true
- else
- is_rand<T>::value == false
!*/
};
// ----------------------------------------------------------------------------------------
template <typename T>
struct is_config_reader : public default_is_kind_value
{
/*!
- if (T is an implementation of config_reader/config_reader_kernel_abstract.h) then
- is_config_reader<T>::value == true
- else
- is_config_reader<T>::value == false
!*/
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// Implementation details
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <typename T, typename alloc>
struct is_std_vector<std::vector<T,alloc> > { const static bool value = true; };
template <typename T> struct is_std_vector<T&> { const static bool value = is_std_vector<T>::value; };
template <typename T> struct is_std_vector<const T&>{ const static bool value = is_std_vector<T>::value; };
template <typename T> struct is_std_vector<const T> { const static bool value = is_std_vector<T>::value; };
// ----------------------------------------------------------------------------------------
template <typename T, typename U>
struct is_pair<std::pair<T,U> > { const static bool value = true; };
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_IS_KINd_H_

View File

@@ -0,0 +1 @@
#include "dlib_include_path_tutorial.txt"

View File

@@ -0,0 +1 @@
#include "dlib_include_path_tutorial.txt"

View File

@@ -0,0 +1,11 @@
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_LOGGEr_
#define DLIB_LOGGEr_
#include "logger/logger_kernel_1.h"
#include "logger/extra_logger_headers.h"
#include "logger/logger_config_file.h"
#endif // DLIB_LOGGEr_

View File

@@ -0,0 +1,41 @@
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_EXTRA_LOGGER_HEADERs_
#define DLIB_EXTRA_LOGGER_HEADERs_
#include "logger_kernel_abstract.h"
#include "logger_kernel_1.h"
#include <iostream>
#include <string>
#include "../uintn.h"
// ----------------------------------------------------------------------------------------
namespace dlib
{
void print_datetime_logger_header (
std::ostream& out,
const std::string& logger_name,
const log_level& l,
const uint64 thread_id
);
/*!
requires
- is not called more than once at a time (i.e. is not called from multiple
threads at the same time).
ensures
- let DATE be the current date and time (e.g. Thu Aug 31 16:41:52 2006).
- prints a string to out in the form: "l.name (DATE) [thread_id] logger_name:"
!*/
}
// ----------------------------------------------------------------------------------------
#ifdef NO_MAKEFILE
#include "extra_logger_headers.cpp"
#endif
#endif // DLIB_EXTRA_LOGGER_HEADERs_

View File

@@ -0,0 +1,135 @@
// Copyright (C) 2007 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_LOGGER_CONFIg_FILE_
#define DLIB_LOGGER_CONFIg_FILE_
#include "logger_kernel_abstract.h"
#include "logger_kernel_1.h"
#include <string>
#include "../config_reader.h"
// ----------------------------------------------------------------------------------------
namespace dlib
{
class logger_config_file_error : public error
{
/*!
WHAT THIS OBJECT REPRESENTS
This is the exception class used by the configure_loggers_from_file()
function defined below.
!*/
public:
logger_config_file_error(const std::string& s):error(s){}
};
void configure_loggers_from_file (
const std::string& file_name
);
/*!
ensures
- configures the loggers with the contents of the file_name file
throws
- dlib::logger_config_file_error
this exception is thrown if there is a problem reading the config file
!*/
void configure_loggers_from_file (
const config_reader& cr
);
/*!
ensures
- configures the loggers with the contents of cr. This function is just like
the above version that reads from a file except that it reads from an in-memory
config_reader instead.
throws
- dlib::logger_config_file_error
this exception is thrown if there is a problem reading the config file
!*/
// ----------------------------------------------------------------------------------------
/*!
# -----------------------------------------------
# ------------- EXAMPLE CONFIG FILE -------------
# -----------------------------------------------
# The overall format of the config file is the same as the one defined by
# the config_reader component of this library.
# This line is a comment line
# The config file always has a block named logger_config. This is where all the
# config data for the loggers reside.
logger_config
{
# This sets all loggers to the level LINFO since it is just inside the
# logger_config block
logging_level = info
# Alternatively we could specify a user defined logging level by
# supplying a priority number. The following line would specify
# that only logging levels at or above 100 are printed. (note that
# you would have to comment out the logging_level statement above
# to avoid a conflict).
# logging_level = 100
parent_logger
{
# This sets all loggers named "parent_logger" or children of
# loggers with that name to not log at all (i.e. to logging level
# LNONE).
logging_level = none
}
parent_logger2
{
# set loggers named "parent_logger2" and its children loggers
# to write their output to a file named out.txt
output = file out.txt
child_logger
{
# Set loggers named "parent_logger2.child_logger" and children of loggers
# with this name to logging level LALL
logging_level = all
# Note that this logger will also log to out.txt because that is what
# its parent does and we haven't overridden it here with something else.
# if we wanted this logger to write to cout instead we could uncomment
# the following line:
# output = cout
}
}
}
# So in summary, all logger config stuff goes inside a block named logger_config. Then
# inside that block all blocks must be the names of loggers. There are only two keys,
# logging_level and output.
#
# The valid values of logging_level are:
# "LALL", "LNONE", "LTRACE", "LDEBUG", "LINFO", "LWARN", "LERROR", "LFATAL",
# "ALL", "NONE", "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL",
# "all", "none", "trace", "debug", "info", "warn", "error", "fatal", or
# any integral value
#
# The valid values of output are:
# "cout", "cerr", "clog", or a string of the form "file some_file_name"
# which causes the output to be logged to the specified file.
#
!*/
}
// ----------------------------------------------------------------------------------------
#ifdef NO_MAKEFILE
#include "logger_config_file.cpp"
#endif
#endif // DLIB_LOGGER_CONFIg_FILE_

View File

@@ -0,0 +1,687 @@
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_LOGGER_KERNEl_1_
#define DLIB_LOGGER_KERNEl_1_
#include <limits>
#include <memory>
#include <cstring>
#include <streambuf>
#include <vector>
#include "../threads.h"
#include "../misc_api.h"
#include "../set.h"
#include "logger_kernel_abstract.h"
#include "../algs.h"
#include "../assert.h"
#include "../uintn.h"
#include "../map.h"
#include "../member_function_pointer.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
class log_level
{
public:
log_level(
int priority_,
const char* name_
) :
priority(priority_)
{
strncpy(name,name_,19);
name[19] = '\0';
}
bool operator< (const log_level& rhs) const { return priority < rhs.priority; }
bool operator<=(const log_level& rhs) const { return priority <= rhs.priority; }
bool operator> (const log_level& rhs) const { return priority > rhs.priority; }
bool operator>=(const log_level& rhs) const { return priority >= rhs.priority; }
int priority;
char name[20];
};
inline std::ostream& operator<< (std::ostream& out, const log_level& item)
{
out << item.name;
return out;
}
const log_level LALL (std::numeric_limits<int>::min(),"ALL");
const log_level LNONE (std::numeric_limits<int>::max(),"NONE");
const log_level LTRACE(-100,"TRACE");
const log_level LDEBUG(0 ,"DEBUG");
const log_level LINFO (100,"INFO ");
const log_level LWARN (200,"WARN ");
const log_level LERROR(300,"ERROR");
const log_level LFATAL(400,"FATAL");
// ----------------------------------------------------------------------------------------
void set_all_logging_output_streams (
std::ostream& out
);
void set_all_logging_levels (
const log_level& new_level
);
typedef void (*print_header_type)(
std::ostream& out,
const std::string& logger_name,
const log_level& l,
const uint64 thread_id
);
void set_all_logging_headers (
const print_header_type& new_header
);
// ----------------------------------------------------------------------------------------
void print_default_logger_header (
std::ostream& out,
const std::string& logger_name,
const log_level& l,
const uint64 thread_id
);
template <
typename T
>
void set_all_logging_output_hooks (
T& object,
void (T::*hook_)(const std::string& logger_name,
const log_level& l,
const uint64 thread_id,
const char* message_to_log)
);
template <
typename T
>
void set_all_logging_output_hooks (
T& object
)
{
set_all_logging_output_hooks(object, &T::log);
}
// ----------------------------------------------------------------------------------------
class logger
{
/*!
INITIAL VALUE
- print_header == print_default_logger_header
- out.rdbuf() == std::cout.rdbuf()
- cur_level == LERROR
- auto_flush_enabled == true
- hook.is_set() == false
CONVENTION
- print_header == logger_header()
- if (hook.is_set() == false) then
- out.rdbuf() == output_streambuf()
- else
- out.rdbuf() == &gd.hookbuf
- output_streambuf() == 0
- cur_level == level()
- logger_name == name()
- auto_flush_enabled == auto_flush()
- logger::gd::loggers == a set containing all currently existing loggers.
- logger::gd::m == the mutex used to lock everything in the logger
- logger::gd::thread_names == a map of thread ids to thread names.
- logger::gd::next_thread_name == the next thread name that will be given out
to a thread when we find that it isn't already in thread_names.
!*/
// ------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------
class logger_stream
{
/*!
INITIAL VALUE
- been_used == false
CONVENTION
- enabled == is_enabled()
- if (been_used) then
- logger::gd::m is locked
- someone has used the << operator to write something to the
output stream.
!*/
public:
logger_stream (
const log_level& l_,
logger& log_
) :
l(l_),
log(log_),
been_used(false),
enabled (l.priority >= log.cur_level.priority)
{}
inline ~logger_stream(
)
{
if (!been_used)
{
return;
}
else
{
print_end_of_line();
}
}
bool is_enabled (
) const { return enabled; }
template <typename T>
inline logger_stream& operator << (
const T& item
)
{
if (!enabled)
{
return *this;
}
else
{
print_header_and_stuff();
log.out << item;
return *this;
}
}
private:
void print_header_and_stuff (
);
/*!
ensures
- if (!been_used) then
- prints the logger header
- locks log.gd.m
- #been_used == true
!*/
void print_end_of_line (
);
/*!
ensures
- prints a newline to log.out
- unlocks log.gd.m
!*/
const log_level& l;
logger& log;
bool been_used;
const bool enabled;
}; // end of class logger_stream
// ------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------
friend class logger_stream;
public:
typedef member_function_pointer<const std::string&, const log_level&,
const uint64, const char*> hook_mfp;
logger (
const std::string& name_
);
virtual ~logger (
);
const std::string& name (
) const { return logger_name; }
logger_stream operator << (
const log_level& l
) const { return logger_stream(l,const_cast<logger&>(*this)); }
bool is_child_of (
const logger& log
) const
{
return (name().find(log.name() + ".") == 0) || (log.name() == name());
}
const log_level level (
) const
{
auto_mutex M(gd.m);
return log_level(cur_level);
};
void set_level (
const log_level& new_level
)
{
auto_mutex M(gd.m);
gd.loggers.reset();
while (gd.loggers.move_next())
{
if (gd.loggers.element()->is_child_of(*this))
gd.loggers.element()->cur_level = new_level;
}
gd.set_level(logger_name, new_level);
}
bool auto_flush (
) const
{
auto_mutex M(gd.m);
return auto_flush_enabled;
};
void set_auto_flush (
bool enabled
)
{
auto_mutex M(gd.m);
gd.loggers.reset();
while (gd.loggers.move_next())
{
if (gd.loggers.element()->is_child_of(*this))
gd.loggers.element()->auto_flush_enabled = enabled;
}
gd.set_auto_flush(logger_name, enabled);
}
std::streambuf* output_streambuf (
)
{
auto_mutex M(gd.m);
// if there is an output hook set then we are supposed to return 0.
if (hook)
return 0;
else
return out.rdbuf();
}
template <
typename T
>
void set_output_hook (
T& object,
void (T::*hook_)(const std::string& logger_name,
const log_level& l,
const uint64 thread_id,
const char* message_to_log)
)
{
auto_mutex M(gd.m);
hook.set(object, hook_);
gd.loggers.reset();
while (gd.loggers.move_next())
{
if (gd.loggers.element()->is_child_of(*this))
{
gd.loggers.element()->out.rdbuf(&gd.hookbuf);
gd.loggers.element()->hook = hook;
}
}
gd.set_output_hook(logger_name, hook);
gd.set_output_stream(logger_name, gd.hookbuf);
}
void set_output_stream (
std::ostream& out_
)
{
auto_mutex M(gd.m);
gd.loggers.reset();
while (gd.loggers.move_next())
{
if (gd.loggers.element()->is_child_of(*this))
{
gd.loggers.element()->out.rdbuf(out_.rdbuf());
gd.loggers.element()->hook.clear();
}
}
gd.set_output_stream(logger_name, out_);
hook.clear();
gd.set_output_hook(logger_name, hook);
}
print_header_type logger_header (
) const { return print_header; }
void set_logger_header (
print_header_type ph
)
{
auto_mutex M(gd.m);
gd.loggers.reset();
while (gd.loggers.move_next())
{
if (gd.loggers.element()->is_child_of(*this))
gd.loggers.element()->print_header = ph;
}
gd.set_logger_header(logger_name, ph);
}
private:
// ------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------
struct global_data
{
rmutex m;
set<logger*>::kernel_1b loggers;
map<thread_id_type,uint64>::kernel_1b thread_names;
uint64 next_thread_name;
// Make a very simple streambuf that writes characters into a std::vector<char>. We can
// use this as the output target for hooks. The reason we don't just use a std::ostringstream
// instead is that this way we can be guaranteed that logging doesn't perform memory allocations.
// This is because a std::vector never frees memory. I.e. its capacity() doesn't go down when
// you resize it back to 0. It just stays the same.
class hook_streambuf : public std::streambuf
{
public:
std::vector<char> buffer;
int_type overflow ( int_type c)
{
if (c != EOF) buffer.push_back(static_cast<char>(c));
return c;
}
std::streamsize xsputn ( const char* s, std::streamsize num)
{
buffer.insert(buffer.end(), s, s+num);
return num;
}
};
hook_streambuf hookbuf;
global_data (
);
~global_data(
);
uint64 get_thread_name (
);
/*!
requires
- m is locked
ensures
- returns a unique id for the calling thread. also makes the number
small and nice unlike what you get from get_thread_id()
!*/
void thread_end_handler (
);
/*!
ensures
- removes the terminated thread from thread_names
!*/
struct level_container
{
level_container ();
log_level val;
map<std::string,std::unique_ptr<level_container> >::kernel_1b_c table;
} level_table;
const log_level level (
const std::string& name
) const;
/*!
ensures
- returns the level loggers with the given name are supposed
to have
!*/
void set_level (
const std::string& name,
const log_level& new_level
);
/*!
ensures
- for all children C of name:
- #level(C) == new_level
- if name == "" then
- for all loggers L:
- #level(L) == new_level
!*/
struct auto_flush_container
{
bool val;
map<std::string,std::unique_ptr<auto_flush_container> >::kernel_1b_c table;
} auto_flush_table;
bool auto_flush (
const std::string& name
) const;
/*!
ensures
- returns the auto_flush value loggers with the given name are supposed
to have
!*/
void set_auto_flush (
const std::string& name,
bool enabled
);
/*!
ensures
- for all children C of name:
- #auto_flush_enabled(C) == enabled
- if name == "" then
- for all loggers L:
- #auto_flush_enabled(L) == enabled
!*/
struct output_streambuf_container
{
std::streambuf* val;
map<std::string,std::unique_ptr<output_streambuf_container> >::kernel_1b_c table;
} streambuf_table;
std::streambuf* output_streambuf (
const std::string& name
);
/*!
ensures
- returns the streambuf loggers with the given name are supposed
to have
!*/
void set_output_stream (
const std::string& name,
std::ostream& out_
);
/*!
ensures
- for all children C of name:
- #output_streambuf(C) == out_.rdbuf()
- if name == "" then
- for all loggers L:
- #output_streambuf(L) == out_.rdbuf()
!*/
void set_output_stream (
const std::string& name,
std::streambuf& buf
);
/*!
ensures
- for all children C of name:
- #output_streambuf(C) == &buf
- if name == "" then
- for all loggers L:
- #output_streambuf(L) == &buf
!*/
struct output_hook_container
{
hook_mfp val;
map<std::string,std::unique_ptr<output_hook_container> >::kernel_1b_c table;
} hook_table;
hook_mfp output_hook (
const std::string& name
);
/*!
ensures
- returns the hook loggers with the given name are supposed
to have
!*/
void set_output_hook (
const std::string& name,
const hook_mfp& hook
);
/*!
ensures
- for all children C of name:
- #output_hook(C) == hook
- if name == "" then
- for all loggers L:
- #output_hook(L) == hook
!*/
struct logger_header_container
{
print_header_type val;
map<std::string,std::unique_ptr<logger_header_container> >::kernel_1b_c table;
} header_table;
print_header_type logger_header (
const std::string& name
);
/*!
ensures
- returns the header function loggers with the given name are supposed
to have
!*/
void set_logger_header (
const std::string& name,
print_header_type ph
);
/*!
ensures
- for all children C of name:
- #logger_header(C) == ph
- if name == "" then
- for all loggers L:
- #logger_header(L) == ph
!*/
}; // end of struct global_data
static global_data& get_global_data();
// ------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------
friend void set_all_logging_levels (
const log_level& new_level
);
friend void set_all_logging_headers (
const print_header_type& new_header
);
friend void set_all_logging_output_streams (
std::ostream& out
);
template <
typename T
>
friend void set_all_logging_output_hooks (
T& object,
void (T::*hook_)(const std::string& logger_name,
const log_level& l,
const uint64 thread_id,
const char* message_to_log)
)
{
logger::hook_mfp hook;
// There is a bug in one of the versions (but not all apparently) of
// Visual studio 2005 that causes it to error out if <T> isn't in the
// following line of code. However, there is also a bug in gcc-3.3
// that causes it to error out if <T> is present. So this works around
// this problem.
#if defined(_MSC_VER) && _MSC_VER == 1400
hook.set<T>(object, hook_);
#else
hook.set(object, hook_);
#endif
logger::global_data& gd = logger::get_global_data();
auto_mutex M(gd.m);
gd.loggers.reset();
while (gd.loggers.move_next())
{
gd.loggers.element()->out.rdbuf(&gd.hookbuf);
gd.loggers.element()->hook = hook;
}
gd.set_output_stream("",gd.hookbuf);
gd.set_output_hook("",hook);
}
// ------------------------------------------------------------------------------------
global_data& gd;
const std::string logger_name;
print_header_type print_header;
bool auto_flush_enabled;
std::ostream out;
log_level cur_level;
hook_mfp hook;
// restricted functions
logger(const logger&); // copy constructor
logger& operator=(const logger&); // assignment operator
};
// ----------------------------------------------------------------------------------------
}
#ifdef NO_MAKEFILE
#include "logger_kernel_1.cpp"
#endif
#endif // DLIB_LOGGER_KERNEl_1_

View File

@@ -0,0 +1,429 @@
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_LOGGER_KERNEl_ABSTRACT_
#ifdef DLIB_LOGGER_KERNEl_ABSTRACT_
#include "../threads.h"
#include <limits>
#include <string>
#include <iostream>
#include "../uintn.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class log_level
{
/*!
WHAT THIS OBJECT REPRESENTS
This object is a simple named level to log at. It contains a numeric
priority and a name to use in the logging messages.
!*/
public:
log_level(
int priority_,
const char* name_
);
/*!
ensures
- #priority = priority_
- the first 19 characters of name_ are copied into name and name
is null terminated.
!*/
bool operator< (const log_level& rhs) const { return priority < rhs.priority; }
bool operator<=(const log_level& rhs) const { return priority <= rhs.priority; }
bool operator> (const log_level& rhs) const { return priority > rhs.priority; }
bool operator>=(const log_level& rhs) const { return priority >= rhs.priority; }
int priority;
char name[20];
};
inline std::ostream& operator<< (std::ostream& out, const log_level& item);
/*!
ensures
- performs out << item.name
- returns out
!*/
// ----------------------------------------------------------------------------------------
const log_level LALL (std::numeric_limits<int>::min(),"ALL");
const log_level LNONE (std::numeric_limits<int>::max(),"NONE");
const log_level LTRACE(-100,"TRACE");
const log_level LDEBUG(0 ,"DEBUG");
const log_level LINFO (100 ,"INFO ");
const log_level LWARN (200 ,"WARN ");
const log_level LERROR(300 ,"ERROR");
const log_level LFATAL(400 ,"FATAL");
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
void set_all_logging_output_streams (
std::ostream& out
);
/*!
ensures
- for all loggers L (even loggers not yet constructed):
- #L.output_streambuf() == out.rdbuf()
- Removes any previous output hook from L. So now the logger
L will write all its messages to the given output stream.
throws
- std::bad_alloc
!*/
// ----------------------------------------------------------------------------------------
typedef void (*print_header_type)(
std::ostream& out,
const std::string& logger_name,
const log_level& l,
const uint64 thread_id
);
void set_all_logging_headers (
const print_header_type& new_header
);
/*!
ensures
- for all loggers L (even loggers not yet constructed):
- #L.logger_header() == new_header
throws
- std::bad_alloc
!*/
// ----------------------------------------------------------------------------------------
template <
typename T
>
void set_all_logging_output_hooks (
T& object,
void (T::*hook)(const std::string& logger_name,
const log_level& l,
const uint64 thread_id,
const char* message_to_log)
);
/*!
ensures
- for all loggers L (even loggers not yet constructed):
- #L.output_streambuf() == 0
- performs the equivalent to calling L.set_output_hook(object, hook);
(i.e. sets all loggers so that they will use the given hook function)
throws
- std::bad_alloc
!*/
template <
typename T
>
void set_all_logging_output_hooks (
T& object
);
/*!
ensures
- calls set_all_logging_output_hooks(object, &T::log);
!*/
// ----------------------------------------------------------------------------------------
void set_all_logging_levels (
const log_level& new_level
);
/*!
ensures
- for all loggers L (even loggers not yet constructed):
- #L.level() == new_level
throws
- std::bad_alloc
!*/
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
void print_default_logger_header (
std::ostream& out,
const std::string& logger_name,
const log_level& l,
const uint64 thread_id
);
/*!
requires
- is not called more than once at a time (i.e. is not called from multiple
threads at the same time).
ensures
- let MS be the number of milliseconds since program start.
- prints a string to out in the form: "MS l.name [thread_id] logger_name:"
!*/
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class logger
{
/*!
INITIAL VALUE
- name() == a user supplied value given to the constructor
- The values of level(), output_streambuf(), logger_header(), and
auto_flush() are inherited from the parent of this logger.
WHAT THIS OBJECT REPRESENTS
This object represents a logging output stream in the style of the log4j
logger available for Java.
Additionally, the logger doesn't perform any memory allocations during
each logging action. It just writes directly into the user supplied output
stream. Alternatively, if you use a logging output hook no memory allocations
are performed either. Logging just goes straight into a memory buffer
which gets passed to the user supplied logging hook.
DEFAULTS
If the user hasn't specified values for the four inherited values level(),
output_streambuf(), logger_header(), or auto_flush() then the default
values will be used. The defaults are as follows:
- level() == LERROR
- output_streambuf() == std::cout.rdbuf() (i.e. the default is to log
to standard output).
- logger_header() == print_default_logger_header
- auto_flush() == true
THREAD SAFETY
All methods of this class are thread safe. Note that it is safe to
chain calls to operator << such as:
log << LINFO << "message " << variable << " more message";
The logger ensures that the entire statement executes atomically so the
message won't be broken up by other loggers in other threads.
!*/
class logger_stream
{
public:
bool is_enabled (
) const;
/*!
ensures
- returns true if this logger stream will print out items
given to it by the << operator. returns false otherwise.
!*/
template <typename T>
logger_stream& operator << (
const T& item
);
/*!
ensures
- if (is_enabled()) then
- writes item to this output stream
- returns *this
!*/
};
public:
logger (
const std::string& name_
);
/*!
requires
- name_ != ""
ensures
- #*this is properly initialized
- #name() == name_
throws
- std::bad_alloc
- dlib::thread_error
!*/
virtual ~logger (
);
/*!
ensures
- any resources associated with *this have been released
!*/
const std::string& name (
) const;
/*!
ensures
- returns the name of this logger
!*/
logger_stream operator << (
const log_level& l
) const;
/*!
ensures
- if (l.priority >= level().priority) then
- returns a logger_stream with is_enabled() == true. I.e. this
returned stream will write its output to the I/O destination
used by this logger object.
- else
- returns a logger stream with is_enabled() == false
throws
- std::bad_alloc
!*/
bool is_child_of (
const logger& log
) const;
/*!
ensures
- if ( (name().find(log.name() + ".") == 0) || (log.name() == name()) ) then
- returns true
(i.e. if log.name() + "." is a prefix of name() or if both *this and log
have the same name then return true)
- else
- returns false
!*/
const log_level level (
) const;
/*!
ensures
- returns the current log level of this logger.
!*/
void set_level (
const log_level& new_level
);
/*!
ensures
- for all loggers L such that L.is_child_of(*this) == true:
- #L.level() == new_level
throws
- std::bad_alloc
!*/
bool auto_flush (
);
/*!
ensures
- returns true if the output stream is flushed after every logged message.
returns false otherwise. (Note that flushing only does anything if
the logger is set to use an output stream rather than a hook)
!*/
void set_auto_flush (
bool enabled
);
/*!
ensures
- for all loggers L such that L.is_child_of(*this) == true:
- #L.auto_flush() == enabled
throws
- std::bad_alloc
!*/
template <
typename T
>
void set_output_hook (
T& object,
void (T::*hook)(const std::string& logger_name,
const log_level& l,
const uint64 thread_id,
const char* message_to_log)
);
/*!
requires
- hook is a valid pointer to a member function in T
ensures
- for all loggers L such that L.is_child_of(*this) == true:
- #L.output_streambuf() == 0
- #L will not send its log messages to an ostream object anymore. Instead
it will call the given hook member function (i.e. (object.*hook)(name,l,id,msg) )
for each message that needs to be logged.
- The arguments to the hook function have the following meanings:
- logger_name == The name of the logger that is printing the log message.
- l == The level of the logger that is printing the log message.
- thread_id == A number that uniquely identifies the thread trying to log
the message. Note that this number is unique among all threads, past and
present. Also note that this id is not the same one returned by
get_thread_id().
- message_to_log == the actual text of the message the user is giving to
the logger object to log.
- All hook functions will also only be called one at a time. This means
that hook functions don't need to be thread safe.
!*/
std::streambuf* output_streambuf (
);
/*!
ensures
- if (an output hook isn't set) then
- returns the output stream buffer that this logger writes all
messages to.
- else
- returns 0
!*/
void set_output_stream (
std::ostream& out
);
/*!
ensures
- for all loggers L such that L.is_child_of(*this) == true:
- #L.output_streambuf() == out.rdbuf()
- Removes any previous output hook from L. So now the logger
L will write all its messages to the given output stream.
throws
- std::bad_alloc
!*/
print_header_type logger_header (
) const;
/*!
ensures
- returns the function that is called to print the header information
onto each logged message. The arguments to the function have the following
meanings:
- out == The output stream this function writes the header to.
- logger_name == The name of the logger that is printing the log message.
- l == The level of the logger that is printing the log message.
- thread_id == A number that uniquely identifies the thread trying to log
the message. Note that this number is unique among all threads, past and
present. Also note that this id is not the same one returned by
get_thread_id().
- This logger_header function will also only be called once at a time. This means
the logger_header function doesn't need to be thread safe.
- the logger_header function is only used when output_streambuf() != 0
!*/
void set_logger_header (
print_header_type print_header
);
/*!
ensures
- for all loggers L such that L.is_child_of(*this) == true:
- #L.logger_header() == print_header
throws
- std::bad_alloc
!*/
private:
// restricted functions
logger(const logger&); // copy constructor
logger& operator=(const logger&); // assignment operator
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_LOGGER_KERNEl_ABSTRACT_

View File

@@ -0,0 +1,59 @@
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_MAp_
#define DLIB_MAp_
#include "map/map_kernel_1.h"
#include "map/map_kernel_c.h"
#include "binary_search_tree.h"
#include "algs.h"
#include <functional>
namespace dlib
{
template <
typename domain,
typename range,
typename mem_manager = default_memory_manager,
typename compare = std::less<domain>
>
class map
{
map() {}
// a typedef for the binary search tree used by kernel_2
typedef typename binary_search_tree<domain,range,mem_manager,compare>::kernel_1a
binary_search_tree_1;
// a typedef for the binary search tree used by kernel_2
typedef typename binary_search_tree<domain,range,mem_manager,compare>::kernel_2a
binary_search_tree_2;
public:
//----------- kernels ---------------
// kernel_1a
typedef map_kernel_1<domain,range,binary_search_tree_1,mem_manager>
kernel_1a;
typedef map_kernel_c<kernel_1a >
kernel_1a_c;
// kernel_1b
typedef map_kernel_1<domain,range,binary_search_tree_2,mem_manager>
kernel_1b;
typedef map_kernel_c<kernel_1b >
kernel_1b_c;
};
}
#endif // DLIB_MAp_

View File

@@ -0,0 +1,436 @@
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_MAP_KERNEl_1_
#define DLIB_MAP_KERNEl_1_
#include "map_kernel_abstract.h"
#include "../algs.h"
#include "../interfaces/enumerable.h"
#include "../interfaces/map_pair.h"
#include "../interfaces/remover.h"
#include "../serialize.h"
namespace dlib
{
template <
typename domain,
typename range,
typename bst_base,
typename mem_manager = default_memory_manager
>
class map_kernel_1 : public enumerable<map_pair<domain,range> >,
public asc_pair_remover<domain,range,typename bst_base::compare_type>
{
/*!
REQUIREMENTS ON BST_BASE
bst_base is instantiated with domain and range and
implements binary_search_tree/binary_search_tree_kernel_abstract.h
INITIAL VALUE
bst has its initial value
CONVENTION
bst.size() == the number of elements in the map and
the elements in map are stored in bst_base
!*/
public:
typedef domain domain_type;
typedef range range_type;
typedef typename bst_base::compare_type compare_type;
typedef mem_manager mem_manager_type;
map_kernel_1(
)
{}
virtual ~map_kernel_1(
)
{}
inline void clear(
);
inline void add (
domain& d,
range& r
);
inline bool is_in_domain (
const domain& d
) const;
inline void remove_any (
domain& d,
range& r
);
inline void remove (
const domain& d,
domain& d_copy,
range& r
);
inline void destroy (
const domain& d
);
inline range& operator[] (
const domain& d
);
inline const range& operator[] (
const domain& d
) const;
inline void swap (
map_kernel_1& item
);
// functions from the enumerable interface
inline size_t size (
) const;
inline bool at_start (
) const;
inline void reset (
) const;
inline bool current_element_valid (
) const;
inline const map_pair<domain,range>& element (
) const;
inline map_pair<domain,range>& element (
);
inline bool move_next (
) const;
private:
bst_base bst;
// restricted functions
map_kernel_1(map_kernel_1&);
map_kernel_1& operator= ( map_kernel_1&);
};
template <
typename domain,
typename range,
typename bst_base,
typename mem_manager
>
inline void swap (
map_kernel_1<domain,range,bst_base,mem_manager>& a,
map_kernel_1<domain,range,bst_base,mem_manager>& b
) { a.swap(b); }
template <
typename domain,
typename range,
typename bst_base,
typename mem_manager
>
void deserialize (
map_kernel_1<domain,range,bst_base,mem_manager>& item,
std::istream& in
)
{
try
{
item.clear();
unsigned long size;
deserialize(size,in);
domain d;
range r;
for (unsigned long i = 0; i < size; ++i)
{
deserialize(d,in);
deserialize(r,in);
item.add(d,r);
}
}
catch (serialization_error& e)
{
item.clear();
throw serialization_error(e.info + "\n while deserializing object of type map_kernel_1");
}
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename bst_base,
typename mem_manager
>
void map_kernel_1<domain,range,bst_base,mem_manager>::
clear (
)
{
bst.clear();
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename bst_base,
typename mem_manager
>
void map_kernel_1<domain,range,bst_base,mem_manager>::
add(
domain& d,
range& r
)
{
// try to add pair to bst_base
bst.add(d,r);
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename bst_base,
typename mem_manager
>
bool map_kernel_1<domain,range,bst_base,mem_manager>::
is_in_domain(
const domain& d
) const
{
return (bst[d] != 0);
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename bst_base,
typename mem_manager
>
void map_kernel_1<domain,range,bst_base,mem_manager>::
remove_any(
domain& d,
range& r
)
{
bst.remove_any(d,r);
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename bst_base,
typename mem_manager
>
void map_kernel_1<domain,range,bst_base,mem_manager>::
remove (
const domain& d,
domain& d_copy,
range& r
)
{
bst.remove(d,d_copy,r);
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename bst_base,
typename mem_manager
>
void map_kernel_1<domain,range,bst_base,mem_manager>::
destroy (
const domain& d
)
{
bst.destroy(d);
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename bst_base,
typename mem_manager
>
range& map_kernel_1<domain,range,bst_base,mem_manager>::
operator[](
const domain& d
)
{
return *bst[d];
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename bst_base,
typename mem_manager
>
const range& map_kernel_1<domain,range,bst_base,mem_manager>::
operator[](
const domain& d
) const
{
return *bst[d];
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename bst_base,
typename mem_manager
>
size_t map_kernel_1<domain,range,bst_base,mem_manager>::
size (
) const
{
return bst.size();
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename bst_base,
typename mem_manager
>
void map_kernel_1<domain,range,bst_base,mem_manager>::
swap (
map_kernel_1<domain,range,bst_base,mem_manager>& item
)
{
bst.swap(item.bst);
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// enumerable function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename bst_base,
typename mem_manager
>
bool map_kernel_1<domain,range,bst_base,mem_manager>::
at_start (
) const
{
return bst.at_start();
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename bst_base,
typename mem_manager
>
void map_kernel_1<domain,range,bst_base,mem_manager>::
reset (
) const
{
bst.reset();
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename bst_base,
typename mem_manager
>
bool map_kernel_1<domain,range,bst_base,mem_manager>::
current_element_valid (
) const
{
return bst.current_element_valid();
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename bst_base,
typename mem_manager
>
const map_pair<domain,range>& map_kernel_1<domain,range,bst_base,mem_manager>::
element (
) const
{
return bst.element();
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename bst_base,
typename mem_manager
>
map_pair<domain,range>& map_kernel_1<domain,range,bst_base,mem_manager>::
element (
)
{
return bst.element();
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename bst_base,
typename mem_manager
>
bool map_kernel_1<domain,range,bst_base,mem_manager>::
move_next (
) const
{
return bst.move_next();
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_MAP_KERNEl_1_

View File

@@ -0,0 +1,235 @@
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_MAP_KERNEl_ABSTRACT_
#ifdef DLIB_MAP_KERNEl_ABSTRACT_
#include "../interfaces/map_pair.h"
#include "../interfaces/enumerable.h"
#include "../interfaces/remover.h"
#include "../serialize.h"
#include "../algs.h"
#include <functional>
namespace dlib
{
template <
typename domain,
typename range,
typename mem_manager = default_memory_manager,
typename compare = std::less<domain>
>
class map : public enumerable<map_pair<domain,range> >,
public asc_pair_remover<domain,range,compare>
{
/*!
REQUIREMENTS ON domain
domain must be comparable by compare where compare is a functor compatible with std::less and
domain is swappable by a global swap() and
domain must have a default constructor
REQUIREMENTS ON range
range is swappable by a global swap() and
range must have a default constructor
REQUIREMENTS ON mem_manager
must be an implementation of memory_manager/memory_manager_kernel_abstract.h or
must be an implementation of memory_manager_global/memory_manager_global_kernel_abstract.h or
must be an implementation of memory_manager_stateless/memory_manager_stateless_kernel_abstract.h
mem_manager::type can be set to anything.
POINTERS AND REFERENCES TO INTERNAL DATA
swap(), is_in_domain(), and operator[] functions do not invalidate
pointers or references to internal data.
All other functions have no such guarantee.
INITIAL VALUE
size() == 0
ENUMERATION ORDER
The enumerator will iterate over the domain (and each associated
range element) elements in ascending order according to the compare functor.
(i.e. the elements are enumerated in sorted order)
WHAT THIS OBJECT REPRESENTS
map contains items of type domain and range
This object is similar an array. It maps items of type domain on to
items of type range.
Also note that unless specified otherwise, no member functions
of this object throw exceptions.
definition of equivalent:
a is equivalent to b if
a < b == false and
b < a == false
!*/
public:
typedef domain domain_type;
typedef range range_type;
typedef compare compare_type;
typedef mem_manager mem_manager_type;
map(
);
/*!
ensures
- #*this is properly initialized
throws
- std::bad_alloc or any exception thrown by domain's or range's
constructor.
!*/
virtual ~map(
);
/*!
ensures
- all memory associated with *this has been released
!*/
void clear(
);
/*!
ensures
- #*this has its initial value
throws
- std::bad_alloc or any exception thrown by domain's or range's
constructor.
if this exception is thrown then *this is unusable
until clear() is called and succeeds
!*/
void add (
domain& d,
range& r
);
/*!
requires
- &d != &r (i.e. d and r cannot be the same variable)
- is_in_domain(d) == false
ensures
- #is_in_domain(d) == true
- #operator[](d) == r
- #d and #r have initial values for their types
- #size() == size() + 1
- #at_start() == true
throws
- std::bad_alloc or any exception thrown by domain's or range's
constructor.
if add() throws then it has no effect
!*/
bool is_in_domain (
const domain& d
) const;
/*!
ensures
- returns whether or not an element equivalent to d is in the
domain of *this
!*/
void remove (
const domain& d,
domain& d_copy,
range& r
);
/*!
requires
- &d != &r (i.e. d and r cannot be the same variable)
- &d != &d_copy (i.e. d and d_copy cannot be the same variable)
- &r != &d_copy (i.e. r and d_copy cannot be the same variable)
- is_in_domain(d) == true
ensures
- #is_in_domain(d) == false
- #d_copy is equivalent to d
- the element in the range of *this associated with #d_copy has been
swapped into #r
- #size() == size() - 1
- #at_start() == true
!*/
void destroy (
const domain& d
);
/*!
requires
- is_in_domain(d) == true
ensures
- #is_in_domain(d) == false
- #size() == size() - 1
- #at_start() == true
!*/
range& operator[] (
const domain& d
);
/*!
requires
- is_in_domain(d) == true
ensures
- returns a non-const reference to the element in the range of *this
associated with the element equivalent to d
!*/
const range& operator[] (
const domain& d
) const;
/*!
requires
- is_in_domain(d) == true
ensures
- returns a const reference to the element in the range of *this
associated with the element equivalent to d
!*/
void swap (
map& item
);
/*!
ensures
- swaps *this and item
!*/
private:
// restricted functions
map(map&); // copy constructor
map& operator=(map&); // assignment operator
};
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
inline void swap (
map<domain,range,mem_manager,compare>& a,
map<domain,range,mem_manager,compare>& b
) { a.swap(b); }
/*!
provides a global swap function
!*/
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void deserialize (
map<domain,range,mem_manager,compare>& item,
std::istream& in
);
/*!
provides deserialization support
!*/
}
#endif // DLIB_MAP_KERNEl_ABSTRACT_

View File

@@ -0,0 +1,248 @@
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_MAP_KERNEl_C_
#define DLIB_MAP_KERNEl_C_
#include "map_kernel_abstract.h"
#include "../algs.h"
#include "../assert.h"
#include "../interfaces/map_pair.h"
namespace dlib
{
template <
typename map_base
>
class map_kernel_c : public map_base
{
typedef typename map_base::domain_type domain;
typedef typename map_base::range_type range;
public:
void add (
domain& d,
range& r
);
void remove_any (
domain& d,
range& r
);
void remove (
const domain& d,
domain& d_copy,
range& r
);
void destroy (
const domain& d
);
range& operator[] (
const domain& d
);
const range& operator[] (
const domain& d
) const;
const map_pair<domain,range>& element (
) const
{
// make sure requires clause is not broken
DLIB_CASSERT(this->current_element_valid() == true,
"\tconst map_pair<domain,range>& map::element"
<< "\n\tyou can't access the current element if it doesn't exist"
<< "\n\tthis: " << this
);
// call the real function
return map_base::element();
}
map_pair<domain,range>& element (
)
{
// make sure requires clause is not broken
DLIB_CASSERT(this->current_element_valid() == true,
"\tmap_pair<domain,range>& map::element"
<< "\n\tyou can't access the current element if it doesn't exist"
<< "\n\tthis: " << this
);
// call the real function
return map_base::element();
}
};
template <
typename map_base
>
inline void swap (
map_kernel_c<map_base>& a,
map_kernel_c<map_base>& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename map_base
>
void map_kernel_c<map_base>::
add (
domain& d,
range& r
)
{
// make sure requires clause is not broken
DLIB_CASSERT( (!this->is_in_domain(d)) &&
(static_cast<void*>(&d) != static_cast<void*>(&r)),
"\tvoid map::add"
<< "\n\tdomain element being added must not already be in the map"
<< "\n\tand d and r must not be the same variable"
<< "\n\tis_in_domain(d): " << (this->is_in_domain(d) ? "true" : "false")
<< "\n\tthis: " << this
<< "\n\t&d: " << static_cast<void*>(&d)
<< "\n\t&r: " << static_cast<void*>(&r)
);
// call the real function
map_base::add(d,r);
}
// ----------------------------------------------------------------------------------------
template <
typename map_base
>
void map_kernel_c<map_base>::
remove_any (
domain& d,
range& r
)
{
// make sure requires clause is not broken
DLIB_CASSERT( (this->size() > 0) &&
(static_cast<void*>(&d) != static_cast<void*>(&r)),
"\tvoid map::remove_any"
<< "\n\tsize() must be greater than zero if something is going to be removed"
<< "\n\tand d and r must not be the same variable."
<< "\n\tsize(): " << this->size()
<< "\n\tthis: " << this
<< "\n\t&d: " << static_cast<void*>(&d)
<< "\n\t&r: " << static_cast<void*>(&r)
);
// call the real function
map_base::remove_any(d,r);
}
// ----------------------------------------------------------------------------------------
template <
typename map_base
>
void map_kernel_c<map_base>::
remove (
const domain& d,
domain& d_copy,
range& r
)
{
// make sure requires clause is not broken
DLIB_CASSERT( (this->is_in_domain(d)) &&
(static_cast<const void*>(&d) != static_cast<void*>(&r)) &&
(static_cast<void*>(&r) != static_cast<void*>(&d_copy)) &&
(static_cast<const void*>(&d) != static_cast<void*>(&d_copy)),
"\tvoid map::remove"
<< "\n\tcan't remove something that isn't in the map or if the paremeters actually"
<< "\n\tare the same variable. Either way can't remove."
<< "\n\tis_in_domain(d): " << (this->is_in_domain(d) ? "true" : "false")
<< "\n\tthis: " << this
<< "\n\t&d: " << static_cast<const void*>(&d)
<< "\n\t&r: " << static_cast<void*>(&r)
<< "\n\t&d_copy: " << static_cast<void*>(&d_copy)
);
// call the real function
map_base::remove(d,d_copy,r);
}
// ----------------------------------------------------------------------------------------
template <
typename map_base
>
void map_kernel_c<map_base>::
destroy (
const domain& d
)
{
// make sure requires clause is not broken
DLIB_CASSERT(this->is_in_domain(d),
"\tvoid map::destroy"
<< "\n\tcan't remove something that isn't in the map"
<< "\n\tthis: " << this
<< "\n\t&d: " << static_cast<const void*>(&d)
);
// call the real function
map_base::destroy(d);
}
// ----------------------------------------------------------------------------------------
template <
typename map_base
>
typename map_base::range_type& map_kernel_c<map_base>::
operator[] (
const domain& d
)
{
// make sure requires clause is not broken
DLIB_CASSERT( this->is_in_domain(d),
"\trange& map::operator[]"
<< "\n\td must be in the domain of the map"
<< "\n\tthis: " << this
);
// call the real function
return map_base::operator[](d);
}
// ----------------------------------------------------------------------------------------
template <
typename map_base
>
const typename map_base::range_type& map_kernel_c<map_base>::
operator[] (
const domain& d
) const
{
// make sure requires clause is not broken
DLIB_CASSERT( this->is_in_domain(d),
"\tconst range& map::operator[]"
<< "\n\td must be in the domain of the map"
<< "\n\tthis: " << this
);
// call the real function
return map_base::operator[](d);
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_MAP_KERNEl_C_

View File

@@ -0,0 +1,10 @@
// Copyright (C) 2005 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_MEMBER_FUNCTION_POINTEr_
#define DLIB_MEMBER_FUNCTION_POINTEr_
#include "member_function_pointer/member_function_pointer_kernel_1.h"
#include "member_function_pointer/make_mfp.h"
#endif // DLIB_MEMBER_FUNCTION_POINTEr_

View File

@@ -0,0 +1,179 @@
// Copyright (C) 2011 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_MAKE_MFp_H_
#define DLIB_MAKE_MFp_H_
#include "member_function_pointer_kernel_1.h"
#include "make_mfp_abstract.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
template <
typename T
>
member_function_pointer<> make_mfp (
T& object,
void (T::*cb)()
)
{
member_function_pointer<> temp;
temp.set(object, cb);
return temp;
}
template <
typename T
>
member_function_pointer<> make_mfp (
const T& object,
void (T::*cb)()const
)
{
member_function_pointer<> temp;
temp.set(object, cb);
return temp;
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename A1
>
member_function_pointer<A1> make_mfp (
T& object,
void (T::*cb)(A1)
)
{
member_function_pointer<A1> temp;
temp.set(object, cb);
return temp;
}
template <
typename T,
typename A1
>
member_function_pointer<A1> make_mfp (
const T& object,
void (T::*cb)(A1)const
)
{
member_function_pointer<A1> temp;
temp.set(object, cb);
return temp;
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename A1,
typename A2
>
member_function_pointer<A1,A2> make_mfp (
T& object,
void (T::*cb)(A1,A2)
)
{
member_function_pointer<A1,A2> temp;
temp.set(object, cb);
return temp;
}
template <
typename T,
typename A1,
typename A2
>
member_function_pointer<A1,A2> make_mfp (
const T& object,
void (T::*cb)(A1,A2)const
)
{
member_function_pointer<A1,A2> temp;
temp.set(object, cb);
return temp;
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename A1,
typename A2,
typename A3
>
member_function_pointer<A1,A2,A3> make_mfp (
T& object,
void (T::*cb)(A1,A2,A3)
)
{
member_function_pointer<A1,A2,A3> temp;
temp.set(object, cb);
return temp;
}
template <
typename T,
typename A1,
typename A2,
typename A3
>
member_function_pointer<A1,A2,A3> make_mfp (
const T& object,
void (T::*cb)(A1,A2,A3)const
)
{
member_function_pointer<A1,A2,A3> temp;
temp.set(object, cb);
return temp;
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename A1,
typename A2,
typename A3,
typename A4
>
member_function_pointer<A1,A2,A3,A4> make_mfp (
T& object,
void (T::*cb)(A1,A2,A3,A4)
)
{
member_function_pointer<A1,A2,A3,A4> temp;
temp.set(object, cb);
return temp;
}
template <
typename T,
typename A1,
typename A2,
typename A3,
typename A4
>
member_function_pointer<A1,A2,A3,A4> make_mfp (
const T& object,
void (T::*cb)(A1,A2,A3,A4)const
)
{
member_function_pointer<A1,A2,A3,A4> temp;
temp.set(object, cb);
return temp;
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_MAKE_MFp_H_

View File

@@ -0,0 +1,207 @@
// Copyright (C) 2011 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_MAKE_MFp_ABSTRACT_
#ifdef DLIB_MAKE_MFp_ABSTRACT_
#include "member_function_pointer_kernel_abstract.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
template <
typename T
>
member_function_pointer<> make_mfp (
T& object,
void (T::*cb)()
);
/*!
requires
- cb == a valid member function pointer for class T
ensures
- returns a member function pointer object MFP such that:
- MFP.is_set() == true
- calls to MFP() will call (object.*cb)()
!*/
template <
typename T
>
member_function_pointer<> make_mfp (
const T& object,
void (T::*cb)()const
);
/*!
requires
- cb == a valid member function pointer for class T
ensures
- returns a member function pointer object MFP such that:
- MFP.is_set() == true
- calls to MFP() will call (object.*cb)()
!*/
// ----------------------------------------------------------------------------------------
template <
typename T,
typename A1
>
member_function_pointer<A1> make_mfp (
T& object,
void (T::*cb)(A1 a1)
);
/*!
requires
- cb == a valid member function pointer for class T
ensures
- returns a member function pointer object MFP such that:
- MFP.is_set() == true
- calls to MFP(a1) will call (object.*cb)(a1)
!*/
template <
typename T,
typename A1
>
member_function_pointer<A1> make_mfp (
const T& object,
void (T::*cb)(A1 a1)const
);
/*!
requires
- cb == a valid member function pointer for class T
ensures
- returns a member function pointer object MFP such that:
- MFP.is_set() == true
- calls to MFP(a1) will call (object.*cb)(a1)
!*/
// ----------------------------------------------------------------------------------------
template <
typename T,
typename A1,
typename A2
>
member_function_pointer<A1,A2> make_mfp (
T& object,
void (T::*cb)(A1 a1, A2 a2)
);
/*!
requires
- cb == a valid member function pointer for class T
ensures
- returns a member function pointer object MFP such that:
- MFP.is_set() == true
- calls to MFP(a1,a2) will call (object.*cb)(a1,a2)
!*/
template <
typename T,
typename A1,
typename A2
>
member_function_pointer<A1,A2> make_mfp (
const T& object,
void (T::*cb)(A1 a1, A2 a2)const
);
/*!
requires
- cb == a valid member function pointer for class T
ensures
- returns a member function pointer object MFP such that:
- MFP.is_set() == true
- calls to MFP(a1,a2) will call (object.*cb)(a1,a2)
!*/
// ----------------------------------------------------------------------------------------
template <
typename T,
typename A1,
typename A2,
typename A3
>
member_function_pointer<A1,A2,A3> make_mfp (
T& object,
void (T::*cb)(A1 a1, A2 a2, A3 a3)
);
/*!
requires
- cb == a valid member function pointer for class T
ensures
- returns a member function pointer object MFP such that:
- MFP.is_set() == true
- calls to MFP(a1,a2,a3) will call (object.*cb)(a1,a2,a3)
!*/
template <
typename T,
typename A1,
typename A2,
typename A3
>
member_function_pointer<A1,A2,A3> make_mfp (
const T& object,
void (T::*cb)(A1 a1, A2 a2, A3 a3)const
);
/*!
requires
- cb == a valid member function pointer for class T
ensures
- returns a member function pointer object MFP such that:
- MFP.is_set() == true
- calls to MFP(a1,a2,a3) will call (object.*cb)(a1,a2,a3)
!*/
// ----------------------------------------------------------------------------------------
template <
typename T,
typename A1,
typename A2,
typename A3,
typename A4
>
member_function_pointer<A1,A2,A3,A4> make_mfp (
T& object,
void (T::*cb)(A1 a1, A2 a2, A3 a3, A4 a4)
);
/*!
requires
- cb == a valid member function pointer for class T
ensures
- returns a member function pointer object MFP such that:
- MFP.is_set() == true
- calls to MFP(a1,a2,a3,a4) will call (object.*cb)(a1,a2,a3,a4)
!*/
template <
typename T,
typename A1,
typename A2,
typename A3,
typename A4
>
member_function_pointer<A1,A2,A3,A4> make_mfp (
const T& object,
void (T::*cb)(A1 a1, A2 a2, A3 a3, A4 a4)const
);
/*!
requires
- cb == a valid member function pointer for class T
ensures
- returns a member function pointer object MFP such that:
- MFP.is_set() == true
- calls to MFP(a1,a2,a3,a4) will call (object.*cb)(a1,a2,a3,a4)
!*/
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_MAKE_MFp_ABSTRACT_

View File

@@ -0,0 +1,509 @@
// Copyright (C) 2005 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_MEMBER_FUNCTION_POINTER_KERNEl_1_
#define DLIB_MEMBER_FUNCTION_POINTER_KERNEl_1_
#include "../algs.h"
#include "member_function_pointer_kernel_abstract.h"
#include "../enable_if.h"
#include <new>
namespace dlib
{
// ----------------------------------------------------------------------------------------
template <
typename PARAM1 = void,
typename PARAM2 = void,
typename PARAM3 = void,
typename PARAM4 = void
>
class member_function_pointer;
// ----------------------------------------------------------------------------------------
#define DLIB_MFP_SC DLIB_ASSERT(cb != 0, \
"\tvoid member_function_pointer::set" \
<< "\n\tthe member function pointer can't be null" \
<< "\n\tthis: " << this );
#define DLIB_MFP_OC DLIB_ASSERT(this->is_set() == true , \
"\tvoid member_function_pointer::operator()" \
<< "\n\tYou must call set() before you can use this function" \
<< "\n\tthis: " << this);
// ----------------------------------------------------------------------------------------
template <unsigned long num_args>
class mfp_kernel_1_base_class
{
/*
All member function pointer classes inherit from this class. This
is where most of the things in a member function pointer are defined.
The reason for the num_args template argument to this class is to prevent
any sort of implicit casting between derived member function pointer classes
that take different numbers of arguments.
*/
protected:
enum mfp_type { mfp_nonconst, mfp_const, mfp_null};
class mp_base_base
{
public:
mp_base_base(void* ptr, mfp_type type_) : o(ptr),type(type_) {}
virtual ~mp_base_base(){}
virtual void clone(void* ptr) const = 0;
virtual bool is_same (const mp_base_base* item) const = 0;
bool is_set () const { return o!=0; }
void* const o;
const mfp_type type;
};
template <typename T>
class mp_null : public mp_base_base
{
public:
typedef void (T::*mfp_pointer_type)() ;
mp_null (void* , mfp_pointer_type ) : mp_base_base(0,mfp_null), callback(0) {}
mp_null () : mp_base_base(0,mfp_null), callback(0) {}
const mfp_pointer_type callback;
};
template <typename mp_impl>
class mp_impl_T : public mp_impl
{
/*
This class supplies the implementations clone() and is_same() for any
classes that inherit from mp_base_base. It does this in a very
roundabout way...
*/
public:
typedef typename mp_impl::mfp_pointer_type mfp_pointer_type;
mp_impl_T() : mp_impl(0,0) {}
mp_impl_T(void* ptr, mfp_pointer_type cb) : mp_impl(ptr,cb) {}
template <unsigned long mem_size>
void safe_clone(stack_based_memory_block<mem_size>& buf)
{
// This is here just to validate the assumption that our block of memory we have made
// in mp_memory is the right size to store the data for this object. If you
// get a compiler error on this line then email me :)
COMPILE_TIME_ASSERT(sizeof(mp_impl_T) <= mem_size);
clone(buf.get());
}
void clone (void* ptr) const { new(ptr) mp_impl_T(this->o,this->callback); }
bool is_same (const mp_base_base* item) const
{
if (item->o == 0 && this->o == 0)
{
return true;
}
else if (item->o == this->o && this->type == item->type)
{
const mp_impl* i = reinterpret_cast<const mp_impl*>(item);
return (i->callback == this->callback);
}
return false;
}
};
// MSVC with the /vms option, we get C2287 since the dummy class requires virtual
// inheritance. Adding the __virtual_inheritance specifier explicitly fixes the issue,
// but then Clang-CL no longer accepts it.
#if defined(_MSC_VER) && !defined(__clang__)
#define DLIB_MSVC_INHERITANCE_VIRTUAL __virtual_inheritance
#else
#define DLIB_MSVC_INHERITANCE_VIRTUAL
#endif
struct dummy_base { virtual void nonnull() {}; virtual ~dummy_base(){}; int a; };
struct DLIB_MSVC_INHERITANCE_VIRTUAL dummy : virtual public dummy_base{ void nonnull() {}; };
#undef DLIB_MSVC_INHERITANCE_VIRTUAL
typedef mp_impl_T<mp_null<dummy> > mp_null_impl;
public:
mfp_kernel_1_base_class (
const mfp_kernel_1_base_class& item
) { item.mp()->clone(mp_memory.get()); }
mfp_kernel_1_base_class (
) { mp_null_impl().safe_clone(mp_memory); }
bool operator == (
const mfp_kernel_1_base_class& item
) const { return mp()->is_same(item.mp()); }
bool operator != (
const mfp_kernel_1_base_class& item
) const { return !(*this == item); }
mfp_kernel_1_base_class& operator= (
const mfp_kernel_1_base_class& item
) { mfp_kernel_1_base_class(item).swap(*this); return *this; }
~mfp_kernel_1_base_class (
) { destroy_mp_memory(); }
void clear(
) { mfp_kernel_1_base_class().swap(*this); }
bool is_set (
) const { return mp()->is_set(); }
private:
typedef void (dummy::*safe_bool)();
public:
operator safe_bool () const { return is_set() ? &dummy::nonnull : 0; }
bool operator!() const { return !is_set(); }
void swap (
mfp_kernel_1_base_class& item
)
{
// make a temp copy of item
mfp_kernel_1_base_class temp(item);
// destory the stuff in item
item.destroy_mp_memory();
// copy *this into item
mp()->clone(item.mp_memory.get());
// destory the stuff in this
destroy_mp_memory();
// copy temp into *this
temp.mp()->clone(mp_memory.get());
}
protected:
// The reason for adding 1 here is because visual studio 2003 will sometimes
// try to compile this code with sizeof(mp_null_impl) == 0 (which is a bug in visual studio).
// Fortunately, no actual real instances of this template seem to end up with that screwed up
// value so everything works fine if we just add 1 so that this degenerate case doesn't cause
// trouble. Note that we know it all works fine because safe_clone() checks the size of this
// memory block whenever the member function pointer is used.
stack_based_memory_block<sizeof(mp_null_impl)+1> mp_memory;
void destroy_mp_memory (
)
{
// Honestly this probably doesn't even do anything but I'm putting
// it here just for good measure.
mp()->~mp_base_base();
}
mp_base_base* mp () { return static_cast<mp_base_base*>(mp_memory.get()); }
const mp_base_base* mp () const { return static_cast<const mp_base_base*>(mp_memory.get()); }
};
// ----------------------------------------------------------------------------------------
template <>
class member_function_pointer<void,void,void,void> : public mfp_kernel_1_base_class<0>
{
class mp_base : public mp_base_base {
public:
mp_base(void* ptr, mfp_type type_) : mp_base_base(ptr,type_) {}
virtual void call() const = 0;
};
template <typename T>
class mp_impl : public mp_base {
public:
typedef void (T::*mfp_pointer_type)() ;
void call () const { (static_cast<T*>(this->o)->*callback)(); }
mp_impl ( void* object, mfp_pointer_type cb) : mp_base(object, mfp_nonconst), callback(cb) {}
const mfp_pointer_type callback;
};
template <typename T>
class mp_impl_const : public mp_base {
public:
typedef void ((T::*mfp_pointer_type)()const);
void call () const { (static_cast<const T*>(this->o)->*callback)(); }
mp_impl_const ( void* object, mfp_pointer_type cb) : mp_base(object,mfp_const), callback(cb) {}
const mfp_pointer_type callback;
};
public:
typedef void param1_type;
typedef void param2_type;
typedef void param3_type;
typedef void param4_type;
// These two typedefs are here for backwards compatibility with previous versions
// of dlib.
typedef member_function_pointer kernel_1a;
typedef member_function_pointer kernel_1a_c;
void operator() () const { DLIB_MFP_OC; static_cast<const mp_base*>(mp_memory.get())->call(); }
// the reason for putting disable_if on this function is that it avoids an overload
// resolution bug in visual studio.
template <typename T> typename disable_if<is_const_type<T>,void>::type
set(T& object, typename mp_impl<T>::mfp_pointer_type cb)
{ DLIB_MFP_SC; destroy_mp_memory(); mp_impl_T<mp_impl<T> >(&object,cb).safe_clone(mp_memory); }
template <typename T> void set(const T& object, typename mp_impl_const<T>::mfp_pointer_type cb)
{ DLIB_MFP_SC; destroy_mp_memory(); mp_impl_T<mp_impl_const<T> >((void*)&object,cb).safe_clone(mp_memory); }
};
// ----------------------------------------------------------------------------------------
template <
typename PARAM1
>
class member_function_pointer<PARAM1,void,void,void> : public mfp_kernel_1_base_class<1>
{
class mp_base : public mp_base_base {
public:
mp_base(void* ptr, mfp_type type_) : mp_base_base(ptr,type_) {}
virtual void call(PARAM1) const = 0;
};
template <typename T>
class mp_impl : public mp_base {
public:
typedef void (T::*mfp_pointer_type)(PARAM1) ;
void call (PARAM1 p1) const { (static_cast<T*>(this->o)->*callback)(p1); }
mp_impl ( void* object, mfp_pointer_type cb) : mp_base(object, mfp_nonconst), callback(cb) {}
const mfp_pointer_type callback;
};
template <typename T>
class mp_impl_const : public mp_base {
public:
typedef void ((T::*mfp_pointer_type)(PARAM1)const);
void call (PARAM1 p1) const { (static_cast<const T*>(this->o)->*callback)(p1); }
mp_impl_const ( void* object, mfp_pointer_type cb) : mp_base(object,mfp_const), callback(cb) {}
const mfp_pointer_type callback;
};
public:
typedef PARAM1 param1_type;
typedef void param2_type;
typedef void param3_type;
typedef void param4_type;
// These two typedefs are here for backwards compatibility with previous versions
// of dlib.
typedef member_function_pointer kernel_1a;
typedef member_function_pointer kernel_1a_c;
void operator() (PARAM1 p1) const { DLIB_MFP_OC; static_cast<const mp_base*>(mp_memory.get())->call(p1); }
// the reason for putting disable_if on this function is that it avoids an overload
// resolution bug in visual studio.
template <typename T> typename disable_if<is_const_type<T>,void>::type
set(T& object, typename mp_impl<T>::mfp_pointer_type cb)
{ DLIB_MFP_SC; destroy_mp_memory(); mp_impl_T<mp_impl<T> >(&object,cb).safe_clone(mp_memory); }
template <typename T> void set(const T& object, typename mp_impl_const<T>::mfp_pointer_type cb)
{ DLIB_MFP_SC; destroy_mp_memory(); mp_impl_T<mp_impl_const<T> >((void*)&object,cb).safe_clone(mp_memory); }
};
// ----------------------------------------------------------------------------------------
template <
typename PARAM1,
typename PARAM2
>
class member_function_pointer<PARAM1,PARAM2,void,void> : public mfp_kernel_1_base_class<2>
{
class mp_base : public mp_base_base {
public:
mp_base(void* ptr, mfp_type type_) : mp_base_base(ptr,type_) {}
virtual void call(PARAM1,PARAM2) const = 0;
};
template <typename T>
class mp_impl : public mp_base {
public:
typedef void (T::*mfp_pointer_type)(PARAM1,PARAM2) ;
void call (PARAM1 p1, PARAM2 p2) const { (static_cast<T*>(this->o)->*callback)(p1,p2); }
mp_impl ( void* object, mfp_pointer_type cb) : mp_base(object, mfp_nonconst), callback(cb) {}
const mfp_pointer_type callback;
};
template <typename T>
class mp_impl_const : public mp_base {
public:
typedef void ((T::*mfp_pointer_type)(PARAM1,PARAM2)const);
void call (PARAM1 p1, PARAM2 p2) const { (static_cast<const T*>(this->o)->*callback)(p1,p2); }
mp_impl_const ( void* object, mfp_pointer_type cb) : mp_base(object,mfp_const), callback(cb) {}
const mfp_pointer_type callback;
};
public:
typedef PARAM1 param1_type;
typedef PARAM2 param2_type;
typedef void param3_type;
typedef void param4_type;
// These two typedefs are here for backwards compatibility with previous versions
// of dlib.
typedef member_function_pointer kernel_1a;
typedef member_function_pointer kernel_1a_c;
void operator() (PARAM1 p1, PARAM2 p2) const { DLIB_MFP_OC; static_cast<const mp_base*>(mp_memory.get())->call(p1,p2); }
// the reason for putting disable_if on this function is that it avoids an overload
// resolution bug in visual studio.
template <typename T> typename disable_if<is_const_type<T>,void>::type
set(T& object, typename mp_impl<T>::mfp_pointer_type cb)
{ DLIB_MFP_SC; destroy_mp_memory(); mp_impl_T<mp_impl<T> >(&object,cb).safe_clone(mp_memory); }
template <typename T> void set(const T& object, typename mp_impl_const<T>::mfp_pointer_type cb)
{ DLIB_MFP_SC; destroy_mp_memory(); mp_impl_T<mp_impl_const<T> >((void*)&object,cb).safe_clone(mp_memory); }
};
// ----------------------------------------------------------------------------------------
template <
typename PARAM1,
typename PARAM2,
typename PARAM3
>
class member_function_pointer<PARAM1,PARAM2,PARAM3,void> : public mfp_kernel_1_base_class<3>
{
class mp_base : public mp_base_base {
public:
mp_base(void* ptr, mfp_type type_) : mp_base_base(ptr,type_) {}
virtual void call(PARAM1,PARAM2,PARAM3) const = 0;
};
template <typename T>
class mp_impl : public mp_base {
public:
typedef void (T::*mfp_pointer_type)(PARAM1,PARAM2,PARAM3) ;
void call (PARAM1 p1, PARAM2 p2, PARAM3 p3) const { (static_cast<T*>(this->o)->*callback)(p1,p2,p3); }
mp_impl ( void* object, mfp_pointer_type cb) : mp_base(object, mfp_nonconst), callback(cb) {}
const mfp_pointer_type callback;
};
template <typename T>
class mp_impl_const : public mp_base {
public:
typedef void ((T::*mfp_pointer_type)(PARAM1,PARAM2,PARAM3)const);
void call (PARAM1 p1, PARAM2 p2, PARAM3 p3) const { (static_cast<const T*>(this->o)->*callback)(p1,p2,p3); }
mp_impl_const ( void* object, mfp_pointer_type cb) : mp_base(object,mfp_const), callback(cb) {}
const mfp_pointer_type callback;
};
public:
typedef PARAM1 param1_type;
typedef PARAM2 param2_type;
typedef PARAM3 param3_type;
typedef void param4_type;
// These two typedefs are here for backwards compatibility with previous versions
// of dlib.
typedef member_function_pointer kernel_1a;
typedef member_function_pointer kernel_1a_c;
void operator() (PARAM1 p1, PARAM2 p2, PARAM3 p3) const { DLIB_MFP_OC; static_cast<const mp_base*>(mp_memory.get())->call(p1,p2,p3); }
// the reason for putting disable_if on this function is that it avoids an overload
// resolution bug in visual studio.
template <typename T> typename disable_if<is_const_type<T>,void>::type
set(T& object, typename mp_impl<T>::mfp_pointer_type cb)
{ DLIB_MFP_SC; destroy_mp_memory(); mp_impl_T<mp_impl<T> >(&object,cb).safe_clone(mp_memory); }
template <typename T> void set(const T& object, typename mp_impl_const<T>::mfp_pointer_type cb)
{ DLIB_MFP_SC; destroy_mp_memory(); mp_impl_T<mp_impl_const<T> >((void*)&object,cb).safe_clone(mp_memory); }
};
// ----------------------------------------------------------------------------------------
template <
typename PARAM1,
typename PARAM2,
typename PARAM3,
typename PARAM4
>
class member_function_pointer : public mfp_kernel_1_base_class<4>
{
class mp_base : public mp_base_base {
public:
mp_base(void* ptr, mfp_type type_) : mp_base_base(ptr,type_) {}
virtual void call(PARAM1,PARAM2,PARAM3,PARAM4) const = 0;
};
template <typename T>
class mp_impl : public mp_base {
public:
typedef void (T::*mfp_pointer_type)(PARAM1,PARAM2,PARAM3, PARAM4) ;
void call (PARAM1 p1, PARAM2 p2, PARAM3 p3, PARAM4 p4) const { (static_cast<T*>(this->o)->*callback)(p1,p2,p3,p4); }
mp_impl ( void* object, mfp_pointer_type cb) : mp_base(object, mfp_nonconst), callback(cb) {}
const mfp_pointer_type callback;
};
template <typename T>
class mp_impl_const : public mp_base {
public:
typedef void ((T::*mfp_pointer_type)(PARAM1,PARAM2,PARAM3,PARAM4)const);
void call (PARAM1 p1, PARAM2 p2, PARAM3 p3, PARAM4 p4) const { (static_cast<const T*>(this->o)->*callback)(p1,p2,p3,p4); }
mp_impl_const ( void* object, mfp_pointer_type cb) : mp_base(object,mfp_const), callback(cb) {}
const mfp_pointer_type callback;
};
public:
typedef PARAM1 param1_type;
typedef PARAM2 param2_type;
typedef PARAM3 param3_type;
typedef PARAM4 param4_type;
// These two typedefs are here for backwards compatibility with previous versions
// of dlib.
typedef member_function_pointer kernel_1a;
typedef member_function_pointer kernel_1a_c;
void operator() (PARAM1 p1, PARAM2 p2, PARAM3 p3, PARAM4 p4) const
{ DLIB_MFP_OC; static_cast<const mp_base*>(mp_memory.get())->call(p1,p2,p3,p4); }
// the reason for putting disable_if on this function is that it avoids an overload
// resolution bug in visual studio.
template <typename T> typename disable_if<is_const_type<T>,void>::type
set(T& object, typename mp_impl<T>::mfp_pointer_type cb)
{ DLIB_MFP_SC; destroy_mp_memory(); mp_impl_T<mp_impl<T> >(&object,cb).safe_clone(mp_memory); }
template <typename T> void set(const T& object, typename mp_impl_const<T>::mfp_pointer_type cb)
{ DLIB_MFP_SC; destroy_mp_memory(); mp_impl_T<mp_impl_const<T> >((void*)&object,cb).safe_clone(mp_memory); }
};
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_MEMBER_FUNCTION_POINTER_KERNEl_1_

View File

@@ -0,0 +1,483 @@
// Copyright (C) 2005 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_MEMBER_FUNCTION_POINTER_KERNEl_ABSTRACT_
#ifdef DLIB_MEMBER_FUNCTION_POINTER_KERNEl_ABSTRACT_
namespace dlib
{
// ----------------------------------------------------------------------------------------
template <
typename PARAM1 = void,
typename PARAM2 = void,
typename PARAM3 = void,
typename PARAM4 = void
>
class member_function_pointer;
// ----------------------------------------------------------------------------------------
template <>
class member_function_pointer<void,void,void,void>
{
/*!
INITIAL VALUE
is_set() == false
WHAT THIS OBJECT REPRESENTS
This object represents a member function pointer. It is useful because
instances of this object can be created without needing to know the type
of object whose member function we will be calling.
There are five template specializations of this object. The first
represents a pointer to a member function taking no parameters, the
second represents a pointer to a member function taking one parameter,
the third to one taking two parameters, and so on.
You specify the parameters to your member function pointer by filling in
the PARAM template parameters. For example:
To use a pointer to a function with no parameters you would say:
member_function_pointer<> my_pointer;
To use a pointer to a function that takes a single int you would say:
member_function_pointer<int> my_pointer;
To use a pointer to a function that takes an int and then a reference
to a string you would say:
member_function_pointer<int,string&> my_pointer;
Also note that the formal comments are only present for the first
template specialization. They are all exactly the same except for the
number of parameters each takes in its member function pointer.
!*/
public:
typedef void param1_type;
typedef void param2_type;
typedef void param3_type;
typedef void param4_type;
member_function_pointer (
);
/*!
ensures
- #*this is properly initialized
!*/
member_function_pointer(
const member_function_pointer& item
);
/*!
ensures
- *this == item
!*/
~member_function_pointer (
);
/*!
ensures
- any resources associated with *this have been released
!*/
member_function_pointer& operator=(
const member_function_pointer& item
);
/*!
ensures
- *this == item
!*/
bool operator == (
const member_function_pointer& item
) const;
/*!
ensures
- if (is_set() == false && item.is_set() == false) then
- returns true
- else if (both *this and item point to the same member function
in the same object instance) then
- returns true
- else
- returns false
!*/
bool operator != (
const member_function_pointer& item
) const;
/*!
ensures
- returns !(*this == item)
!*/
void clear(
);
/*!
ensures
- #*this has its initial value
!*/
bool is_set (
) const;
/*!
ensures
- if (this->set() has been called) then
- returns true
- else
- returns false
!*/
template <
typename T
>
void set (
T& object,
void (T::*cb)()
);
/*!
requires
- cb == a valid member function pointer for class T
ensures
- #is_set() == true
- calls to this->operator() will call (object.*cb)()
!*/
template <
typename T
>
void set (
const T& object,
void (T::*cb)()const
);
/*!
requires
- cb == a valid member function pointer for class T
ensures
- #is_set() == true
- calls to this->operator() will call (object.*cb)()
!*/
operator some_undefined_pointer_type (
) const;
/*!
ensures
- if (is_set()) then
- returns a non 0 value
- else
- returns a 0 value
!*/
bool operator! (
) const;
/*!
ensures
- returns !is_set()
!*/
void operator () (
) const;
/*!
requires
- is_set() == true
ensures
- calls the member function on the object specified by the last
call to this->set()
throws
- any exception thrown by the member function specified by
the previous call to this->set().
If any of these exceptions are thrown then the call to this
function will have no effect on *this.
!*/
void swap (
member_function_pointer& item
);
/*!
ensures
- swaps *this and item
!*/
};
// ----------------------------------------------------------------------------------------
template <
typename PARAM1
>
class member_function_pointer<PARAM1,void,void,void>
{
public:
typedef PARAM1 param1_type;
typedef void param2_type;
typedef void param3_type;
typedef void param4_type;
member_function_pointer ();
member_function_pointer(
const member_function_pointer& item
);
~member_function_pointer (
);
member_function_pointer& operator=(
const member_function_pointer& item
);
bool operator == (
const member_function_pointer& item
) const;
bool operator != (
const member_function_pointer& item
) const;
void clear();
bool is_set () const;
template <typename T>
void set (
T& object,
void (T::*cb)(PARAM1)
);
template <typename T>
void set (
const T& object,
void (T::*cb)(PARAM1)const
);
operator some_undefined_pointer_type (
) const;
bool operator! (
) const;
void operator () (
PARAM1 param1
) const;
void swap (
member_function_pointer& item
);
};
// ----------------------------------------------------------------------------------------
template <
typename PARAM1,
typename PARAM2
>
class member_function_pointer<PARAM1,PARAM2,void,void>
{
public:
typedef PARAM1 param1_type;
typedef PARAM2 param2_type;
typedef void param3_type;
typedef void param4_type;
member_function_pointer ();
member_function_pointer(
const member_function_pointer& item
);
~member_function_pointer (
);
member_function_pointer& operator=(
const member_function_pointer& item
);
bool operator == (
const member_function_pointer& item
) const;
bool operator != (
const member_function_pointer& item
) const;
void clear();
bool is_set () const;
template <typename T>
void set (
T& object,
void (T::*cb)(PARAM1,PARAM2)
);
template <typename T>
void set (
const T& object,
void (T::*cb)(PARAM1,PARAM2)const
);
operator some_undefined_pointer_type (
) const;
bool operator! (
) const;
void operator () (
PARAM1 param1,
PARAM2 param2
) const;
void swap (
member_function_pointer& item
);
};
// ----------------------------------------------------------------------------------------
template <
typename PARAM1,
typename PARAM2,
typename PARAM3
>
class member_function_pointer<PARAM1,PARAM2,PARAM3,void>
{
public:
typedef PARAM1 param1_type;
typedef PARAM2 param2_type;
typedef PARAM3 param3_type;
typedef void param4_type;
member_function_pointer ();
member_function_pointer(
const member_function_pointer& item
);
~member_function_pointer (
);
member_function_pointer& operator=(
const member_function_pointer& item
);
bool operator == (
const member_function_pointer& item
) const;
bool operator != (
const member_function_pointer& item
) const;
void clear();
bool is_set () const;
template <typename T>
void set (
T& object,
void (T::*cb)(PARAM1,PARAM2,PARAM3)
);
template <typename T>
void set (
const T& object,
void (T::*cb)(PARAM1,PARAM2,PARAM3)const
);
operator some_undefined_pointer_type (
) const;
bool operator! (
) const;
void operator () (
PARAM1 param1,
PARAM2 param2,
PARAM2 param3
) const;
void swap (
member_function_pointer& item
);
};
// ----------------------------------------------------------------------------------------
template <
typename PARAM1,
typename PARAM2,
typename PARAM3,
typename PARAM4
>
class member_function_pointer
{
public:
typedef PARAM1 param1_type;
typedef PARAM2 param2_type;
typedef PARAM3 param3_type;
typedef PARAM4 param4_type;
member_function_pointer ();
member_function_pointer(
const member_function_pointer& item
);
~member_function_pointer (
);
member_function_pointer& operator=(
const member_function_pointer& item
);
bool operator == (
const member_function_pointer& item
) const;
bool operator != (
const member_function_pointer& item
) const;
void clear();
bool is_set () const;
template <typename T>
void set (
T& object,
void (T::*cb)(PARAM1,PARAM2,PARAM3,PARAM4)
);
template <typename T>
void set (
const T& object,
void (T::*cb)(PARAM1,PARAM2,PARAM3,PARAM4)const
);
operator some_undefined_pointer_type (
) const;
bool operator! (
) const;
void operator () (
PARAM1 param1,
PARAM2 param2,
PARAM2 param3,
PARAM2 param4
) const;
void swap (
member_function_pointer& item
);
};
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_MEMBER_FUNCTION_POINTER_KERNEl_ABSTRACT_

View File

@@ -0,0 +1,73 @@
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_MEMORY_MANAGEr_
#define DLIB_MEMORY_MANAGEr_
#include "memory_manager/memory_manager_kernel_1.h"
#include "memory_manager/memory_manager_kernel_2.h"
#include "memory_manager/memory_manager_kernel_3.h"
namespace dlib
{
template <
typename T
>
class memory_manager
{
memory_manager() {}
public:
//----------- kernels ---------------
// kernel_1
typedef memory_manager_kernel_1<T,0>
kernel_1a;
typedef memory_manager_kernel_1<T,10>
kernel_1b;
typedef memory_manager_kernel_1<T,100>
kernel_1c;
typedef memory_manager_kernel_1<T,1000>
kernel_1d;
typedef memory_manager_kernel_1<T,10000>
kernel_1e;
typedef memory_manager_kernel_1<T,100000>
kernel_1f;
// kernel_2
typedef memory_manager_kernel_2<T,10>
kernel_2a;
typedef memory_manager_kernel_2<T,100>
kernel_2b;
typedef memory_manager_kernel_2<T,1000>
kernel_2c;
typedef memory_manager_kernel_2<T,10000>
kernel_2d;
typedef memory_manager_kernel_2<T,100000>
kernel_2e;
// kernel_3
typedef memory_manager_kernel_3<T,10>
kernel_3a;
typedef memory_manager_kernel_3<T,100>
kernel_3b;
typedef memory_manager_kernel_3<T,1000>
kernel_3c;
typedef memory_manager_kernel_3<T,10000>
kernel_3d;
typedef memory_manager_kernel_3<T,100000>
kernel_3e;
};
}
#endif // DLIB_MEMORY_MANAGEr_

View File

@@ -0,0 +1,305 @@
// Copyright (C) 2004 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_MEMORY_MANAGER_KERNEl_1_
#define DLIB_MEMORY_MANAGER_KERNEl_1_
#include "../algs.h"
#include "memory_manager_kernel_abstract.h"
#include "../assert.h"
#include <new>
namespace dlib
{
template <
typename T,
size_t max_pool_size
>
class memory_manager_kernel_1
{
/*!
INITIAL VALUE
allocations == 0
next == 0
pool_size == 0
REQUIREMENTS ON max_pool_size
max_pool_size is the maximum number of nodes we will keep in our linked list at once.
So you can put any value in for this argument.
CONVENTION
This memory manager implementation allocates T objects one at a time when there are
allocation requests. Then when there is a deallocate request the returning T object
is place into a list of free blocks if that list has less than max_pool_size
blocks in it. subsequent allocation requests will be serviced by drawing from the
free list whenever it isn't empty.
allocations == get_number_of_allocations()
- if (next != 0) then
- next == the next pointer to return from allocate()
and next == pointer to the first node in a linked list. each node
is one item in the memory pool.
- the last node in the linked list has next set to 0
- pool_size == the number of nodes in the linked list
- pool_size <= max_pool_size
- else
- we need to call new to get the next pointer to return from allocate()
!*/
union node
{
node* next;
char item[sizeof(T)];
};
public:
typedef T type;
template <typename U>
struct rebind {
typedef memory_manager_kernel_1<U,max_pool_size> other;
};
memory_manager_kernel_1(
) :
allocations(0),
next(0),
pool_size(0)
{
}
virtual ~memory_manager_kernel_1(
)
{
while (next != 0)
{
node* temp = next;
next = next->next;
::operator delete ( static_cast<void*>(temp));
}
}
size_t get_number_of_allocations (
) const { return allocations; }
T* allocate_array (
size_t size
)
{
T* temp = new T[size];
++allocations;
return temp;
}
void deallocate_array (
T* item
)
{
--allocations;
delete [] item;
}
T* allocate (
)
{
T* temp;
if (next != 0)
{
temp = reinterpret_cast<T*>(next);
node* n = next->next;
try
{
// construct this new T object with placement new.
new (static_cast<void*>(temp))T();
}
catch (...)
{
next->next = n;
throw;
}
next = n;
--pool_size;
}
else
{
temp = static_cast<T*>(::operator new(sizeof(node)));
try
{
// construct this new T object with placement new.
new (static_cast<void*>(temp))T();
}
catch (...)
{
// construction of the new object threw so delete the block of memory
::operator delete ( static_cast<void*>(temp));
throw;
}
}
++allocations;
return temp;
}
void deallocate (
T* item
)
{
--allocations;
item->~T();
if (pool_size >= max_pool_size)
{
::operator delete ( static_cast<void*>(item));
return;
}
// add this memory chunk into our linked list.
node* temp = reinterpret_cast<node*>(item);
temp->next = next;
next = temp;
++pool_size;
}
void swap (
memory_manager_kernel_1& item
)
{
exchange(allocations,item.allocations);
exchange(next,item.next);
exchange(pool_size,item.pool_size);
}
private:
// data members
size_t allocations;
node* next;
size_t pool_size;
// restricted functions
memory_manager_kernel_1(memory_manager_kernel_1&); // copy constructor
memory_manager_kernel_1& operator=(memory_manager_kernel_1&); // assignment operator
};
// ----------------------------------------------------------------------------------------
template <
typename T
>
class memory_manager_kernel_1<T,0>
{
/*!
INITIAL VALUE
allocations == 0
CONVENTION
This memory manager just calls new and delete directly so it doesn't
really do anything.
allocations == get_number_of_allocations()
!*/
public:
typedef T type;
template <typename U>
struct rebind {
typedef memory_manager_kernel_1<U,0> other;
};
memory_manager_kernel_1(
) :
allocations(0)
{
}
virtual ~memory_manager_kernel_1(
)
{
}
size_t get_number_of_allocations (
) const { return allocations; }
T* allocate_array (
size_t size
)
{
T* temp = new T[size];
++allocations;
return temp;
}
void deallocate_array (
T* item
)
{
--allocations;
delete [] item;
}
T* allocate (
)
{
T* temp = new T;
++allocations;
return temp;
}
void deallocate (
T* item
)
{
delete item;
--allocations;
}
void swap (
memory_manager_kernel_1& item
)
{
exchange(allocations,item.allocations);
}
private:
// data members
size_t allocations;
// restricted functions
memory_manager_kernel_1(memory_manager_kernel_1&); // copy constructor
memory_manager_kernel_1& operator=(memory_manager_kernel_1&); // assignment operator
};
// ----------------------------------------------------------------------------------------
template <
typename T,
size_t max_pool_size
>
inline void swap (
memory_manager_kernel_1<T,max_pool_size>& a,
memory_manager_kernel_1<T,max_pool_size>& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_MEMORY_MANAGER_KERNEl_1_

View File

@@ -0,0 +1,253 @@
// Copyright (C) 2004 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_MEMORY_MANAGER_KERNEl_2_
#define DLIB_MEMORY_MANAGER_KERNEl_2_
#include "../algs.h"
#include "memory_manager_kernel_abstract.h"
#include "../assert.h"
#include <new>
namespace dlib
{
template <
typename T,
size_t chunk_size
>
class memory_manager_kernel_2
{
/*!
INITIAL VALUE
allocations == 0
next == 0
first_chunk == 0
REQUIREMENTS ON chunk_size
chunk_size is the number of items of type T we will allocate at a time. so
it must be > 0.
CONVENTION
This memory manager implementation allocates memory in blocks of chunk_size*sizeof(T)
bytes. All the sizeof(T) subblocks are kept in a linked list of free memory blocks
and are given out whenever an allocation request occurs. Also, memory is not freed
until this object is destructed.
Note that array allocations are not memory managed.
allocations == get_number_of_allocations()
- if (next != 0) then
- next == the next pointer to return from allocate()
and next == pointer to the first node in a linked list. each node
is one item in the memory pool.
- the last node in the linked list has next set to 0
- else
- we need to call new to get the next pointer to return from allocate()
- if (first_chunk != 0) then
- first_chunk == the first node in a linked list that contains pointers
to all the chunks we have ever allocated. The last link in the list
has its next pointer set to 0.
!*/
union node
{
node* next;
char item[sizeof(T)];
};
struct chunk_node
{
node* chunk;
chunk_node* next;
};
public:
typedef T type;
template <typename U>
struct rebind {
typedef memory_manager_kernel_2<U,chunk_size> other;
};
memory_manager_kernel_2(
) :
allocations(0),
next(0),
first_chunk(0)
{
// You FOOL! You can't have a zero chunk_size.
COMPILE_TIME_ASSERT(chunk_size > 0);
}
virtual ~memory_manager_kernel_2(
)
{
if (allocations == 0)
{
while (first_chunk != 0)
{
chunk_node* temp = first_chunk;
first_chunk = first_chunk->next;
// delete the memory chunk
::operator delete ( static_cast<void*>(temp->chunk));
// delete the chunk_node
delete temp;
}
}
}
size_t get_number_of_allocations (
) const { return allocations; }
T* allocate_array (
size_t size
)
{
T* temp = new T[size];
++allocations;
return temp;
}
void deallocate_array (
T* item
)
{
--allocations;
delete [] item;
}
T* allocate (
)
{
T* temp = 0;
if (next != 0)
{
temp = reinterpret_cast<T*>(next);
node* n = next->next;
try
{
// construct this new T object with placement new.
new (static_cast<void*>(temp))T();
}
catch (...)
{
next->next = n;
throw;
}
next = n;
}
else
{
// the linked list is empty so we need to allocate some more memory
node* block = 0;
block = static_cast<node*>(::operator new (sizeof(node)*chunk_size));
// the first part of this block can be our new object
temp = reinterpret_cast<T*>(block);
try
{
// construct this new T object with placement new.
new (static_cast<void*>(temp))T();
}
catch (...)
{
// construction of the new object threw so delete the block of memory
::operator delete ( static_cast<void*>(block));
throw;
}
// allocate a new chunk_node
chunk_node* chunk;
try {chunk = new chunk_node; }
catch (...)
{
temp->~T();
::operator delete ( static_cast<void*>(block));
throw;
}
// add this block into the chunk list
chunk->chunk = block;
chunk->next = first_chunk;
first_chunk = chunk;
++block;
// now add the rest of the block into the linked list of free nodes.
for (size_t i = 0; i < chunk_size-1; ++i)
{
block->next = next;
next = block;
++block;
}
}
++allocations;
return temp;
}
void deallocate (
T* item
)
{
--allocations;
item->~T();
// add this memory into our linked list.
node* temp = reinterpret_cast<node*>(item);
temp->next = next;
next = temp;
}
void swap (
memory_manager_kernel_2& item
)
{
exchange(allocations,item.allocations);
exchange(next,item.next);
exchange(first_chunk,item.first_chunk);
}
private:
// data members
size_t allocations;
node* next;
chunk_node* first_chunk;
// restricted functions
memory_manager_kernel_2(memory_manager_kernel_2&); // copy constructor
memory_manager_kernel_2& operator=(memory_manager_kernel_2&); // assignment operator
};
template <
typename T,
size_t chunk_size
>
inline void swap (
memory_manager_kernel_2<T,chunk_size>& a,
memory_manager_kernel_2<T,chunk_size>& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_MEMORY_MANAGER_KERNEl_2_

View File

@@ -0,0 +1,385 @@
// Copyright (C) 2004 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_MEMORY_MANAGER_KERNEl_3_
#define DLIB_MEMORY_MANAGER_KERNEl_3_
#include "../algs.h"
#include "memory_manager_kernel_abstract.h"
#include "../assert.h"
#include <new>
#include "memory_manager_kernel_2.h"
#include "../binary_search_tree/binary_search_tree_kernel_2.h"
namespace dlib
{
template <
typename T,
size_t chunk_size
>
class memory_manager_kernel_3
{
/*!
INITIAL VALUE
allocations == 0
next == 0
first_chunk == 0
bst_of_arrays == 0
REQUIREMENTS ON chunk_size
chunk_size is the number of items of type T we will allocate at a time. so
it must be > 0.
CONVENTION
This memory manager implementation allocates memory in blocks of chunk_size*sizeof(T)
bytes. All the sizeof(T) subblocks are kept in a linked list of free memory blocks
and are given out whenever an allocation request occurs. Also, memory is not freed
until this object is destructed.
allocations == get_number_of_allocations()
- if (next != 0) then
- next == the next pointer to return from allocate()
and next == pointer to the first node in a linked list. each node
is one item in the memory pool.
- the last node in the linked list has next set to 0
- else
- we need to call new to get the next pointer to return from allocate()
- if (arrays != 0) then
- someone has called allocate_array()
- (*arrays)[size] == an array of size bytes of memory
- if (first_chunk != 0) then
- first_chunk == the first node in a linked list that contains pointers
to all the chunks we have ever allocated. The last link in the list
has its next pointer set to 0.
!*/
union node
{
node* next;
char item[sizeof(T)];
};
struct chunk_node
{
node* chunk;
chunk_node* next;
};
typedef binary_search_tree_kernel_2<
size_t,
char*,
memory_manager_kernel_2<char,5>
> bst_of_arrays;
public:
typedef T type;
template <typename U>
struct rebind {
typedef memory_manager_kernel_3<U,chunk_size> other;
};
memory_manager_kernel_3(
) :
allocations(0),
next(0),
first_chunk(0),
arrays(0)
{
// You FOOL! You can't have a zero chunk_size.
COMPILE_TIME_ASSERT(chunk_size > 0);
}
virtual ~memory_manager_kernel_3(
)
{
if (allocations == 0)
{
while (first_chunk != 0)
{
chunk_node* temp = first_chunk;
first_chunk = first_chunk->next;
// delete the memory chunk
::operator delete ( static_cast<void*>(temp->chunk));
// delete the chunk_node
delete temp;
}
}
if (arrays)
{
arrays->reset();
while (arrays->move_next())
{
::operator delete (arrays->element().value());
}
delete arrays;
}
}
size_t get_number_of_allocations (
) const { return allocations; }
T* allocate_array (
size_t size
)
{
size_t block_size = sizeof(T)*size + sizeof(size_t)*2;
// make sure we have initialized the arrays object.
if (arrays == 0)
{
arrays = new bst_of_arrays;
}
char* temp;
// see if we have a suitable block of memory already.
arrays->position_enumerator(block_size);
if (arrays->current_element_valid())
{
// we have a suitable block of memory already so use that one.
arrays->remove_current_element(block_size,temp);
}
else
{
temp = static_cast<char*>(::operator new(block_size));
}
reinterpret_cast<size_t*>(temp)[0] = block_size;
reinterpret_cast<size_t*>(temp)[1] = size;
temp += sizeof(size_t)*2;
try
{
initialize_array(reinterpret_cast<T*>(temp),size);
}
catch (...)
{
// something was thrown while we were initializing the array so
// stick our memory block into arrays and rethrow the exception
temp -= sizeof(size_t)*2;
arrays->add(block_size,temp);
throw;
}
++allocations;
return reinterpret_cast<T*>(temp);
}
void deallocate_array (
T* item
)
{
char* temp = reinterpret_cast<char*>(item);
temp -= sizeof(size_t)*2;
size_t block_size = reinterpret_cast<size_t*>(temp)[0];
size_t size = reinterpret_cast<size_t*>(temp)[1];
deinitialize_array(item,size);
arrays->add(block_size,temp);
--allocations;
}
T* allocate (
)
{
T* temp;
if (next != 0)
{
temp = reinterpret_cast<T*>(next);
node* n = next->next;
try
{
// construct this new T object with placement new.
new (static_cast<void*>(temp))T();
}
catch (...)
{
next->next = n;
throw;
}
next = n;
}
else
{
// the linked list is empty so we need to allocate some more memory
node* block = static_cast<node*>(::operator new (sizeof(node)*chunk_size));
// the first part of this block can be our new object
temp = reinterpret_cast<T*>(block);
try
{
// construct this new T object with placement new.
new (static_cast<void*>(temp))T();
}
catch (...)
{
// construction of the new object threw so delete the block of memory
::operator delete ( static_cast<void*>(block));
throw;
}
// allocate a new chunk_node
chunk_node* chunk;
try {chunk = new chunk_node; }
catch (...)
{
temp->~T();
::operator delete ( static_cast<void*>(block));
throw;
}
// add this block into the chunk list
chunk->chunk = block;
chunk->next = first_chunk;
first_chunk = chunk;
++block;
// now add the rest of the block into the linked list of free nodes.
for (size_t i = 0; i < chunk_size-1; ++i)
{
block->next = next;
next = block;
++block;
}
}
++allocations;
return temp;
}
void deallocate (
T* item
)
{
--allocations;
item->~T();
// add this memory into our linked list.
node* temp = reinterpret_cast<node*>(item);
temp->next = next;
next = temp;
}
void swap (
memory_manager_kernel_3& item
)
{
exchange(allocations,item.allocations);
exchange(next,item.next);
exchange(first_chunk,item.first_chunk);
exchange(arrays,item.arrays);
}
private:
// data members
size_t allocations;
node* next;
chunk_node* first_chunk;
bst_of_arrays* arrays;
void initialize_array (
T* array,
size_t size
) const
{
size_t i;
try
{
for (i = 0; i < size; ++i)
{
// construct this new T object with placement new.
new (static_cast<void*>(array+i))T();
}
}
catch (...)
{
// Catch any exceptions thrown during the construction process
// and then destruct any T objects that actually were successfully
// constructed.
for (size_t j = 0; j < i; ++j)
{
array[i].~T();
}
throw;
}
}
void deinitialize_array (
T* array,
size_t size
) const
{
for (size_t i = 0; i < size; ++i)
{
array[i].~T();
}
}
// don't do any initialization for the built in types
void initialize_array(unsigned char*, size_t) {}
void deinitialize_array(unsigned char*, size_t) {}
void initialize_array(signed char*, size_t) {}
void deinitialize_array(signed char*, size_t) {}
void initialize_array(char*, size_t) {}
void deinitialize_array(char*, size_t) {}
void initialize_array(int*, size_t) {}
void deinitialize_array(int*, size_t) {}
void initialize_array(unsigned int*, size_t) {}
void deinitialize_array(unsigned int*, size_t) {}
void initialize_array(unsigned long*, size_t) {}
void deinitialize_array(unsigned long*, size_t) {}
void initialize_array(long*, size_t) {}
void deinitialize_array(long*, size_t) {}
void initialize_array(float*, size_t) {}
void deinitialize_array(float*, size_t) {}
void initialize_array(double*, size_t) {}
void deinitialize_array(double*, size_t) {}
void initialize_array(short*, size_t) {}
void deinitialize_array(short*, size_t) {}
void initialize_array(unsigned short*, size_t) {}
void deinitialize_array(unsigned short*, size_t) {}
// restricted functions
memory_manager_kernel_3(memory_manager_kernel_3&); // copy constructor
memory_manager_kernel_3& operator=(memory_manager_kernel_3&); // assignment operator
};
template <
typename T,
size_t chunk_size
>
inline void swap (
memory_manager_kernel_3<T,chunk_size>& a,
memory_manager_kernel_3<T,chunk_size>& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_MEMORY_MANAGER_KERNEl_3_

View File

@@ -0,0 +1,146 @@
// Copyright (C) 2004 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_MEMORY_MANAGER_KERNEl_ABSTRACT_
#ifdef DLIB_MEMORY_MANAGER_KERNEl_ABSTRACT_
#include "../algs.h"
namespace dlib
{
template <
typename T
>
class memory_manager
{
/*!
REQUIREMENTS ON T
T must have a default constructor.
INITIAL VALUE
get_number_of_allocations() == 0
WHAT THIS OBJECT REPRESENTS
This object represents some kind of memory manager or memory pool.
!*/
public:
typedef T type;
template <typename U>
struct rebind {
typedef memory_manager<U> other;
};
memory_manager(
);
/*!
ensures
- #*this is properly initialized
throws
- std::bad_alloc
!*/
virtual ~memory_manager(
);
/*!
ensures
- if (get_number_of_allocations() == 0) then
- all resources associated with *this have been released.
- else
- The memory still allocated will not be deleted and this
causes a memory leak.
!*/
size_t get_number_of_allocations (
) const;
/*!
ensures
- returns the current number of outstanding allocations
!*/
T* allocate (
);
/*!
ensures
- allocates a new object of type T and returns a pointer to it.
- #get_number_of_allocations() == get_number_of_allocations() + 1
throws
- std::bad_alloc or any exception thrown by T's constructor.
If this exception is thrown then the call to allocate()
has no effect on #*this.
!*/
void deallocate (
T* item
);
/*!
requires
- item == is a pointer to memory that was obtained from a call to
this->allocate(). (i.e. you can't deallocate a pointer you
got from a different memory_manager instance.)
- the memory pointed to by item hasn't already been deallocated.
ensures
- deallocates the object pointed to by item
- #get_number_of_allocations() == get_number_of_allocations() - 1
!*/
T* allocate_array (
size_t size
);
/*!
ensures
- allocates a new array of size objects of type T and returns a
pointer to it.
- #get_number_of_allocations() == get_number_of_allocations() + 1
throws
- std::bad_alloc or any exception thrown by T's constructor.
If this exception is thrown then the call to allocate()
has no effect on #*this.
!*/
void deallocate_array (
T* item
);
/*!
requires
- item == is a pointer to memory that was obtained from a call to
this->allocate_array(). (i.e. you can't deallocate a pointer you
got from a different memory_manager instance and it must be an
array.)
- the memory pointed to by item hasn't already been deallocated.
ensures
- deallocates the array pointed to by item
- #get_number_of_allocations() == get_number_of_allocations() - 1
!*/
void swap (
memory_manager& item
);
/*!
ensures
- swaps *this and item
!*/
private:
// restricted functions
memory_manager(memory_manager&); // copy constructor
memory_manager& operator=(memory_manager&); // assignment operator
};
template <
typename T
>
inline void swap (
memory_manager<T>& a,
memory_manager<T>& b
) { a.swap(b); }
/*!
provides a global swap function
!*/
}
#endif // DLIB_MEMORY_MANAGER_KERNEl_ABSTRACT_

View File

@@ -0,0 +1,38 @@
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_MEMORY_MANAGER_GLOBAl_
#define DLIB_MEMORY_MANAGER_GLOBAl_
#include "memory_manager_global/memory_manager_global_kernel_1.h"
#include "memory_manager.h"
namespace dlib
{
template <
typename T,
typename factory
>
class memory_manager_global
{
memory_manager_global() {}
public:
//----------- kernels ---------------
// kernel_1
typedef memory_manager_global_kernel_1<T,factory>
kernel_1a;
};
}
#endif // DLIB_MEMORY_MANAGER_GLOBAl_

View File

@@ -0,0 +1,113 @@
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_MEMORY_MANAGER_GLOBAl_1_
#define DLIB_MEMORY_MANAGER_GLOBAl_1_
#include "../algs.h"
#include "../memory_manager/memory_manager_kernel_abstract.h"
#include "memory_manager_global_kernel_abstract.h"
namespace dlib
{
template <
typename T,
typename factory
>
class memory_manager_global_kernel_1
{
/*!
INITIAL VALUE
- *global_mm == get_global_memory_manager()
CONVENTION
- global_mm->get_number_of_allocations() == get_number_of_allocations()
- *global_mm == get_global_memory_manager()
!*/
public:
typedef typename factory::template return_type<T>::type mm_global_type;
typedef T type;
template <typename U>
struct rebind {
typedef memory_manager_global_kernel_1<U,factory> other;
};
memory_manager_global_kernel_1(
) :
global_mm(factory::template get_instance<T>())
{}
virtual ~memory_manager_global_kernel_1(
) {}
size_t get_number_of_allocations (
) const { return global_mm->get_number_of_allocations(); }
mm_global_type& get_global_memory_manager (
) { return *global_mm; }
T* allocate (
)
{
return global_mm->allocate();
}
void deallocate (
T* item
)
{
global_mm->deallocate(item);
}
T* allocate_array (
size_t size
)
{
return global_mm->allocate_array(size);
}
void deallocate_array (
T* item
)
{
global_mm->deallocate_array(item);
}
void swap (
memory_manager_global_kernel_1& item
)
{
exchange(item.global_mm, global_mm);
}
private:
mm_global_type* global_mm;
// restricted functions
memory_manager_global_kernel_1(memory_manager_global_kernel_1&); // copy constructor
memory_manager_global_kernel_1& operator=(memory_manager_global_kernel_1&); // assignment operator
};
template <
typename T,
typename factory
>
inline void swap (
memory_manager_global_kernel_1<T,factory>& a,
memory_manager_global_kernel_1<T,factory>& b
) { a.swap(b); }
/*!
provides a global swap function
!*/
}
#endif // DLIB_MEMORY_MANAGER_GLOBAl_1_

View File

@@ -0,0 +1,181 @@
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_MEMORY_MANAGER_GLOBAl_ABSTRACT_
#ifdef DLIB_MEMORY_MANAGER_GLOBAl_ABSTRACT_
#include "../algs.h"
#include "../memory_manager/memory_manager_kernel_abstract.h"
namespace dlib
{
template <
typename T,
typename factory
>
class memory_manager_global
{
/*!
REQUIREMENTS ON T
T must have a default constructor.
REQUIREMENTS ON factory
factory must be defined as follows:
struct factory
{
template <typename U>
struct return_type {
typedef typename memory_manager_type<U> type;
};
template <typename U>
static typename return_type<U>::type* get_instance (
);
/ *!
ensures
- returns a pointer to an instance of a memory_manager object
where memory_manager_type implements the interface defined
by dlib/memory_manager/memory_manager_kernel_abstract.h
!* /
};
WHAT THIS OBJECT REPRESENTS
This object represents some kind of global memory manager or memory pool.
It is identical to the memory_manager object except that it gets all of
its allocations from a global instance of a memory_manager object which
is provided by the factory object's static member get_instance().
THREAD SAFETY
This object is, by itself, threadsafe. However, if you want to use this
object in multiple threads then you must ensure that your factory is
threadsafe. This means its factory::get_instance() method should be
threadsafe and the memory_manager object it returns must also be threadsafe.
!*/
public:
typedef typename factory::template return_type<T>::type mm_global_type;
typedef T type;
template <typename U>
struct rebind {
typedef memory_manager_global<U,factory> other;
};
memory_manager_global(
);
/*!
ensures
- #*this is properly initialized
- #get_global_memory_manager() == the memory manager that was
returned by a call to factory::get_instance<T>()
throws
- std::bad_alloc
!*/
virtual ~memory_manager_global(
);
/*!
ensures
- This destructor has no effect on the global memory_manager
get_global_memory_manager().
!*/
size_t get_number_of_allocations (
) const;
/*!
ensures
- returns get_global_memory_manager().get_number_of_allocations()
!*/
mm_global_type& get_global_memory_manager (
);
/*!
ensures
- returns a reference to the global memory manager instance being
used by *this.
!*/
T* allocate (
);
/*!
ensures
- #get_number_of_allocations() == get_number_of_allocations() + 1
- returns get_global_memory_manager().allocate()
throws
- std::bad_alloc or any exception thrown by T's constructor.
If this exception is thrown then the call to allocate()
has no effect on #*this.
!*/
void deallocate (
T* item
);
/*!
requires
- item == is a pointer to memory that was obtained from a call to
the get_global_memory_manager() object's allocate() method.
- the memory pointed to by item hasn't already been deallocated.
ensures
- calls get_global_memory_manager().deallocate(item)
- #get_number_of_allocations() == get_number_of_allocations() - 1
!*/
T* allocate_array (
size_t size
);
/*!
ensures
- #get_number_of_allocations() == get_number_of_allocations() + 1
- returns get_global_memory_manager().allocate_array()
throws
- std::bad_alloc or any exception thrown by T's constructor.
If this exception is thrown then the call to allocate_array()
has no effect on #*this.
!*/
void deallocate_array (
T* item
);
/*!
requires
- item == is a pointer to memory that was obtained from a call to
the get_global_memory_manager() object's allocate_array() method.
- the memory pointed to by item hasn't already been deallocated.
ensures
- calls get_global_memory_manager().deallocate_array(item)
- #get_number_of_allocations() == get_number_of_allocations() - 1
!*/
void swap (
memory_manager_global& item
);
/*!
ensures
- swaps *this and item
!*/
private:
// restricted functions
memory_manager_global(memory_manager_global&); // copy constructor
memory_manager_global& operator=(memory_manager_global&); // assignment operator
};
template <
typename T,
typename factory
>
inline void swap (
memory_manager_global<T,factory>& a,
memory_manager_global<T,factory>& b
) { a.swap(b); }
/*!
provides a global swap function
!*/
}
#endif // DLIB_MEMORY_MANAGER_GLOBAl_ABSTRACT_

View File

@@ -0,0 +1,72 @@
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_MEMORY_MANAGER_STATELESs_
#define DLIB_MEMORY_MANAGER_STATELESs_
#include "memory_manager_stateless/memory_manager_stateless_kernel_1.h"
#include "memory_manager_stateless/memory_manager_stateless_kernel_2.h"
#include "memory_manager.h"
namespace dlib
{
template <
typename T
>
class memory_manager_stateless
{
memory_manager_stateless() {}
public:
//----------- kernels ---------------
// kernel_1
typedef memory_manager_stateless_kernel_1<T>
kernel_1a;
// kernel_2
typedef memory_manager_stateless_kernel_2<T,memory_manager<char>::kernel_1a>
kernel_2_1a;
typedef memory_manager_stateless_kernel_2<T,memory_manager<char>::kernel_1b>
kernel_2_1b;
typedef memory_manager_stateless_kernel_2<T,memory_manager<char>::kernel_1c>
kernel_2_1c;
typedef memory_manager_stateless_kernel_2<T,memory_manager<char>::kernel_1d>
kernel_2_1d;
typedef memory_manager_stateless_kernel_2<T,memory_manager<char>::kernel_1e>
kernel_2_1e;
typedef memory_manager_stateless_kernel_2<T,memory_manager<char>::kernel_1f>
kernel_2_1f;
typedef memory_manager_stateless_kernel_2<T,memory_manager<char>::kernel_2a>
kernel_2_2a;
typedef memory_manager_stateless_kernel_2<T,memory_manager<char>::kernel_2b>
kernel_2_2b;
typedef memory_manager_stateless_kernel_2<T,memory_manager<char>::kernel_2c>
kernel_2_2c;
typedef memory_manager_stateless_kernel_2<T,memory_manager<char>::kernel_2d>
kernel_2_2d;
typedef memory_manager_stateless_kernel_2<T,memory_manager<char>::kernel_2e>
kernel_2_2e;
typedef memory_manager_stateless_kernel_2<T,memory_manager<char>::kernel_3a>
kernel_2_3a;
typedef memory_manager_stateless_kernel_2<T,memory_manager<char>::kernel_3b>
kernel_2_3b;
typedef memory_manager_stateless_kernel_2<T,memory_manager<char>::kernel_3c>
kernel_2_3c;
typedef memory_manager_stateless_kernel_2<T,memory_manager<char>::kernel_3d>
kernel_2_3d;
typedef memory_manager_stateless_kernel_2<T,memory_manager<char>::kernel_3e>
kernel_2_3e;
};
}
#endif // DLIB_MEMORY_MANAGER_STATELESs_

View File

@@ -0,0 +1,101 @@
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_MEMORY_MANAGER_STATELESs_1_
#define DLIB_MEMORY_MANAGER_STATELESs_1_
#include "memory_manager_stateless_kernel_abstract.h"
#include <memory>
namespace dlib
{
template <
typename T
>
class memory_manager_stateless_kernel_1
{
/*!
this implementation just calls new and delete directly
!*/
public:
typedef T type;
const static bool is_stateless = true;
template <typename U>
struct rebind {
typedef memory_manager_stateless_kernel_1<U> other;
};
memory_manager_stateless_kernel_1(
)
{}
virtual ~memory_manager_stateless_kernel_1(
) {}
T* allocate (
)
{
return new T;
}
void deallocate (
T* item
)
{
delete item;
}
T* allocate_array (
size_t size
)
{
return new T[size];
}
void deallocate_array (
T* item
)
{
delete [] item;
}
void swap (memory_manager_stateless_kernel_1&)
{}
std::unique_ptr<T> extract(
T* item
)
{
return std::unique_ptr<T>(item);
}
std::unique_ptr<T[]> extract_array(
T* item
)
{
return std::unique_ptr<T[]>(item);
}
private:
// restricted functions
memory_manager_stateless_kernel_1(memory_manager_stateless_kernel_1&); // copy constructor
memory_manager_stateless_kernel_1& operator=(memory_manager_stateless_kernel_1&); // assignment operator
};
template <
typename T
>
inline void swap (
memory_manager_stateless_kernel_1<T>& a,
memory_manager_stateless_kernel_1<T>& b
) { a.swap(b); }
}
#endif // DLIB_MEMORY_MANAGER_STATELESs_1_

View File

@@ -0,0 +1,119 @@
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_MEMORY_MANAGER_STATELESs_2_
#define DLIB_MEMORY_MANAGER_STATELESs_2_
#include "../algs.h"
#include "memory_manager_stateless_kernel_abstract.h"
#include "../threads.h"
namespace dlib
{
template <
typename T,
typename mem_manager
>
class memory_manager_stateless_kernel_2
{
/*!
REQUIREMENTS ON mem_manager
mem_manager must be an implementation of memory_manager/memory_manager_kernel_abstract.h
CONVENTION
this object has a single global instance of mem_manager
!*/
public:
typedef T type;
const static bool is_stateless = true;
template <typename U>
struct rebind {
typedef memory_manager_stateless_kernel_2<U,mem_manager> other;
};
memory_manager_stateless_kernel_2(
)
{
// call this just to make sure the mutex is is initialized before
// multiple threads start calling the member functions.
global_mutex();
}
virtual ~memory_manager_stateless_kernel_2(
) {}
T* allocate (
)
{
auto_mutex M(global_mutex());
return global_mm().allocate();
}
void deallocate (
T* item
)
{
auto_mutex M(global_mutex());
return global_mm().deallocate(item);
}
T* allocate_array (
size_t size
)
{
auto_mutex M(global_mutex());
return global_mm().allocate_array(size);
}
void deallocate_array (
T* item
)
{
auto_mutex M(global_mutex());
return global_mm().deallocate_array(item);
}
void swap (memory_manager_stateless_kernel_2&)
{}
private:
static mutex& global_mutex (
)
{
static mutex lock;
return lock;
}
typedef typename mem_manager::template rebind<T>::other rebound_mm_type;
static rebound_mm_type& global_mm (
)
{
static rebound_mm_type mm;
return mm;
}
// restricted functions
memory_manager_stateless_kernel_2(memory_manager_stateless_kernel_2&); // copy constructor
memory_manager_stateless_kernel_2& operator=(memory_manager_stateless_kernel_2&); // assignment operator
};
template <
typename T,
typename mem_manager
>
inline void swap (
memory_manager_stateless_kernel_2<T,mem_manager>& a,
memory_manager_stateless_kernel_2<T,mem_manager>& b
) { a.swap(b); }
}
#endif // DLIB_MEMORY_MANAGER_STATELESs_2_

View File

@@ -0,0 +1,173 @@
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_MEMORY_MANAGER_STATELESs_ABSTRACT_
#ifdef DLIB_MEMORY_MANAGER_STATELESs_ABSTRACT_
#include "../algs.h"
#include <memory>
namespace dlib
{
template <
typename T
>
class memory_manager_stateless
{
/*!
REQUIREMENTS ON T
T must have a default constructor.
WHAT THIS OBJECT REPRESENTS
This object represents some kind of stateless memory manager or memory pool.
Stateless means that all instances (instances of the same kernel implementation that is)
of this object are identical and can be used interchangeably. Note that
implementations are allowed to have some shared global state such as a
global memory pool.
THREAD SAFETY
This object is thread safe. You may access it from any thread at any time
without synchronizing access.
!*/
public:
typedef T type;
const static bool is_stateless = true;
template <typename U>
struct rebind {
typedef memory_manager_stateless<U> other;
};
memory_manager_stateless(
);
/*!
ensures
- #*this is properly initialized
throws
- std::bad_alloc
!*/
virtual ~memory_manager_stateless(
);
/*!
ensures
- frees any resources used by *this but has no effect on any shared global
resources used by the implementation.
!*/
T* allocate (
);
/*!
ensures
- allocates a new object of type T and returns a pointer to it.
throws
- std::bad_alloc or any exception thrown by T's constructor.
If this exception is thrown then the call to allocate()
has no effect on #*this.
!*/
void deallocate (
T* item
);
/*!
requires
- item == is a pointer to memory that was obtained from a call to
allocate(). (i.e. The pointer you are deallocating must have
come from the same implementation of memory_manager_stateless
that is trying to deallocate it.)
- the memory pointed to by item hasn't already been deallocated.
ensures
- deallocates the object pointed to by item
!*/
T* allocate_array (
size_t size
);
/*!
ensures
- allocates a new array of size objects of type T and returns a
pointer to it.
throws
- std::bad_alloc or any exception thrown by T's constructor.
If this exception is thrown then the call to allocate()
has no effect on #*this.
!*/
void deallocate_array (
T* item
);
/*!
requires
- item == is a pointer to memory that was obtained from a call to
allocate_array(). (i.e. The pointer you are deallocating must have
come from the same implementation of memory_manager_stateless
that is trying to deallocate it.)
- the memory pointed to by item hasn't already been deallocated.
ensures
- deallocates the array pointed to by item
!*/
void swap (
memory_manager_stateless& item
);
/*!
ensures
- this function has no effect on *this or item. It is just provided
to make this object's interface more compatible with the other
memory managers.
!*/
std::unique_ptr<T> extract(
T* item
);
/*!
requires
- item == is a pointer to memory that was obtained from a call to
allocate().
ensures
- returns a unique_ptr that owns item. That is, if the returned ptr is
PTR then PTR.get() == item. Therefore, this function extracts item
from the memory manager's internal pool. Therefore, you shouldn't
call deallocate(item) after this.
- Note that not all memory managers implement extract().
!*/
std::unique_ptr<T[]> extract_array(
T* item
);
/*!
requires
- item == is a pointer to memory that was obtained from a call to
allocate_array().
ensures
- returns a unique_ptr that owns item. That is, if the returned ptr is
PTR then PTR.get() == item. Therefore, this function extracts item
from the memory manager's internal pool. Therefore, you shouldn't
call deallocate_array(item) after this.
- Note that not all memory managers implement extract().
!*/
private:
// restricted functions
memory_manager_stateless(memory_manager_stateless&); // copy constructor
memory_manager_stateless& operator=(memory_manager_stateless&); // assignment operator
};
template <
typename T
>
inline void swap (
memory_manager_stateless<T>& a,
memory_manager_stateless<T>& b
) { a.swap(b); }
/*!
provides a global swap function
!*/
}
#endif // DLIB_MEMORY_MANAGER_STATELESs_ABSTRACT_

View File

@@ -0,0 +1,111 @@
// Copyright (C) 2017 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_METApROGRAMMING_Hh_
#define DLIB_METApROGRAMMING_Hh_
#include "algs.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
template <size_t... n>
struct compile_time_integer_list
{
/*!
WHAT THIS OBJECT REPRESENTS
The point of this type is to, as the name suggests, hold a compile time list of integers.
As an example, here is something simple you could do with it:
template <size_t... ints>
void print_compile_time_ints (
compile_time_integer_list<ints...>
)
{
print(ints...);
}
int main()
{
print_compile_time_ints(compile_time_integer_list<0,4,9>());
}
Which just calls: print(0,4,9);
This is a simple example, but this kind of thing is useful in larger and
more complex template metaprogramming constructs.
!*/
template <size_t m>
struct push_back
{
typedef compile_time_integer_list<n..., m> type;
};
};
// ----------------------------------------------------------------------------------------
template <size_t max>
struct make_compile_time_integer_range
{
/*!
WHAT THIS OBJECT REPRESENTS
This object makes a compile_time_integer_list containing the integers in the range [1,max] inclusive.
For example:
make_compile_time_integer_range<4>::type
evaluates to:
compile_time_integer_list<1,2,3,4>
!*/
typedef typename make_compile_time_integer_range<max-1>::type::template push_back<max>::type type;
};
// base case
template <> struct make_compile_time_integer_range<0> { typedef compile_time_integer_list<> type; };
// ----------------------------------------------------------------------------------------
namespace impl
{
template <
typename Funct,
typename... Args,
typename int_<decltype(std::declval<Funct>()(std::declval<Args>()...))>::type = 0
>
bool call_if_valid (
special_,
Funct&& f, Args&&... args
)
{
f(std::forward<Args>(args)...);
return true;
}
template <
typename Funct,
typename... Args
>
bool call_if_valid (
general_,
Funct&& /*f*/, Args&&... /*args*/
) { return false; }
}
template <typename Funct, typename... Args>
bool call_if_valid(Funct&& f, Args&&... args)
/*!
ensures
- if f(std::forward<Args>(args)...) is a valid expression then we evaluate it and return
true. Otherwise we do nothing and return false.
!*/
{
return impl::call_if_valid(special_(), f, std::forward<Args>(args)...);
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_METApROGRAMMING_Hh_

View File

@@ -0,0 +1,20 @@
// Copyright (C) 2004 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_MISC_APi_
#define DLIB_MISC_APi_
#include "platform.h"
#ifdef WIN32
#include "misc_api/windows.h"
#endif
#ifndef WIN32
#include "misc_api/posix.h"
#endif
#include "misc_api/misc_api_shared.h"
#endif // DLIB_MISC_APi_

View File

@@ -0,0 +1,110 @@
// Copyright (C) 2004 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_MISC_API_KERNEl_1_
#define DLIB_MISC_API_KERNEl_1_
#ifdef DLIB_ISO_CPP_ONLY
#error "DLIB_ISO_CPP_ONLY is defined so you can't use this OS dependent code. Turn DLIB_ISO_CPP_ONLY off if you want to use it."
#endif
#include "misc_api_kernel_abstract.h"
#include "../algs.h"
#include <string>
#include "../uintn.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
void sleep (
unsigned long milliseconds
);
// ----------------------------------------------------------------------------------------
std::string get_current_dir (
);
// ----------------------------------------------------------------------------------------
class set_current_dir_error : public error
{
public:
set_current_dir_error(
const std::string& a
): error(a) {}
};
void set_current_dir (
const std::string& new_dir
);
// ----------------------------------------------------------------------------------------
class timestamper
{
/*!
INITIAL VALUE
- last_time == 0
- offset == 0
- dword_max == 2^32
CONVENTION
- last_time == the time returned by GetTickCount() the last time we
called it.
- offset == the number of microseconds we should add to the result of
GetTickCount() so that it is correct.
- dword_max == 2^32.
This is the number of values representable by a DWORD.
!*/
mutable unsigned long last_time;
mutable uint64 offset;
mutable uint64 dword_max;
public:
timestamper(
) :
last_time(0),
offset(0)
{
dword_max = 0xFFFFFFFF;
++dword_max;
}
uint64 get_timestamp (
) const;
};
// ----------------------------------------------------------------------------------------
class dir_create_error : public error
{
public:
dir_create_error(
const std::string& dir_name
) :
error(EDIR_CREATE,"Error creating directory '" + dir_name + "'."),
name(dir_name)
{}
~dir_create_error() throw() {}
const std::string name;
};
void create_directory (
const std::string& dir
);
// ----------------------------------------------------------------------------------------
}
#ifdef NO_MAKEFILE
#include "misc_api_kernel_1.cpp"
#endif
#endif // DLIB_MISC_API_KERNEl_1_

View File

@@ -0,0 +1,81 @@
// Copyright (C) 2004 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_MISC_API_KERNEl_2_
#define DLIB_MISC_API_KERNEl_2_
#ifdef DLIB_ISO_CPP_ONLY
#error "DLIB_ISO_CPP_ONLY is defined so you can't use this OS dependent code. Turn DLIB_ISO_CPP_ONLY off if you want to use it."
#endif
#include "misc_api_kernel_abstract.h"
#include "../algs.h"
#include <string>
#include "../uintn.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
void sleep (
unsigned long milliseconds
);
// ----------------------------------------------------------------------------------------
std::string get_current_dir (
);
// ----------------------------------------------------------------------------------------
class set_current_dir_error : public error
{
public:
set_current_dir_error(
const std::string& a
): error(a) {}
};
void set_current_dir (
const std::string& new_dir
);
// ----------------------------------------------------------------------------------------
class timestamper
{
public:
uint64 get_timestamp (
) const;
};
// ----------------------------------------------------------------------------------------
class dir_create_error : public error
{
public:
dir_create_error(
const std::string& dir_name
) :
error(EDIR_CREATE,"Error creating directory '" + dir_name + "'."),
name(dir_name)
{}
const std::string& name;
};
void create_directory (
const std::string& dir
);
// ----------------------------------------------------------------------------------------
}
#ifdef NO_MAKEFILE
#include "misc_api_kernel_2.cpp"
#endif
#endif // DLIB_MISC_API_KERNEl_2_

View File

@@ -0,0 +1,159 @@
// Copyright (C) 2004 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_MISC_API_KERNEl_ABSTRACT_
#ifdef DLIB_MISC_API_KERNEl_ABSTRACT_
#include <string>
#include "../uintn.h"
#include "../algs.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
/*!
GENERAL COMMENTS
This file just contains miscellaneous api functions
!*/
// ----------------------------------------------------------------------------------------
void sleep (
unsigned long milliseconds
);
/*!
ensures
- causes the calling thread to sleep for the given number of
milliseconds.
!*/
// ----------------------------------------------------------------------------------------
std::string get_current_dir (
);
/*!
ensures
- if (no errors occur) then
- returns the path to the current working directory
- else
- returns ""
throws
- std::bad_alloc
!*/
// ----------------------------------------------------------------------------------------
class set_current_dir_error : public error;
void set_current_dir (
const std::string& new_dir
);
/*!
ensures
- sets the current working directory to new_dir
throws
- std::bad_alloc
- set_current_dir_error
This exception is thrown if there is an error when attempting
to change the current working directory.
!*/
// ----------------------------------------------------------------------------------------
class locally_change_current_dir : noncopyable
{
/*!
WHAT THIS OBJECT REPRESENTS
This object is a RAII tool for safely switching the current directory
to a new directory and then automatically switching back to the original
directory upon this object's destruction.
!*/
public:
explicit locally_change_current_dir (
const std::string& new_dir
);
/*!
ensures
- calls set_current_dir(new_dir)
- #old_dir() == The value of get_current_dir() prior to switching to new_dir.
!*/
const std::string& old_dir (
) const;
/*!
ensures
- returns the directory we switch back to once this object is destructed.
!*/
~locally_change_current_dir(
);
/*!
ensures
- if (revert() hasn't already been called) then
- calls set_current_dir(old_dir())
!*/
void revert (
);
/*!
ensures
- if (revert() hasn't already been called) then
- calls set_current_dir(old_dir())
!*/
};
// ----------------------------------------------------------------------------------------
class dir_create_error : public error {
public:
const std::string name
};
void create_directory (
const std::string& dir
);
/*!
ensures
- if (dir does not already exist) then
- creates the given directory.
- else
- the call to create_directory() has no effect.
throws
- dir_create_error
This exception is thrown if we were unable to create the requested
directory and it didn't already exist. The type member of the exception
will bet set to EDIR_CREATE and the name member will be set to dir.
!*/
// ----------------------------------------------------------------------------------------
class timestamper
{
/*!
WHAT THIS OBJECT REPRESENTS
This object represents a timer that is capable of returning
timestamps.
Note that the time is measured in microseconds but you are not
guaranteed to have that level of resolution. The actual resolution
is implementation dependent.
!*/
public:
uint64 get_timestamp (
) const;
/*!
ensures
- returns a timestamp that measures the time in microseconds since an
arbitrary point in the past. Note that this arbitrary point remains
the same between all calls to get_timestamp().
!*/
};
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_MISC_API_KERNEl_ABSTRACT_

View File

@@ -0,0 +1,57 @@
// Copyright (C) 2014 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_MISC_API_ShARED_Hh_
#define DLIB_MISC_API_ShARED_Hh_
#include <string>
#include "../noncopyable.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
class locally_change_current_dir : noncopyable
{
public:
explicit locally_change_current_dir (
const std::string& new_dir
)
{
reverted = false;
_old_dir = get_current_dir();
set_current_dir(new_dir);
}
~locally_change_current_dir()
{
revert();
}
const std::string& old_dir (
) const
{
return _old_dir;
}
void revert (
)
{
if (!reverted)
{
set_current_dir(_old_dir);
reverted = true;
}
}
private:
bool reverted;
std::string _old_dir;
};
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_MISC_API_ShARED_Hh_

View File

@@ -0,0 +1,6 @@
// Copyright (C) 2004 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_MISC_API_KERNEl_1_
#include "misc_api_kernel_2.h"
#endif

View File

@@ -0,0 +1,6 @@
// Copyright (C) 2004 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_MISC_API_KERNEl_2_
#include "misc_api_kernel_1.h"
#endif

View File

@@ -0,0 +1,32 @@
// (C) Copyright Beman Dawes 1999-2003. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Contributed by Dave Abrahams
// See http://www.boost.org/libs/utility for documentation.
#ifndef DLIB_BOOST_NONCOPYABLE_HPP_INCLUDED
#define DLIB_BOOST_NONCOPYABLE_HPP_INCLUDED
namespace dlib
{
class noncopyable
{
/*!
This class makes it easier to declare a class as non-copyable.
If you want to make an object that can't be copied just inherit
from this object.
!*/
protected:
noncopyable() = default;
~noncopyable() = default;
private: // emphasize the following members are private
noncopyable(const noncopyable&);
const noncopyable& operator=(const noncopyable&);
};
}
#endif // DLIB_BOOST_NONCOPYABLE_HPP_INCLUDED

View File

@@ -0,0 +1,53 @@
//Copyright (C) 2013 Steve Taylor (steve98654@gmail.com), Davis E. King
//License: Boost Software License. See LICENSE.txt for full license.
#ifndef DLIB_NUMERIC_CONSTANTs_H_
#define DLIB_NUMERIC_CONSTANTs_H_
namespace dlib
{
// pi -- Pi
const double pi = 3.1415926535897932385;
// e -- Euler's Constant
const double e = 2.7182818284590452354;
// sqrt_2 -- The square root of 2
const double sqrt_2 = 1.4142135623730950488;
// sqrt_3 -- The square root of 3
const double sqrt_3 = 1.7320508075688772935;
// log10_2 -- The logarithm base 10 of two
const double log10_2 = 0.30102999566398119521;
// light_spd -- The speed of light in vacuum in meters per second
const double light_spd = 2.99792458e8;
// newton_G -- Newton's gravitational constant (in metric units of m^3/(kg*s^2))
const double newton_G = 6.67384e-11;
// planck_cst -- Planck's constant (in units of Joules * seconds)
const double planck_cst = 6.62606957e-34;
// golden_ratio -- The Golden Ratio
const double golden_ratio = 1.6180339887498948482;
// euler_gamma -- The Euler Mascheroni Constant
const double euler_gamma = 0.5772156649015328606065;
// catalan -- Catalan's Constant
const double catalan = 0.91596559417721901505;
// glaisher -- Glaisher Kinkelin constant
const double glaisher = 1.2824271291006226369;
// khinchin -- Khinchin's constant
const double khinchin = 2.6854520010653064453;
// apery -- Apery's constant
const double apery = 1.2020569031595942854;
}
#endif //DLIB_NUMERIC_CONSTANTs_H_

View File

@@ -0,0 +1,8 @@
// Copyright (C) 2013 Steve Taylor (steve98654@gmail.com)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_INTEGRATE_FUNCTION_ADAPT_SIMPSON_HEADER
#define DLIB_INTEGRATE_FUNCTION_ADAPT_SIMPSON_HEADER
#include "numerical_integration/integrate_function_adapt_simpson.h"
#endif // DLIB_INTEGRATE_FUNCTION_ADAPT_SIMPSON_HEADER

View File

@@ -0,0 +1,93 @@
// Copyright (C) 2013 Steve Taylor (steve98654@gmail.com)
// License: Boost Software License See LICENSE.txt for full license
#ifndef DLIB_INTEGRATE_FUNCTION_ADAPT_SIMPSONh_
#define DLIB_INTEGRATE_FUNCTION_ADAPT_SIMPSONh_
#include "integrate_function_adapt_simpson_abstract.h"
#include "../assert.h"
// ----------------------------------------------------------------------------------------
namespace dlib
{
template <typename T, typename funct>
T impl_adapt_simp_stop(const funct& f, T a, T b, T fa, T fm, T fb, T is, int cnt)
{
const int maxint = 500;
T m = (a + b)/2.0;
T h = (b - a)/4.0;
T fml = f(a + h);
T fmr = f(b - h);
T i1 = h/1.5*(fa+4.0*fm+fb);
T i2 = h/3.0*(fa+4.0*(fml+fmr)+2.0*fm+fb);
i1 = (16.0*i2 - i1)/15.0;
T Q = 0;
if ((std::abs(i1-i2) <= std::abs(is)) || (m <= a) || (b <= m))
{
Q = i1;
}
else
{
if(cnt < maxint)
{
cnt = cnt + 1;
Q = impl_adapt_simp_stop(f,a,m,fa,fml,fm,is,cnt)
+ impl_adapt_simp_stop(f,m,b,fm,fmr,fb,is,cnt);
}
}
return Q;
}
// ----------------------------------------------------------------------------------------
template <typename T, typename funct>
T integrate_function_adapt_simp(
const funct& f,
T a,
T b,
T tol = 1e-10
)
{
// make sure requires clause is not broken
DLIB_ASSERT(b > a && tol > 0,
"\t T integrate_function_adapt_simp()"
<< "\n\t Invalid arguments were given to this function."
<< "\n\t a: " << a
<< "\n\t b: " << b
<< "\n\t tol: " << tol
);
T eps = std::numeric_limits<T>::epsilon();
if(tol < eps)
{
tol = eps;
}
const T ba = b-a;
const T fa = f(a);
const T fb = f(b);
const T fm = f((a+b)/2);
T is = ba/8*(fa+fb+fm+ f(a + 0.9501*ba) + f(a + 0.2311*ba) + f(a + 0.6068*ba)
+ f(a + 0.4860*ba) + f(a + 0.8913*ba));
if(is == 0)
{
is = b-a;
}
is = is*tol;
int cnt = 0;
return impl_adapt_simp_stop(f, a, b, fa, fm, fb, is, cnt);
}
}
// ----------------------------------------------------------------------------------------
#endif // DLIB_INTEGRATE_FUNCTION_ADAPT_SIMPSONh_

View File

@@ -0,0 +1,34 @@
// Copyright (C) 2013 Steve Taylor (steve98654@gmail.com)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_INTEGRATE_FUNCTION_ADAPT_SIMPSON_ABSTRACTh_
#ifdef DLIB_INTEGRATE_FUNCTION_ADAPT_SIMPSON_ABSTRACTh_
namespace dlib
{
template <typename T, typename funct>
T integrate_function_adapt_simp(
const funct& f,
T a,
T b,
T tol = 1e-10
);
/*!
requires
- b > a
- tol > 0
- T should be either float, double, or long double
- The expression f(a) should be a valid expression that evaluates to a T.
I.e. f() should be a real valued function of a single variable.
ensures
- returns an approximation of the integral of f over the domain [a,b] using the
adaptive Simpson method outlined in Gander, W. and W. Gautshi, "Adaptive
Quadrature -- Revisited" BIT, Vol. 40, (2000), pp.84-101
- tol is a tolerance parameter that determines the overall accuracy of
approximated integral. We suggest a default value of 1e-10 for tol.
!*/
}
#endif // DLIB_INTEGRATE_FUNCTION_ADAPT_SIMPSON_ABSTRACTh_

View File

@@ -0,0 +1 @@
#include "dlib_include_path_tutorial.txt"

View File

@@ -0,0 +1,10 @@
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_PIPe_
#define DLIB_PIPe_
#include "pipe/pipe_kernel_1.h"
#endif // DLIB_PIPe_

View File

@@ -0,0 +1,756 @@
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_PIPE_KERNEl_1_
#define DLIB_PIPE_KERNEl_1_
#include "../algs.h"
#include "../threads.h"
#include "pipe_kernel_abstract.h"
namespace dlib
{
template <
typename T
>
class pipe
{
/*!
INITIAL VALUE
- pipe_size == 0
- pipe_max_size == defined by constructor
- enabled == true
- data == a pointer to an array of ((pipe_max_size>0)?pipe_max_size:1) T objects.
- dequeue_waiters == 0
- enqueue_waiters == 0
- first == 1
- last == 1
- unblock_sig_waiters == 0
CONVENTION
- size() == pipe_size
- max_size() == pipe_max_size
- is_enabled() == enabled
- m == the mutex used to lock access to all the members of this class
- dequeue_waiters == the number of threads blocked on calls to dequeue()
- enqueue_waiters == the number of threads blocked on calls to enqueue() and
wait_until_empty()
- unblock_sig_waiters == the number of threads blocked on calls to
wait_for_num_blocked_dequeues() and the destructor. (i.e. the number of
blocking calls to unblock_sig.wait())
- dequeue_sig == the signaler that threads blocked on calls to dequeue() wait on
- enqueue_sig == the signaler that threads blocked on calls to enqueue()
or wait_until_empty() wait on.
- unblock_sig == the signaler that is signaled when a thread stops blocking on a call
to enqueue() or dequeue(). It is also signaled when a dequeue that will probably
block is called. The destructor and wait_for_num_blocked_dequeues are the only
things that will wait on this signaler.
- if (pipe_size > 0) then
- data[first] == the next item to dequeue
- data[last] == the item most recently added via enqueue, so the last to dequeue.
- else if (pipe_max_size == 0)
- if (first == 0 && last == 0) then
- data[0] == the next item to dequeue
- else if (first == 0 && last == 1) then
- data[0] has been taken out already by a dequeue
!*/
public:
// this is here for backwards compatibility with older versions of dlib.
typedef pipe kernel_1a;
typedef T type;
explicit pipe (
size_t maximum_size
);
virtual ~pipe (
);
void empty (
);
void wait_until_empty (
) const;
void wait_for_num_blocked_dequeues (
unsigned long num
)const;
void enable (
);
void disable (
);
bool is_enqueue_enabled (
) const;
void disable_enqueue (
);
void enable_enqueue (
);
bool is_dequeue_enabled (
) const;
void disable_dequeue (
);
void enable_dequeue (
);
bool is_enabled (
) const;
size_t max_size (
) const;
size_t size (
) const;
bool enqueue (
T& item
);
bool enqueue (
T&& item
) { return enqueue(item); }
bool dequeue (
T& item
);
bool enqueue_or_timeout (
T& item,
unsigned long timeout
);
bool enqueue_or_timeout (
T&& item,
unsigned long timeout
) { return enqueue_or_timeout(item,timeout); }
bool dequeue_or_timeout (
T& item,
unsigned long timeout
);
private:
size_t pipe_size;
const size_t pipe_max_size;
bool enabled;
T* const data;
size_t first;
size_t last;
mutex m;
signaler dequeue_sig;
signaler enqueue_sig;
signaler unblock_sig;
unsigned long dequeue_waiters;
mutable unsigned long enqueue_waiters;
mutable unsigned long unblock_sig_waiters;
bool enqueue_enabled;
bool dequeue_enabled;
// restricted functions
pipe(const pipe&); // copy constructor
pipe& operator=(const pipe&); // assignment operator
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename T
>
pipe<T>::
pipe (
size_t maximum_size
) :
pipe_size(0),
pipe_max_size(maximum_size),
enabled(true),
data(new T[(maximum_size>0) ? maximum_size : 1]),
first(1),
last(1),
dequeue_sig(m),
enqueue_sig(m),
unblock_sig(m),
dequeue_waiters(0),
enqueue_waiters(0),
unblock_sig_waiters(0),
enqueue_enabled(true),
dequeue_enabled(true)
{
}
// ----------------------------------------------------------------------------------------
template <
typename T
>
pipe<T>::
~pipe (
)
{
auto_mutex M(m);
++unblock_sig_waiters;
// first make sure no one is blocked on any calls to enqueue() or dequeue()
enabled = false;
dequeue_sig.broadcast();
enqueue_sig.broadcast();
unblock_sig.broadcast();
// wait for all threads to unblock
while (dequeue_waiters > 0 || enqueue_waiters > 0 || unblock_sig_waiters > 1)
unblock_sig.wait();
delete [] data;
--unblock_sig_waiters;
}
// ----------------------------------------------------------------------------------------
template <
typename T
>
void pipe<T>::
empty (
)
{
auto_mutex M(m);
pipe_size = 0;
// let any calls to enqueue() know that the pipe is now empty
if (enqueue_waiters > 0)
enqueue_sig.broadcast();
}
// ----------------------------------------------------------------------------------------
template <
typename T
>
void pipe<T>::
wait_until_empty (
) const
{
auto_mutex M(m);
// this function is sort of like a call to enqueue so treat it like that
++enqueue_waiters;
while (pipe_size > 0 && enabled && dequeue_enabled )
enqueue_sig.wait();
// let the destructor know we are ending if it is blocked waiting
if (enabled == false)
unblock_sig.broadcast();
--enqueue_waiters;
}
// ----------------------------------------------------------------------------------------
template <
typename T
>
void pipe<T>::
enable (
)
{
auto_mutex M(m);
enabled = true;
}
// ----------------------------------------------------------------------------------------
template <
typename T
>
void pipe<T>::
disable (
)
{
auto_mutex M(m);
enabled = false;
dequeue_sig.broadcast();
enqueue_sig.broadcast();
unblock_sig.broadcast();
}
// ----------------------------------------------------------------------------------------
template <
typename T
>
bool pipe<T>::
is_enabled (
) const
{
auto_mutex M(m);
return enabled;
}
// ----------------------------------------------------------------------------------------
template <
typename T
>
size_t pipe<T>::
max_size (
) const
{
auto_mutex M(m);
return pipe_max_size;
}
// ----------------------------------------------------------------------------------------
template <
typename T
>
size_t pipe<T>::
size (
) const
{
auto_mutex M(m);
return pipe_size;
}
// ----------------------------------------------------------------------------------------
template <
typename T
>
bool pipe<T>::
enqueue (
T& item
)
{
auto_mutex M(m);
++enqueue_waiters;
// wait until there is room or we are disabled
while (pipe_size == pipe_max_size && enabled && enqueue_enabled &&
!(pipe_max_size == 0 && first == 1) )
enqueue_sig.wait();
if (enabled == false || enqueue_enabled == false)
{
--enqueue_waiters;
// let the destructor know we are unblocking
unblock_sig.broadcast();
return false;
}
// set the appropriate values for first and last
if (pipe_size == 0)
{
first = 0;
last = 0;
}
else
{
last = (last+1)%pipe_max_size;
}
exchange(item,data[last]);
// wake up a call to dequeue() if there are any currently blocked
if (dequeue_waiters > 0)
dequeue_sig.signal();
if (pipe_max_size > 0)
{
++pipe_size;
}
else
{
// wait for a dequeue to take the item out
while (last == 0 && enabled && enqueue_enabled)
enqueue_sig.wait();
if (last == 0 && (enabled == false || enqueue_enabled == false))
{
last = 1;
first = 1;
// no one dequeued this object to put it back into item
exchange(item,data[0]);
--enqueue_waiters;
// let the destructor know we are unblocking
if (unblock_sig_waiters > 0)
unblock_sig.broadcast();
return false;
}
last = 1;
first = 1;
// tell any waiting calls to enqueue() that one of them can proceed
if (enqueue_waiters > 1)
enqueue_sig.broadcast();
// let the destructor know we are unblocking
if (enabled == false && unblock_sig_waiters > 0)
unblock_sig.broadcast();
}
--enqueue_waiters;
return true;
}
// ----------------------------------------------------------------------------------------
template <
typename T
>
bool pipe<T>::
dequeue (
T& item
)
{
auto_mutex M(m);
++dequeue_waiters;
if (pipe_size == 0)
{
// notify wait_for_num_blocked_dequeues()
if (unblock_sig_waiters > 0)
unblock_sig.broadcast();
// notify any blocked enqueue_or_timeout() calls
if (enqueue_waiters > 0)
enqueue_sig.broadcast();
}
// wait until there is something in the pipe or we are disabled
while (pipe_size == 0 && enabled && dequeue_enabled &&
!(pipe_max_size == 0 && first == 0 && last == 0) )
dequeue_sig.wait();
if (enabled == false || dequeue_enabled == false)
{
--dequeue_waiters;
// let the destructor know we are unblocking
unblock_sig.broadcast();
return false;
}
exchange(item,data[first]);
if (pipe_max_size > 0)
{
// set the appropriate values for first
first = (first+1)%pipe_max_size;
--pipe_size;
}
else
{
// let the enqueue waiting on us know that we took the
// item out already.
last = 1;
}
// wake up a call to enqueue() if there are any currently blocked
if (enqueue_waiters > 0)
enqueue_sig.broadcast();
--dequeue_waiters;
return true;
}
// ----------------------------------------------------------------------------------------
template <
typename T
>
bool pipe<T>::
enqueue_or_timeout (
T& item,
unsigned long timeout
)
{
auto_mutex M(m);
++enqueue_waiters;
// wait until there is room or we are disabled or
// we run out of time.
bool timed_out = false;
while (pipe_size == pipe_max_size && enabled && enqueue_enabled &&
!(pipe_max_size == 0 && dequeue_waiters > 0 && first == 1) )
{
if (timeout == 0 || enqueue_sig.wait_or_timeout(timeout) == false)
{
timed_out = true;
break;
}
}
if (enabled == false || timed_out || enqueue_enabled == false)
{
--enqueue_waiters;
// let the destructor know we are unblocking
unblock_sig.broadcast();
return false;
}
// set the appropriate values for first and last
if (pipe_size == 0)
{
first = 0;
last = 0;
}
else
{
last = (last+1)%pipe_max_size;
}
exchange(item,data[last]);
// wake up a call to dequeue() if there are any currently blocked
if (dequeue_waiters > 0)
dequeue_sig.signal();
if (pipe_max_size > 0)
{
++pipe_size;
}
else
{
// wait for a dequeue to take the item out
while (last == 0 && enabled && enqueue_enabled)
enqueue_sig.wait();
if (last == 0 && (enabled == false || enqueue_enabled == false))
{
last = 1;
first = 1;
// no one dequeued this object to put it back into item
exchange(item,data[0]);
--enqueue_waiters;
// let the destructor know we are unblocking
if (unblock_sig_waiters > 0)
unblock_sig.broadcast();
return false;
}
last = 1;
first = 1;
// tell any waiting calls to enqueue() that one of them can proceed
if (enqueue_waiters > 1)
enqueue_sig.broadcast();
// let the destructor know we are unblocking
if (enabled == false && unblock_sig_waiters > 0)
unblock_sig.broadcast();
}
--enqueue_waiters;
return true;
}
// ----------------------------------------------------------------------------------------
template <
typename T
>
bool pipe<T>::
dequeue_or_timeout (
T& item,
unsigned long timeout
)
{
auto_mutex M(m);
++dequeue_waiters;
if (pipe_size == 0)
{
// notify wait_for_num_blocked_dequeues()
if (unblock_sig_waiters > 0)
unblock_sig.broadcast();
// notify any blocked enqueue_or_timeout() calls
if (enqueue_waiters > 0)
enqueue_sig.broadcast();
}
bool timed_out = false;
// wait until there is something in the pipe or we are disabled or we timeout.
while (pipe_size == 0 && enabled && dequeue_enabled &&
!(pipe_max_size == 0 && first == 0 && last == 0) )
{
if (timeout == 0 || dequeue_sig.wait_or_timeout(timeout) == false)
{
timed_out = true;
break;
}
}
if (enabled == false || timed_out || dequeue_enabled == false)
{
--dequeue_waiters;
// let the destructor know we are unblocking
unblock_sig.broadcast();
return false;
}
exchange(item,data[first]);
if (pipe_max_size > 0)
{
// set the appropriate values for first
first = (first+1)%pipe_max_size;
--pipe_size;
}
else
{
// let the enqueue waiting on us know that we took the
// item out already.
last = 1;
}
// wake up a call to enqueue() if there are any currently blocked
if (enqueue_waiters > 0)
enqueue_sig.broadcast();
--dequeue_waiters;
return true;
}
// ----------------------------------------------------------------------------------------
template <
typename T
>
void pipe<T>::
wait_for_num_blocked_dequeues (
unsigned long num
)const
{
auto_mutex M(m);
++unblock_sig_waiters;
while ( (dequeue_waiters < num || pipe_size != 0) && enabled && dequeue_enabled)
unblock_sig.wait();
// let the destructor know we are ending if it is blocked waiting
if (enabled == false)
unblock_sig.broadcast();
--unblock_sig_waiters;
}
// ----------------------------------------------------------------------------------------
template <
typename T
>
bool pipe<T>::
is_enqueue_enabled (
) const
{
auto_mutex M(m);
return enqueue_enabled;
}
// ----------------------------------------------------------------------------------------
template <
typename T
>
void pipe<T>::
disable_enqueue (
)
{
auto_mutex M(m);
enqueue_enabled = false;
enqueue_sig.broadcast();
}
// ----------------------------------------------------------------------------------------
template <
typename T
>
void pipe<T>::
enable_enqueue (
)
{
auto_mutex M(m);
enqueue_enabled = true;
}
// ----------------------------------------------------------------------------------------
template <
typename T
>
bool pipe<T>::
is_dequeue_enabled (
) const
{
auto_mutex M(m);
return dequeue_enabled;
}
// ----------------------------------------------------------------------------------------
template <
typename T
>
void pipe<T>::
disable_dequeue (
)
{
auto_mutex M(m);
dequeue_enabled = false;
dequeue_sig.broadcast();
}
// ----------------------------------------------------------------------------------------
template <
typename T
>
void pipe<T>::
enable_dequeue (
)
{
auto_mutex M(m);
dequeue_enabled = true;
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_PIPE_KERNEl_1_

View File

@@ -0,0 +1,323 @@
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_PIPE_KERNEl_ABSTRACT_
#ifdef DLIB_PIPE_KERNEl_ABSTRACT_
#include "../threads.h"
namespace dlib
{
template <
typename T
>
class pipe
{
/*!
REQUIREMENTS ON T
T must be swappable by a global swap()
T must have a default constructor
INITIAL VALUE
size() == 0
is_enabled() == true
is_enqueue_enabled() == true
is_dequeue_enabled() == true
WHAT THIS OBJECT REPRESENTS
This is a first in first out queue with a fixed maximum size containing
items of type T. It is suitable for passing objects between threads.
THREAD SAFETY
All methods of this class are thread safe. You may call them from any
thread and any number of threads my call them at once.
!*/
public:
typedef T type;
explicit pipe (
size_t maximum_size
);
/*!
ensures
- #*this is properly initialized
- #max_size() == maximum_size
throws
- std::bad_alloc
- dlib::thread_error
!*/
virtual ~pipe (
);
/*!
ensures
- any resources associated with *this have been released
- disables (i.e. sets is_enabled() == false) this object so that
all calls currently blocking on it will return immediately.
!*/
void enable (
);
/*!
ensures
- #is_enabled() == true
!*/
void disable (
);
/*!
ensures
- #is_enabled() == false
- causes all current and future calls to enqueue(), dequeue(),
enqueue_or_timeout() and dequeue_or_timeout() to not block but
to return false immediately until enable() is called.
- causes all current and future calls to wait_until_empty() and
wait_for_num_blocked_dequeues() to not block but return
immediately until enable() is called.
!*/
bool is_enabled (
) const;
/*!
ensures
- returns true if this pipe is currently enabled, false otherwise.
!*/
void empty (
);
/*!
ensures
- #size() == 0
!*/
void wait_until_empty (
) const;
/*!
ensures
- blocks until one of the following is the case:
- size() == 0
- is_enabled() == false
- is_dequeue_enabled() == false
!*/
void wait_for_num_blocked_dequeues (
unsigned long num
) const;
/*!
ensures
- blocks until one of the following is the case:
- size() == 0 and the number of threads blocked on calls
to dequeue() and dequeue_or_timeout() is greater than
or equal to num.
- is_enabled() == false
- is_dequeue_enabled() == false
!*/
bool is_enqueue_enabled (
) const;
/*!
ensures
- returns true if the enqueue() and enqueue_or_timeout() functions are
currently enabled, returns false otherwise. (note that the higher
level is_enabled() function can overrule this one. So if
is_enabled() == false then enqueue functions are still disabled even
if is_enqueue_enabled() returns true. But if is_enqueue_enabled() == false
then enqueue functions are always disabled no matter the state of
is_enabled())
!*/
void disable_enqueue (
);
/*!
ensures
- #is_enqueue_enabled() == false
- causes all current and future calls to enqueue() and
enqueue_or_timeout() to not block but to return false
immediately until enable_enqueue() is called.
!*/
void enable_enqueue (
);
/*!
ensures
- #is_enqueue_enabled() == true
!*/
bool is_dequeue_enabled (
) const;
/*!
ensures
- returns true if the dequeue() and dequeue_or_timeout() functions are
currently enabled, returns false otherwise. (note that the higher
level is_enabled() function can overrule this one. So if
is_enabled() == false then dequeue functions are still disabled even
if is_dequeue_enabled() returns true. But if is_dequeue_enabled() == false
then dequeue functions are always disabled no matter the state of
is_enabled())
!*/
void disable_dequeue (
);
/*!
ensures
- #is_dequeue_enabled() == false
- causes all current and future calls to dequeue() and
dequeue_or_timeout() to not block but to return false
immediately until enable_dequeue() is called.
!*/
void enable_dequeue (
);
/*!
ensures
- #is_dequeue_enabled() == true
!*/
size_t max_size (
) const;
/*!
ensures
- returns the maximum number of objects of type T that this
pipe can contain.
!*/
size_t size (
) const;
/*!
ensures
- returns the number of objects of type T that this
object currently contains.
!*/
bool enqueue (
T& item
);
/*!
ensures
- if (size() == max_size()) then
- this call to enqueue() blocks until one of the following is the case:
- there is room in the pipe for another item
- max_size() == 0 and another thread is trying to dequeue from this
pipe and we can pass our item object directly to that thread.
- someone calls disable()
- someone calls disable_enqueue()
- else
- this call does not block.
- if (this call to enqueue() returns true) then
- #is_enabled() == true
- #is_enqueue_enabled() == true
- if (max_size() == 0) then
- using global swap, item was passed directly to a
thread attempting to dequeue from this pipe
- else
- using global swap, item was added into this pipe.
- #item is in an undefined but valid state for its type
- else
- item was NOT added into the pipe
- #item == item (i.e. the value of item is unchanged)
!*/
bool enqueue (T&& item) { return enqueue(item); }
/*!
enable enqueueing from rvalues
!*/
bool enqueue_or_timeout (
T& item,
unsigned long timeout
);
/*!
ensures
- if (size() == max_size() && timeout > 0) then
- this call to enqueue_or_timeout() blocks until one of the following is the case:
- there is room in the pipe to add another item
- max_size() == 0 and another thread is trying to dequeue from this pipe
and we can pass our item object directly to that thread.
- someone calls disable()
- someone calls disable_enqueue()
- timeout milliseconds passes
- else
- this call does not block.
- if (this call to enqueue() returns true) then
- #is_enabled() == true
- #is_enqueue_enabled() == true
- if (max_size() == 0) then
- using global swap, item was passed directly to a
thread attempting to dequeue from this pipe
- else
- using global swap, item was added into this pipe.
- #item is in an undefined but valid state for its type
- else
- item was NOT added into the pipe
- #item == item (i.e. the value of item is unchanged)
!*/
bool enqueue_or_timeout (T&& item, unsigned long timeout) { return enqueue_or_timeout(item,timeout); }
/*!
enable enqueueing from rvalues
!*/
bool dequeue (
T& item
);
/*!
ensures
- if (size() == 0) then
- this call to dequeue() blocks until one of the following is the case:
- there is something in the pipe we can dequeue
- max_size() == 0 and another thread is trying to enqueue an item
onto this pipe and we can receive our item directly from that thread.
- someone calls disable()
- someone calls disable_dequeue()
- else
- this call does not block.
- if (this call to dequeue() returns true) then
- #is_enabled() == true
- #is_dequeue_enabled() == true
- the oldest item that was enqueued into this pipe has been
swapped into #item.
- else
- nothing was dequeued from this pipe.
- #item == item (i.e. the value of item is unchanged)
!*/
bool dequeue_or_timeout (
T& item,
unsigned long timeout
);
/*!
ensures
- if (size() == 0 && timeout > 0) then
- this call to dequeue_or_timeout() blocks until one of the following is the case:
- there is something in the pipe we can dequeue
- max_size() == 0 and another thread is trying to enqueue an item onto this
pipe and we can receive our item directly from that thread.
- someone calls disable()
- someone calls disable_dequeue()
- timeout milliseconds passes
- else
- this call does not block.
- if (this call to dequeue_or_timeout() returns true) then
- #is_enabled() == true
- #is_dequeue_enabled() == true
- the oldest item that was enqueued into this pipe has been
swapped into #item.
- else
- nothing was dequeued from this pipe.
- #item == item (i.e. the value of item is unchanged)
!*/
private:
// restricted functions
pipe(const pipe&); // copy constructor
pipe& operator=(const pipe&); // assignment operator
};
}
#endif // DLIB_PIPE_KERNEl_ABSTRACT_

View File

@@ -0,0 +1,65 @@
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifdef DLIB_ALL_SOURCE_END
#include "dlib_basic_cpp_build_tutorial.txt"
#endif
#ifndef DLIB_PLATFORm_
#define DLIB_PLATFORm_
/*!
This file ensures that:
- if (we are compiling under a posix platform) then
- DLIB_POSIX will be defined
- if (this is also Mac OS X) then
- MACOSX will be defined
- if (this is also HP-UX) then
- HPUX will be defined
- if (we are compiling under an MS Windows platform) then
- WIN32 will be defined
!*/
/*
A good reference for this sort of information is
http://predef.sourceforge.net/
*/
// Define WIN32 if this is MS Windows
#ifndef WIN32
#if defined( _MSC_VER) || defined(__BORLANDC__) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__)
#define WIN32
#endif
#endif
#ifndef WIN32
// since this is the only other platform the library currently supports
// just assume it is DLIB_POSIX if it isn't WIN32
#ifndef DLIB_POSIX
#define DLIB_POSIX
#endif
#ifndef HPUX
#if defined(__hpux ) || defined(hpux) || defined (_hpux)
#define HPUX
#endif
#endif
#ifndef MACOSX
#ifdef __MACOSX__
#define MACOSX
#endif
#ifdef __APPLE__
#define MACOSX
#endif
#endif
#endif
#endif // DLIB_PLATFORm_

View File

@@ -0,0 +1,84 @@
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_QUEUe_
#define DLIB_QUEUe_
#include "queue/queue_kernel_1.h"
#include "queue/queue_kernel_2.h"
#include "queue/queue_kernel_c.h"
#include "queue/queue_sort_1.h"
#include "algs.h"
namespace dlib
{
template <
typename T,
typename mem_manager = default_memory_manager
>
class queue
{
queue() {}
public:
//----------- kernels ---------------
// kernel_1a
typedef queue_kernel_1<T,mem_manager>
kernel_1a;
typedef queue_kernel_c<kernel_1a>
kernel_1a_c;
// kernel_2a
typedef queue_kernel_2<T,20,mem_manager>
kernel_2a;
typedef queue_kernel_c<kernel_2a>
kernel_2a_c;
// kernel_2b
typedef queue_kernel_2<T,100,mem_manager>
kernel_2b;
typedef queue_kernel_c<kernel_2b>
kernel_2b_c;
//---------- extensions ------------
// sort_1 extend kernel_1a
typedef queue_sort_1<kernel_1a>
sort_1a;
typedef queue_sort_1<kernel_1a_c>
sort_1a_c;
// sort_1 extend kernel_2a
typedef queue_sort_1<kernel_2a>
sort_1b;
typedef queue_sort_1<kernel_2a_c>
sort_1b_c;
// sort_1 extend kernel_2b
typedef queue_sort_1<kernel_2b>
sort_1c;
typedef queue_sort_1<kernel_2b_c>
sort_1c_c;
};
}
#endif // DLIB_QUEUe_

View File

@@ -0,0 +1,554 @@
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_QUEUE_KERNEl_1_
#define DLIB_QUEUE_KERNEl_1_
#include "queue_kernel_abstract.h"
#include "../algs.h"
#include "../interfaces/enumerable.h"
#include "../interfaces/remover.h"
#include "../serialize.h"
namespace dlib
{
template <
typename T,
typename mem_manager = default_memory_manager
>
class queue_kernel_1 : public enumerable<T>,
public remover<T>
{
/*!
INITIAL VALUE
queue_size == 0
current_element == 0
at_start_ == true
CONVENTION
queue_size == the number of elements in the queue
at_start() == at_start_
current_element_valid() == (current_element != 0)
element() == current_element->item
if (queue_size > 0)
{
in points to the last element to be inserted into the queue
out points to the next element to be dequeued
each node points to the node inserted after it except for the most
recently inserted node
current_element == 0
}
!*/
struct node
{
node* last;
T item;
};
public:
typedef T type;
typedef mem_manager mem_manager_type;
queue_kernel_1 (
) :
in(0),
out(0),
queue_size(0),
current_element(0),
at_start_(true)
{
}
virtual ~queue_kernel_1 (
);
inline void clear(
);
void enqueue (
T& item
);
void dequeue (
T& item
);
void cat (
queue_kernel_1& item
);
T& current (
);
const T& current (
) const;
void swap (
queue_kernel_1& item
);
// functions from the remover interface
inline void remove_any (
T& item
);
// functions from the enumerable interface
inline size_t size (
) const;
inline bool at_start (
) const;
inline void reset (
) const;
bool current_element_valid (
) const;
inline const T& element (
) const;
inline T& element (
);
bool move_next (
) const;
private:
void delete_nodes (
node* start,
unsigned long length
);
/*!
requires
- start points to a node in a singly linked list
- start->last points to the next node in the list
- there are at least length nodes in the list beginning with start
ensures
- length nodes have been deleted starting with the node pointed
to by start
!*/
// data members
node* in;
node* out;
unsigned long queue_size;
mutable node* current_element;
mutable bool at_start_;
// restricted functions
queue_kernel_1(queue_kernel_1&); // copy constructor
queue_kernel_1& operator=(queue_kernel_1&); // assignment operator
};
template <
typename T,
typename mem_manager
>
inline void swap (
queue_kernel_1<T,mem_manager>& a,
queue_kernel_1<T,mem_manager>& b
) { a.swap(b); }
template <
typename T,
typename mem_manager
>
void deserialize (
queue_kernel_1<T,mem_manager>& item,
std::istream& in
)
{
try
{
item.clear();
unsigned long size;
deserialize(size,in);
T temp;
for (unsigned long i = 0; i < size; ++i)
{
deserialize(temp,in);
item.enqueue(temp);
}
}
catch (serialization_error& e)
{
item.clear();
throw serialization_error(e.info + "\n while deserializing object of type queue_kernel_1");
}
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
queue_kernel_1<T,mem_manager>::
~queue_kernel_1 (
)
{
delete_nodes(out,queue_size);
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
void queue_kernel_1<T,mem_manager>::
clear (
)
{
delete_nodes(out,queue_size);
queue_size = 0;
// put the enumerator at the start
reset();
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
void queue_kernel_1<T,mem_manager>::
enqueue (
T& item
)
{
// make new node
node* temp = new node;
// swap item into new node
exchange(item,temp->item);
if (queue_size == 0)
out = temp;
else
in->last = temp;
// make in point to the new node
in = temp;
++queue_size;
// put the enumerator at the start
reset();
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
void queue_kernel_1<T,mem_manager>::
dequeue (
T& item
)
{
// swap out into item
exchange(item,out->item);
--queue_size;
if (queue_size == 0)
{
delete out;
}
else
{
node* temp = out;
// move out pointer to the next element in the queue
out = out->last;
// delete old node
delete temp;
}
// put the enumerator at the start
reset();
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
void queue_kernel_1<T,mem_manager>::
cat (
queue_kernel_1<T,mem_manager>& item
)
{
if (item.queue_size > 0)
{
if (queue_size > 0)
{
in->last = item.out;
}
else
{
out = item.out;
}
in = item.in;
queue_size += item.queue_size;
item.queue_size = 0;
}
// put the enumerator at the start
reset();
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
T& queue_kernel_1<T,mem_manager>::
current (
)
{
return out->item;
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
const T& queue_kernel_1<T,mem_manager>::
current (
) const
{
return out->item;
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
void queue_kernel_1<T,mem_manager>::
swap (
queue_kernel_1<T,mem_manager>& item
)
{
node* in_temp = in;
node* out_temp = out;
unsigned long queue_size_temp = queue_size;
node* current_element_temp = current_element;
bool at_start_temp = at_start_;
in = item.in;
out = item.out;
queue_size = item.queue_size;
current_element = item.current_element;
at_start_ = item.at_start_;
item.in = in_temp;
item.out = out_temp;
item.queue_size = queue_size_temp;
item.current_element = current_element_temp;
item.at_start_ = at_start_temp;
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// enumerable function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
bool queue_kernel_1<T,mem_manager>::
at_start (
) const
{
return at_start_;
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
size_t queue_kernel_1<T,mem_manager>::
size (
) const
{
return queue_size;
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
void queue_kernel_1<T,mem_manager>::
reset (
) const
{
at_start_ = true;
current_element = 0;
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
bool queue_kernel_1<T,mem_manager>::
current_element_valid (
) const
{
return (current_element != 0);
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
const T& queue_kernel_1<T,mem_manager>::
element (
) const
{
return current_element->item;
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
T& queue_kernel_1<T,mem_manager>::
element (
)
{
return current_element->item;
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
bool queue_kernel_1<T,mem_manager>::
move_next (
) const
{
if (at_start_)
{
at_start_ = false;
// if the queue is empty then there is nothing to do
if (queue_size == 0)
{
return false;
}
else
{
current_element = out;
return true;
}
}
else
{
// if we are at the last element then the enumeration has finished
if (current_element == in || current_element == 0)
{
current_element = 0;
return false;
}
else
{
current_element = current_element->last;
return true;
}
}
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// remover function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
void queue_kernel_1<T,mem_manager>::
remove_any (
T& item
)
{
dequeue(item);
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// private member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
void queue_kernel_1<T,mem_manager>::
delete_nodes (
node* start,
unsigned long length
)
{
node* temp;
while (length)
{
temp = start->last;
delete start;
start = temp;
--length;
}
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_QUEUE_KERNEl_1_

View File

@@ -0,0 +1,600 @@
// Copyright (C) 2004 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_QUEUE_KERNEl_2_
#define DLIB_QUEUE_KERNEl_2_
#include "queue_kernel_abstract.h"
#include "../algs.h"
#include "../assert.h"
#include "../interfaces/enumerable.h"
#include "../interfaces/remover.h"
#include "../serialize.h"
namespace dlib
{
template <
typename T,
unsigned long block_size,
typename mem_manager = default_memory_manager
>
class queue_kernel_2 : public enumerable<T>,
public remover<T>
{
/*!
REQUIREMENTS ON block_size
0 < block_size < 2000000000
INITIAL VALUE
queue_size == 0
current_element == 0
at_start_ == true
CONVENTION
queue_size == the number of elements in the queue
at_start() == at_start_
current_element_valid() == (current_element != 0)
if (current_element_valid()) then
element() == current_element->item[current_element_pos]
if (queue_size > 0)
{
in->item[in_pos] == the spot where we will put the next item added
into the queue
out->item[out_pos] == current()
when enqueuing elements inside each node item[0] is filled first, then
item[1], then item[2], etc.
each node points to the node inserted after it except for the most
recently inserted node.
}
!*/
struct node
{
node* next;
T item[block_size];
};
public:
typedef T type;
typedef mem_manager mem_manager_type;
queue_kernel_2 (
) :
in(0),
out(0),
queue_size(0),
current_element(0),
at_start_(true)
{
}
virtual ~queue_kernel_2 (
);
inline void clear(
);
void enqueue (
T& item
);
void dequeue (
T& item
);
void cat (
queue_kernel_2& item
);
T& current (
);
const T& current (
) const;
void swap (
queue_kernel_2& item
);
// functions from the remover interface
inline void remove_any (
T& item
);
// functions from the enumerable interface
inline size_t size (
) const;
inline bool at_start (
) const;
inline void reset (
) const;
bool current_element_valid (
) const;
inline const T& element (
) const;
inline T& element (
);
bool move_next (
) const;
private:
void delete_nodes (
node* start,
node* end
);
/*!
requires
- start points to a node in a singly linked list
- start->next points to the next node in the list
- by following the next pointers you eventually hit the node pointed
to by end
ensures
- calls delete on the start node, the end node, and all nodes in between
!*/
// data members
typename mem_manager::template rebind<node>::other pool;
node* in;
node* out;
size_t queue_size;
size_t in_pos;
size_t out_pos;
mutable node* current_element;
mutable size_t current_element_pos;
mutable bool at_start_;
// restricted functions
queue_kernel_2(queue_kernel_2&); // copy constructor
queue_kernel_2& operator=(queue_kernel_2&); // assignment operator
};
template <
typename T,
unsigned long block_size,
typename mem_manager
>
inline void swap (
queue_kernel_2<T,block_size,mem_manager>& a,
queue_kernel_2<T,block_size,mem_manager>& b
) { a.swap(b); }
template <
typename T,
unsigned long block_size,
typename mem_manager
>
void deserialize (
queue_kernel_2<T,block_size,mem_manager>& item,
std::istream& in
)
{
try
{
item.clear();
unsigned long size;
deserialize(size,in);
T temp;
for (unsigned long i = 0; i < size; ++i)
{
deserialize(temp,in);
item.enqueue(temp);
}
}
catch (serialization_error& e)
{
item.clear();
throw serialization_error(e.info + "\n while deserializing object of type queue_kernel_2");
}
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename T,
unsigned long block_size,
typename mem_manager
>
queue_kernel_2<T,block_size,mem_manager>::
~queue_kernel_2 (
)
{
COMPILE_TIME_ASSERT(0 < block_size && block_size < (unsigned long)(2000000000));
if (queue_size > 0)
delete_nodes(out,in);
}
// ----------------------------------------------------------------------------------------
template <
typename T,
unsigned long block_size,
typename mem_manager
>
void queue_kernel_2<T,block_size,mem_manager>::
clear (
)
{
if (queue_size > 0)
{
delete_nodes(out,in);
queue_size = 0;
}
// put the enumerator at the start
reset();
}
// ----------------------------------------------------------------------------------------
template <
typename T,
unsigned long block_size,
typename mem_manager
>
void queue_kernel_2<T,block_size,mem_manager>::
enqueue (
T& item
)
{
if (queue_size == 0)
{
out = in = pool.allocate();
in_pos = 0;
out_pos = 0;
}
else if (in_pos >= block_size)
{
in->next = pool.allocate();
in_pos = 0;
in = in->next;
}
exchange(item,in->item[in_pos]);
++in_pos;
++queue_size;
// put the enumerator at the start
reset();
}
// ----------------------------------------------------------------------------------------
template <
typename T,
unsigned long block_size,
typename mem_manager
>
void queue_kernel_2<T,block_size,mem_manager>::
dequeue (
T& item
)
{
// swap out into item
exchange(item,out->item[out_pos]);
++out_pos;
--queue_size;
// if this was the last element in this node then remove this node
if (out_pos == block_size)
{
out_pos = 0;
node* temp = out;
out = out->next;
pool.deallocate(temp);
}
else if (queue_size == 0)
{
pool.deallocate(out);
}
// put the enumerator at the start
reset();
}
// ----------------------------------------------------------------------------------------
template <
typename T,
unsigned long block_size,
typename mem_manager
>
void queue_kernel_2<T,block_size,mem_manager>::
cat (
queue_kernel_2<T,block_size,mem_manager>& item
)
{
if (queue_size > 0)
{
T temp;
assign_zero_if_built_in_scalar_type(temp);
while (item.size() > 0)
{
item.dequeue(temp);
enqueue(temp);
}
}
else
{
in = item.in;
out = item.out;
out_pos = item.out_pos;
in_pos = item.in_pos;
queue_size = item.queue_size;
item.queue_size = 0;
// put the enumerator at the start
reset();
}
}
// ----------------------------------------------------------------------------------------
template <
typename T,
unsigned long block_size,
typename mem_manager
>
T& queue_kernel_2<T,block_size,mem_manager>::
current (
)
{
return out->item[out_pos];
}
// ----------------------------------------------------------------------------------------
template <
typename T,
unsigned long block_size,
typename mem_manager
>
const T& queue_kernel_2<T,block_size,mem_manager>::
current (
) const
{
return out->item[out_pos];
}
// ----------------------------------------------------------------------------------------
template <
typename T,
unsigned long block_size,
typename mem_manager
>
void queue_kernel_2<T,block_size,mem_manager>::
swap (
queue_kernel_2<T,block_size,mem_manager>& item
)
{
exchange(in,item.in);
exchange(out,item.out);
exchange(queue_size,item.queue_size);
exchange(in_pos,item.in_pos);
exchange(out_pos,item.out_pos);
exchange(current_element,item.current_element);
exchange(current_element_pos,item.current_element_pos);
exchange(at_start_,item.at_start_);
pool.swap(item.pool);
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// enumerable function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename T,
unsigned long block_size,
typename mem_manager
>
size_t queue_kernel_2<T,block_size,mem_manager>::
size (
) const
{
return queue_size;
}
// ----------------------------------------------------------------------------------------
template <
typename T,
unsigned long block_size,
typename mem_manager
>
bool queue_kernel_2<T,block_size,mem_manager>::
at_start (
) const
{
return at_start_;
}
// ----------------------------------------------------------------------------------------
template <
typename T,
unsigned long block_size,
typename mem_manager
>
void queue_kernel_2<T,block_size,mem_manager>::
reset (
) const
{
at_start_ = true;
current_element = 0;
}
// ----------------------------------------------------------------------------------------
template <
typename T,
unsigned long block_size,
typename mem_manager
>
bool queue_kernel_2<T,block_size,mem_manager>::
current_element_valid (
) const
{
return (current_element != 0);
}
// ----------------------------------------------------------------------------------------
template <
typename T,
unsigned long block_size,
typename mem_manager
>
const T& queue_kernel_2<T,block_size,mem_manager>::
element (
) const
{
return current_element->item[current_element_pos];
}
// ----------------------------------------------------------------------------------------
template <
typename T,
unsigned long block_size,
typename mem_manager
>
T& queue_kernel_2<T,block_size,mem_manager>::
element (
)
{
return current_element->item[current_element_pos];
}
// ----------------------------------------------------------------------------------------
template <
typename T,
unsigned long block_size,
typename mem_manager
>
bool queue_kernel_2<T,block_size,mem_manager>::
move_next (
) const
{
if (at_start_)
{
at_start_ = false;
// if the queue is empty then there is nothing to do
if (queue_size == 0)
{
return false;
}
else
{
current_element = out;
current_element_pos = out_pos;
return true;
}
}
else if (current_element == 0)
{
return false;
}
else
{
++current_element_pos;
// if we are at the last element then the enumeration has finished
if (current_element == in && current_element_pos == in_pos )
{
current_element = 0;
return false;
}
else if (current_element_pos == block_size)
{
current_element_pos = 0;
current_element = current_element->next;
}
return true;
}
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// remover function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename T,
unsigned long block_size,
typename mem_manager
>
void queue_kernel_2<T,block_size,mem_manager>::
remove_any (
T& item
)
{
dequeue(item);
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// private member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename T,
unsigned long block_size,
typename mem_manager
>
void queue_kernel_2<T,block_size,mem_manager>::
delete_nodes (
node* start,
node* end
)
{
node* temp;
while (start != end)
{
temp = start;
start = start->next;
pool.deallocate(temp);
}
pool.deallocate(start);
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_QUEUE_KERNEl_2_

View File

@@ -0,0 +1,196 @@
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_QUEUE_KERNEl_ABSTRACT_
#ifdef DLIB_QUEUE_KERNEl_ABSTRACT_
#include "../interfaces/enumerable.h"
#include "../interfaces/remover.h"
#include "../serialize.h"
#include "../algs.h"
namespace dlib
{
template <
typename T,
typename mem_manager = default_memory_manager
>
class queue : public enumerable<T>,
public remover<T>
{
/*!
REQUIREMENTS ON T
T must be swappable by a global swap()
T must have a default constructor
REQUIREMENTS ON mem_manager
must be an implementation of memory_manager/memory_manager_kernel_abstract.h or
must be an implementation of memory_manager_global/memory_manager_global_kernel_abstract.h or
must be an implementation of memory_manager_stateless/memory_manager_stateless_kernel_abstract.h
mem_manager::type can be set to anything.
POINTERS AND REFERENCES TO INTERNAL DATA
swap() and current() functions do not invalidate pointers or
references to internal data.
All other functions have no such guarantee.
INITIAL VALUE
size() == 0
ENUMERATION ORDER
The enumerator will iterate over the elements in the queue in the
same order they would be removed by repeated calls to dequeue().
(e.g. current() would be the first element enumerated)
WHAT THIS OBJECT REPRESENTS
This is a first in first out queue containing items of type T
e.g. if the queue is {b,c,d,e} and then 'a' is enqueued
the queue becomes {a,b,c,d,e} and then calling dequeue takes e out
making the queue {a,b,c,d}
Also note that unless specified otherwise, no member functions
of this object throw exceptions.
!*/
public:
typedef T type;
typedef mem_manager mem_manager_type;
queue (
);
/*!
ensures
- #*this is properly initialized
throws
- std::bad_alloc or any exception thrown by T's constructor
!*/
virtual ~queue (
);
/*!
ensures
- all memory associated with *this has been released
!*/
void clear(
);
/*!
ensures
- #*this has its initial value
throws
- std::bad_alloc or any exception thrown by T's constructor
if this exception is thrown then *this is unusable
until clear() is called and succeeds
!*/
void enqueue (
T& item
);
/*!
ensures
- item is now at the left end of #*this
- #item has an initial value for its type
- #size() == size() + 1
- #at_start() == true
throws
- std::bad_alloc or any exception thrown by T's constructor
if enqueue() throws then it has no effect
!*/
void dequeue (
T& item
);
/*!
requires
- size() != 0
ensures
- #size() == size() - 1
- the far right element of *this has been removed and swapped
into #item
- #at_start() == true
!*/
void cat (
queue& item
);
/*!
ensures
- item has been concatenated onto the left end of *this.
i.e. item.current() is attached onto the left end of *this and
the left most element in item will also be the left most item
in #*this
- #size() == size() + item.size()
- #item has its initial value
- #at_start() == true
throws
- std::bad_alloc or any exception thrown by T's constructor
if cat() throws then the state of #item and *this is undefined
until clear() is successfully called on them.
!*/
T& current (
);
/*!
requires
- size() != 0
ensures
- returns a const reference to the next element to be dequeued.
i.e. the right most element.
!*/
const T& current (
) const;
/*!
requires
- size() != 0
ensures
- returns a non-const reference to the next element to be dequeued.
i.e. the right most element.
!*/
void swap (
queue& item
);
/*!
ensures
- swaps *this and item
!*/
private:
// restricted functions
queue(queue&); // copy constructor
queue& operator=(queue&); // assignment operator
};
template <
typename T,
typename mem_manager
>
inline void swap (
queue<T,mem_manager>& a,
queue<T,mem_manager>& b
) { a.swap(b); }
/*!
provides a global swap function
!*/
template <
typename T,
typename mem_manager
>
void deserialize (
queue<T,mem_manager>& item,
std::istream& in
);
/*!
provides deserialization support
!*/
}
#endif // DLIB_QUEUE_KERNEl_ABSTRACT_

View File

@@ -0,0 +1,187 @@
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_QUEUE_KERNEl_C_
#define DLIB_QUEUE_KERNEl_C_
#include "queue_kernel_abstract.h"
#include "../algs.h"
#include "../assert.h"
namespace dlib
{
template <
typename queue_base // is an implementation of queue_kernel_abstract.h
>
class queue_kernel_c : public queue_base
{
typedef typename queue_base::type T;
public:
void dequeue (
T& item
);
T& current (
);
const T& current (
) const;
const T& element (
) const;
T& element (
);
void remove_any (
T& item
);
};
template <
typename queue_base
>
inline void swap (
queue_kernel_c<queue_base>& a,
queue_kernel_c<queue_base>& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename queue_base
>
void queue_kernel_c<queue_base>::
dequeue (
T& item
)
{
// make sure requires clause is not broken
DLIB_CASSERT(this->size() != 0,
"\tvoid queue::dequeue"
<< "\n\tsize of queue should not be zero"
<< "\n\tthis: " << this
);
// call the real function
queue_base::dequeue(item);
}
// ----------------------------------------------------------------------------------------
template <
typename queue_base
>
const typename queue_base::type& queue_kernel_c<queue_base>::
current (
) const
{
// make sure requires clause is not broken
DLIB_CASSERT(this->size() != 0,
"\tconst T& queue::current"
<< "\n\tsize of queue should not be zero"
<< "\n\tthis: " << this
);
// call the real function
return queue_base::current();
}
// ----------------------------------------------------------------------------------------
template <
typename queue_base
>
typename queue_base::type& queue_kernel_c<queue_base>::
current (
)
{
// make sure requires clause is not broken
DLIB_CASSERT(this->size() != 0,
"\tT& queue::current"
<< "\n\tsize of queue should not be zero"
<< "\n\tthis: " << this
);
// call the real function
return queue_base::current();
}
// ----------------------------------------------------------------------------------------
template <
typename queue_base
>
const typename queue_base::type& queue_kernel_c<queue_base>::
element (
) const
{
// make sure requires clause is not broken
DLIB_CASSERT(this->current_element_valid() == true,
"\tconst T& queue::element"
<< "\n\tyou can't access the current element if it doesn't exist"
<< "\n\tthis: " << this
);
// call the real function
return queue_base::element();
}
// ----------------------------------------------------------------------------------------
template <
typename queue_base
>
typename queue_base::type& queue_kernel_c<queue_base>::
element (
)
{
// make sure requires clause is not broken
DLIB_CASSERT(this->current_element_valid() == true,
"\tT& queue::element"
<< "\n\tyou can't access the current element if it doesn't exist"
<< "\n\tthis: " << this
);
// call the real function
return queue_base::element();
}
// ----------------------------------------------------------------------------------------
template <
typename queue_base
>
void queue_kernel_c<queue_base>::
remove_any (
T& item
)
{
// make sure requires clause is not broken
DLIB_CASSERT( (this->size() > 0),
"\tvoid queue::remove_any"
<< "\n\tsize() must be greater than zero if something is going to be removed"
<< "\n\tsize(): " << this->size()
<< "\n\tthis: " << this
);
// call the real function
queue_base::remove_any(item);
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_QUEUE_KERNEl_C_

View File

@@ -0,0 +1,165 @@
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_QUEUE_SORt_1_
#define DLIB_QUEUE_SORt_1_
#include "queue_sort_abstract.h"
#include "../algs.h"
#include <vector>
#include "../sort.h"
namespace dlib
{
template <
typename queue_base
>
class queue_sort_1 : public queue_base
{
typedef typename queue_base::type T;
public:
/*!
This implementation uses the QuickSort algorithm and
when the quicksort depth goes too high it uses the dlib::qsort_array()
function on the data.
!*/
void sort (
);
template <typename compare_type>
void sort (
const compare_type& compare
)
{
if (this->size() > 1)
{
sort_this_queue(*this,0,compare);
}
}
private:
template <typename compare_type>
void sort_this_queue (
queue_base& queue,
long depth,
const compare_type& compare
)
/*!
ensures
each element in the queue is < the element behind it according
to compare
!*/
{
if (queue.size() <= 1)
{
// already sorted
}
else if (queue.size() <= 29)
{
T vect[29];
const unsigned long size = queue.size();
for (unsigned long i = 0; i < size; ++i)
{
queue.dequeue(vect[i]);
}
isort_array(vect,0,size-1,compare);
for (unsigned long i = 0; i < size; ++i)
{
queue.enqueue(vect[i]);
}
}
else if (depth > 50)
{
std::vector<T> vect(queue.size());
for (unsigned long i = 0; i < vect.size(); ++i)
{
queue.dequeue(vect[i]);
}
hsort_array(vect,0,vect.size()-1,compare);
for (unsigned long i = 0; i < vect.size(); ++i)
{
queue.enqueue(vect[i]);
}
}
else
{
queue_base left, right;
T partition_element;
T temp;
// do this just to avoid a compiler warning
assign_zero_if_built_in_scalar_type(temp);
assign_zero_if_built_in_scalar_type(partition_element);
queue.dequeue(partition_element);
// partition queue into left and right
while (queue.size() > 0)
{
queue.dequeue(temp);
if (compare(temp , partition_element))
{
left.enqueue(temp);
}
else
{
right.enqueue(temp);
}
}
long ratio;
if (left.size() > right.size())
ratio = left.size()/(right.size()+1); // add 1 so we can't divide by zero
else
ratio = right.size()/(left.size()+1);
sort_this_queue(left,ratio+depth,compare);
sort_this_queue(right,ratio+depth,compare);
// combine the two queues
left.swap(queue);
queue.enqueue(partition_element);
queue.cat(right);
}
}
};
template <
typename queue_base
>
inline void swap (
queue_sort_1<queue_base>& a,
queue_sort_1<queue_base>& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename queue_base
>
void queue_sort_1<queue_base>::
sort (
)
{
if (this->size() > 1)
{
sort_this_queue(*this,0,std::less<typename queue_base::type>());
}
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_QUEUE_SORt_1_

View File

@@ -0,0 +1,74 @@
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_QUEUE_SORt_ABSTRACT_
#ifdef DLIB_QUEUE_SORt_ABSTRACT_
#include "queue_kernel_abstract.h"
namespace dlib
{
template <
typename queue_base
>
class queue_sort : public queue_base
{
/*!
REQUIREMENTS ON QUEUE_BASE
- is an implementation of queue/queue_kernel_abstract.h
- queue_base::type must be a type with that is comparable via operator<
POINTERS AND REFERENCES TO INTERNAL DATA
sort() may invalidate pointers and references to internal data.
WHAT THIS EXTENSION DOES FOR QUEUE
This gives a queue the ability to sort its contents by calling sort().
!*/
public:
void sort (
);
/*!
ensures
- for all elements in #*this the ith element is <= the i+1 element
- #at_start() == true
throws
- std::bad_alloc or any exception thrown by T's constructor
data may be lost if sort() throws
!*/
template <typename compare_type>
void sort (
const compare_type& compare
);
/*!
ensures
- for all elements in #*this the ith element is <= the i+1 element
- uses compare(a,b) as the < operator. So if compare(a,b) == true
then a comes before b in the resulting ordering.
- #at_start() == true
throws
- std::bad_alloc or any exception thrown by T's constructor
data may be lost if sort() throws
!*/
};
template <
template queue_base
>
inline void swap (
queue_sort<queue_base>& a,
queue_sort<queue_base>& b
) { a.swap(b); }
/*!
provides a global swap function
!*/
}
#endif // DLIB_QUEUE_SORt_ABSTRACT_

View File

@@ -0,0 +1,84 @@
// Copyright (C) 2010 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_REFERENCE_WRAPpER_H_
#define DLIB_REFERENCE_WRAPpER_H_
namespace dlib
{
// ----------------------------------------------------------------------------------------
template<
typename T
>
class reference_wrapper
{
/*!
WHAT THIS OBJECT REPRESENTS
This is a simple object that just holds a reference to another object.
It is useful because it can serve as a kind of "copyable reference".
!*/
public:
typedef T type;
explicit reference_wrapper(T& o) : obj(&o) {}
operator T&() const { return *obj; }
T& get() const { return *obj; }
private:
T* obj;
};
// ----------------------------------------------------------------------------------------
template <typename T>
reference_wrapper<T> ref(
T& obj
) { return reference_wrapper<T>(obj); }
/*!
ensures
- returns a reference_wrapper that contains a reference to obj.
!*/
// ----------------------------------------------------------------------------------------
template <typename T>
reference_wrapper<T> ref(
reference_wrapper<T> obj
) { return obj; }
/*!
ensures
- returns the given reference_wrapper object without modification
!*/
// ----------------------------------------------------------------------------------------
template <typename T>
reference_wrapper<const T> cref(
const T& obj
) { return reference_wrapper<const T>(obj); }
/*!
ensures
- returns a reference_wrapper that contains a constant reference to obj.
!*/
// ----------------------------------------------------------------------------------------
template <typename T>
reference_wrapper<const T> cref(
reference_wrapper<T> obj
) { return cref(obj.get()); }
/*!
ensures
- converts the given reference_wrapper into a reference_wrapper that contains a
constant reference.
!*/
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_REFERENCE_WRAPpER_H_

View File

@@ -0,0 +1,6 @@
#ifndef DLIB_REVISION_H
#define DLIB_MAJOR_VERSION 19
#define DLIB_MINOR_VERSION 21
#define DLIB_PATCH_VERSION 99
#endif

View File

@@ -0,0 +1,74 @@
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_SEt_
#define DLIB_SEt_
#include "set/set_kernel_1.h"
#include "set/set_kernel_c.h"
#include "binary_search_tree.h"
#include "set/set_compare_1.h"
#include "algs.h"
#include <functional>
namespace dlib
{
template <
typename T,
typename mem_manager = default_memory_manager,
typename compare = std::less<T>
>
class set
{
set() {}
typedef typename binary_search_tree<T,char,mem_manager,compare>::kernel_1a
binary_search_tree_1;
typedef typename binary_search_tree<T,char,mem_manager,compare>::kernel_2a
binary_search_tree_2;
public:
//----------- kernels ---------------
// kernel_1a
typedef set_kernel_1<T,binary_search_tree_1,mem_manager>
kernel_1a;
typedef set_kernel_c<kernel_1a>
kernel_1a_c;
// kernel_1b
typedef set_kernel_1<T,binary_search_tree_2,mem_manager>
kernel_1b;
typedef set_kernel_c<kernel_1b>
kernel_1b_c;
//---------- extensions ------------
// compare extensions
typedef set_compare_1<kernel_1a>
compare_1a;
typedef set_compare_1<kernel_1a_c>
compare_1a_c;
typedef set_compare_1<kernel_1b>
compare_1b;
typedef set_compare_1<kernel_1b_c>
compare_1b_c;
};
}
#endif // DLIB_SEt_

View File

@@ -0,0 +1,122 @@
// Copyright (C) 2005 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_SET_COMPARe_1_
#define DLIB_SET_COMPARe_1_
#include "set_compare_abstract.h"
#include "../algs.h"
namespace dlib
{
template <
typename set_base
>
class set_compare_1 : public set_base
{
public:
bool operator< (
const set_compare_1& rhs
) const;
bool operator== (
const set_compare_1& rhs
) const;
};
template <
typename set_base
>
inline void swap (
set_compare_1<set_base>& a,
set_compare_1<set_base>& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename set_base
>
bool set_compare_1<set_base>::
operator< (
const set_compare_1<set_base>& rhs
) const
{
bool result = false;
if (set_base::size() < rhs.size())
result = true;
if (set_base::size() == rhs.size())
{
rhs.reset();
set_base::reset();
while (rhs.move_next())
{
set_base::move_next();
if (set_base::element() < rhs.element())
{
result = true;
break;
}
else if (rhs.element() < set_base::element())
{
break;
}
}
}
set_base::reset();
rhs.reset();
return result;
}
// ----------------------------------------------------------------------------------------
template <
typename set_base
>
bool set_compare_1<set_base>::
operator== (
const set_compare_1<set_base>& rhs
) const
{
bool result = true;
if (set_base::size() != rhs.size())
result = false;
rhs.reset();
set_base::reset();
while (rhs.move_next() && set_base::move_next())
{
if (!(rhs.element() == set_base::element()))
{
result = false;
break;
}
}
set_base::reset();
rhs.reset();
return result;
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_SET_COMPARe_1_

View File

@@ -0,0 +1,96 @@
// Copyright (C) 2005 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_SET_COMPARe_ABSTRACT_
#ifdef DLIB_SET_COMPARe_ABSTRACT_
#include "set_kernel_abstract.h"
#include "../algs.h"
namespace dlib
{
template <
typename set_base
>
class set_compare : public set_base
{
/*!
REQUIREMENTS ON set_base
must be an implementation of set/set_kernel_abstract.h
POINTERS AND REFERENCES TO INTERNAL DATA
operator== and operator< invalidate pointers or references to
data members.
WHAT THIS EXTENSION DOES FOR set
This gives a set the ability to compare itself to other
sets using the < and == operators.
The < operator is conceptually weird for sets. It is useful
though because it allows you to make sets of sets since
sets require that their containing type implement operator<.
Also note that it is the case that for any two sets a and b
if (a<b) == false and (b<a) == false then a == b.
Also note that unless specified otherwise, no member functions
of this object throw exceptions.
NOTATION
For the purposes of defining what these operators do I will
use the operator[] to reference the elements of the sets.
operator[] is defined to access the elements of the set in
the same order they would be enumerated by the enumerable
interface.
!*/
public:
bool operator< (
const set_compare& rhs
) const;
/*!
ensures
- #at_start() == true
- if (size() < rhs.size()) then
- returns true
- else if (size() > rhs.size()) then
- returns false
- else
- returns true if there exists an integer j such that 0 <= j < size()
and for all integers i such that 0 <= i < j where it is true that
(*this)[i] == rhs[i] and (*this)[j] < rhs[j]
- returns false if there is no j that will satisfy the above conditions.
!*/
bool operator== (
const set_compare& rhs
) const;
/*!
ensures
- #at_start() == true
- returns true if *this and rhs contain the same elements.
returns false otherwise.
!*/
};
template <
typename set_base
>
inline void swap (
set_compare<set_base>& a,
set_compare<set_base>& b
) { a.swap(b); }
/*!
provides a global swap function
!*/
}
#endif // DLIB_SET_COMPARe_ABSTRACT_

View File

@@ -0,0 +1,372 @@
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_SET_KERNEl_1_
#define DLIB_SET_KERNEl_1_
#include "set_kernel_abstract.h"
#include "../algs.h"
#include "../interfaces/enumerable.h"
#include "../interfaces/remover.h"
#include "../serialize.h"
namespace dlib
{
template <
typename T,
typename bst_base,
typename mem_manager = default_memory_manager
>
class set_kernel_1 : public enumerable<const T>,
public asc_remover<T,typename bst_base::compare_type>
{
/*!
REQUIREMENTS ON bst_base
bst_base is instantiated with <domain=T,range=char> and
implements binray_search_tree/binary_search_tree_kernel_abstract.h
INITIAL VALUE
bst has its initial value
CONVENTION
bst.size() == the number of elements in the set and
the elements in the set are stored in bst
!*/
public:
typedef T type;
typedef typename bst_base::compare_type compare_type;
typedef mem_manager mem_manager_type;
set_kernel_1(
)
{
}
virtual ~set_kernel_1(
)
{}
inline void clear(
);
inline void add (
T& item
);
inline bool is_member (
const T& item
) const;
inline void remove (
const T& item,
T& item_copy
);
inline void destroy (
const T& item
);
inline void swap (
set_kernel_1& item
);
// functions from the remover interface
inline void remove_any (
T& item
);
// functions from the enumerable interface
inline size_t size (
) const;
inline bool at_start (
) const;
inline void reset (
) const;
inline bool current_element_valid (
) const;
inline const T& element (
) const;
inline const T& element (
);
inline bool move_next (
) const;
private:
bst_base bst;
char junk;
// restricted functions
set_kernel_1(set_kernel_1&);
set_kernel_1& operator=(set_kernel_1&);
};
template <
typename T,
typename bst_base,
typename mem_manager
>
inline void swap (
set_kernel_1<T,bst_base,mem_manager>& a,
set_kernel_1<T,bst_base,mem_manager>& b
) { a.swap(b); }
template <
typename T,
typename bst_base,
typename mem_manager
>
void deserialize (
set_kernel_1<T,bst_base,mem_manager>& item,
std::istream& in
)
{
try
{
item.clear();
unsigned long size;
deserialize(size,in);
T temp;
for (unsigned long i = 0; i < size; ++i)
{
deserialize(temp,in);
item.add(temp);
}
}
catch (serialization_error& e)
{
item.clear();
throw serialization_error(e.info + "\n while deserializing object of type set_kernel_1");
}
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename T,
typename bst_base,
typename mem_manager
>
void set_kernel_1<T,bst_base,mem_manager>::
clear (
)
{
bst.clear();
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename bst_base,
typename mem_manager
>
void set_kernel_1<T,bst_base,mem_manager>::
add (
T& item
)
{
bst.add(item,junk);
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename bst_base,
typename mem_manager
>
bool set_kernel_1<T,bst_base,mem_manager>::
is_member(
const T& item
) const
{
return (bst[item] != 0);
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename bst_base,
typename mem_manager
>
void set_kernel_1<T,bst_base,mem_manager>::
remove_any (
T& item
)
{
bst.remove_any(item,junk);
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename bst_base,
typename mem_manager
>
void set_kernel_1<T,bst_base,mem_manager>::
remove(
const T& item,
T& item_copy
)
{
bst.remove(item,item_copy,junk);
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename bst_base,
typename mem_manager
>
void set_kernel_1<T,bst_base,mem_manager>::
destroy(
const T& item
)
{
bst.destroy(item);
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename bst_base,
typename mem_manager
>
size_t set_kernel_1<T,bst_base,mem_manager>::
size (
) const
{
return bst.size();
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename bst_base,
typename mem_manager
>
void set_kernel_1<T,bst_base,mem_manager>::
swap (
set_kernel_1<T,bst_base,mem_manager>& item
)
{
bst.swap(item.bst);
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// enumerable function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename T,
typename bst_base,
typename mem_manager
>
bool set_kernel_1<T,bst_base,mem_manager>::
at_start (
) const
{
return bst.at_start();
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename bst_base,
typename mem_manager
>
void set_kernel_1<T,bst_base,mem_manager>::
reset (
) const
{
bst.reset();
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename bst_base,
typename mem_manager
>
bool set_kernel_1<T,bst_base,mem_manager>::
current_element_valid (
) const
{
return bst.current_element_valid();
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename bst_base,
typename mem_manager
>
const T& set_kernel_1<T,bst_base,mem_manager>::
element (
) const
{
return bst.element().key();
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename bst_base,
typename mem_manager
>
const T& set_kernel_1<T,bst_base,mem_manager>::
element (
)
{
return bst.element().key();
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename bst_base,
typename mem_manager
>
bool set_kernel_1<T,bst_base,mem_manager>::
move_next (
) const
{
return bst.move_next();
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_SET_KERNEl_1_

View File

@@ -0,0 +1,192 @@
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_SET_KERNEl_ABSTRACT_
#ifdef DLIB_SET_KERNEl_ABSTRACT_
#include "../interfaces/enumerable.h"
#include "../interfaces/remover.h"
#include "../serialize.h"
#include "../algs.h"
#include <functional>
namespace dlib
{
template <
typename T,
typename mem_manager = default_memory_manager,
typename compare = std::less<T>
>
class set : public enumerable<const T>,
public asc_remover<T,compare>
{
/*!
REQUIREMENTS ON T
T must be comparable by compare where compare is a functor compatible with std::less and
T must be swappable by a global swap() and
T must have a default constructor
REQUIREMENTS ON mem_manager
must be an implementation of memory_manager/memory_manager_kernel_abstract.h or
must be an implementation of memory_manager_global/memory_manager_global_kernel_abstract.h or
must be an implementation of memory_manager_stateless/memory_manager_stateless_kernel_abstract.h
mem_manager::type can be set to anything.
POINTERS AND REFERENCES TO INTERNAL DATA
swap() and is_member() functions do not invalidate pointers
or references to internal data.
All other functions have no such guarantee.
INITIAL VALUE
size() == 0
ENUMERATION ORDER
The enumerator will iterate over the elements in the set in
ascending order according to the compare functor.
(i.e. the elements are enumerated in sorted order)
WHAT THIS OBJECT REPRESENTS
set contains items of type T
This object represents an unaddressed collection of items.
Every element in a set is unique.
definition of equivalent:
a is equivalent to b if
a < b == false and
b < a == false
!*/
public:
typedef T type;
typedef compare compare_type;
typedef mem_manager mem_manager_type;
set(
);
/*!
ensures
- #*this is properly initialized
throws
- std::bad_alloc or any exception thrown by T's constructor
!*/
virtual ~set(
);
/*!
ensures
- all memory associated with *this has been released
!*/
void clear(
);
/*!
ensures
- #*this has its initial value
throws
- std::bad_alloc or any exception thrown by T's constructor
if this exception is thrown then *this is unusable
until clear() is called and succeeds
!*/
void add (
T& item
);
/*!
requires
- is_member(item) == false
ensures
- #is_member(item) == true
- #item has an initial value for its type
- #size() == size() + 1
- #at_start() == true
throws
- std::bad_alloc or any exception thrown by T's constructor
if add() throws then it has no effect
!*/
bool is_member (
const T& item
) const;
/*!
ensures
- returns whether or not there is an element in *this equivalent to
item
!*/
void remove (
const T& item,
T& item_copy
);
/*!
requires
- is_member(item) == true
- &item != &item_copy (i.e. item and item_copy cannot be the same
variable)
ensures
- #is_member(item) == false
- the element in *this equivalent to item has been removed and
swapped into #item_copy
- #size() == size() - 1
- #at_start() == true
!*/
void destroy (
const T& item
);
/*!
requires
- is_member(item) == true
ensures
- #is_member(item) == false
- #size() == size() - 1
- #at_start() == true
!*/
void swap (
set& item
);
/*!
ensures
- swaps *this and item
!*/
private:
// restricted functions
set(set&); // copy constructor
set& operator=(set&); // assignment operator
};
template <
typename T,
typename mem_manager,
typename compare
>
inline void swap (
set<T,mem_manager,compare>& a,
set<T,mem_manager,compare>& b
) { a.swap(b); }
/*!
provides a global swap function
!*/
template <
typename T,
typename mem_manager,
typename compare
>
void deserialize (
set<T,mem_manager,compare>& item,
std::istream& in
);
/*!
provides deserialization support
!*/
}
#endif // DLIB_SET_KERNEl_ABSTRACT_

View File

@@ -0,0 +1,194 @@
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_SET_KERNEl_C_
#define DLIB_SET_KERNEl_C_
#include "set_kernel_abstract.h"
#include "../algs.h"
#include "../assert.h"
namespace dlib
{
template <
typename set_base
>
class set_kernel_c : public set_base
{
typedef typename set_base::type T;
public:
void add (
T& item
);
void remove_any (
T& item
);
void remove (
const T& item,
T& item_copy
);
void destroy (
const T& item
);
const T& element (
);
const T& element (
) const;
};
template <
typename set_base
>
inline void swap (
set_kernel_c<set_base>& a,
set_kernel_c<set_base>& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename set_base
>
void set_kernel_c<set_base>::
add(
T& item
)
{
// make sure requires clause is not broken
DLIB_CASSERT( !this->is_member(item),
"\tvoid set::add"
<< "\n\titem being added must not already be in the set"
<< "\n\tthis: " << this
);
// call the real function
set_base::add(item);
}
// ----------------------------------------------------------------------------------------
template <
typename set_base
>
void set_kernel_c<set_base>::
remove (
const T& item,
T& item_copy
)
{
// make sure requires clause is not broken
DLIB_CASSERT( this->is_member(item) &&
(static_cast<const void*>(&item) != static_cast<void*>(&item_copy)),
"\tvoid set::remove"
<< "\n\titem should be in the set if it's going to be removed"
<< "\n\tthis: " << this
<< "\n\t&item: " << &item
<< "\n\t&item_copy: " << &item_copy
<< "\n\tis_member(item): " << (this->is_member(item)?"true":"false")
);
// call the real function
set_base::remove(item,item_copy);
}
// ----------------------------------------------------------------------------------------
template <
typename set_base
>
void set_kernel_c<set_base>::
destroy (
const T& item
)
{
// make sure requires clause is not broken
DLIB_CASSERT( this->is_member(item),
"\tvoid set::destroy"
<< "\n\titem should be in the set if it's going to be removed"
<< "\n\tthis: " << this
<< "\n\t&item: " << &item
);
// call the real function
set_base::destroy(item);
}
// ----------------------------------------------------------------------------------------
template <
typename set_base
>
void set_kernel_c<set_base>::
remove_any (
T& item
)
{
// make sure requires clause is not broken
DLIB_CASSERT( this->size() != 0,
"\tvoid set::remove_any"
<< "\n\tsize must be greater than zero if an item is to be removed"
<< "\n\tthis: " << this
);
// call the real function
set_base::remove_any(item);
}
// ----------------------------------------------------------------------------------------
template <
typename set_base
>
const typename set_base::type& set_kernel_c<set_base>::
element (
) const
{
// make sure requires clause is not broken
DLIB_CASSERT(this->current_element_valid() == true,
"\tconst T& set::element() const"
<< "\n\tyou can't access the current element if it doesn't exist"
<< "\n\tthis: " << this
);
// call the real function
return set_base::element();
}
// ----------------------------------------------------------------------------------------
template <
typename set_base
>
const typename set_base::type& set_kernel_c<set_base>::
element (
)
{
// make sure requires clause is not broken
DLIB_CASSERT(this->current_element_valid() == true,
"\tconst T& set::element"
<< "\n\tyou can't access the current element if it doesn't exist"
<< "\n\tthis: " << this
);
// call the real function
return set_base::element();
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_SET_KERNEl_C_

View File

@@ -0,0 +1,38 @@
// Copyright (C) 2004 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_SLIDING_BUFFEr_
#define DLIB_SLIDING_BUFFEr_
#include "sliding_buffer/sliding_buffer_kernel_1.h"
#include "sliding_buffer/sliding_buffer_kernel_c.h"
#include "sliding_buffer/circular_buffer.h"
namespace dlib
{
template <
typename T
>
class sliding_buffer
{
sliding_buffer() {}
public:
//----------- kernels ---------------
// kernel_1a
typedef sliding_buffer_kernel_1<T>
kernel_1a;
typedef sliding_buffer_kernel_c<kernel_1a>
kernel_1a_c;
};
}
#endif // DLIB_SLIDING_BUFFEr_

Some files were not shown because too many files have changed in this diff Show More