309 lines
6.3 KiB
C++
309 lines
6.3 KiB
C++
|
/* This file is part of Mapnik (c++ mapping toolkit)
|
||
|
* Copyright (C) 2005 Artem Pavlenko
|
||
|
*
|
||
|
* Mapnik is free software; you can redistribute it and/or
|
||
|
* modify it under the terms of the GNU General Public License
|
||
|
* as published by the Free Software Foundation; either version 2
|
||
|
* of the License, or any later version.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with this program; if not, write to the Free Software
|
||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||
|
*/
|
||
|
|
||
|
//$Id: utils.hpp 39 2005-04-10 20:39:53Z pavlenko $
|
||
|
|
||
|
#ifndef UTILS_HPP
|
||
|
#define UTILS_HPP
|
||
|
|
||
|
#include <stdexcept>
|
||
|
#include <limits>
|
||
|
#include <ctime>
|
||
|
#include <sys/time.h>
|
||
|
#include <sstream>
|
||
|
#include <iostream>
|
||
|
#include <cmath>
|
||
|
|
||
|
namespace mapnik
|
||
|
{
|
||
|
class Mutex;
|
||
|
class Lock;
|
||
|
|
||
|
template <typename T>
|
||
|
class CreateUsingNew
|
||
|
{
|
||
|
public:
|
||
|
static T* create()
|
||
|
{
|
||
|
return new T;
|
||
|
}
|
||
|
static void destroy(T* obj)
|
||
|
{
|
||
|
delete obj;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template <typename T>
|
||
|
class CreateStatic
|
||
|
{
|
||
|
private:
|
||
|
union MaxAlign
|
||
|
{
|
||
|
char t_[sizeof(T)];
|
||
|
short int shortInt_;
|
||
|
int int_;
|
||
|
long int longInt_;
|
||
|
float float_;
|
||
|
double double_;
|
||
|
long double longDouble_;
|
||
|
struct Test;
|
||
|
int Test::* pMember_;
|
||
|
int (Test::*pMemberFn_)(int);
|
||
|
};
|
||
|
public:
|
||
|
static T* create()
|
||
|
{
|
||
|
static MaxAlign staticMemory;
|
||
|
return new(&staticMemory) T;
|
||
|
}
|
||
|
static void destroy(volatile T* obj)
|
||
|
{
|
||
|
obj->~T();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template <typename T,
|
||
|
template <typename T> class CreatePolicy=CreateStatic> class singleton
|
||
|
{
|
||
|
friend class CreatePolicy<T>;
|
||
|
static T* pInstance_;
|
||
|
static bool destroyed_;
|
||
|
singleton(const singleton &rhs);
|
||
|
singleton& operator=(const singleton&);
|
||
|
static void onDeadReference()
|
||
|
{
|
||
|
throw std::runtime_error("dead reference!");
|
||
|
}
|
||
|
protected:
|
||
|
static Mutex mutex_;
|
||
|
singleton() {}
|
||
|
virtual ~singleton()
|
||
|
{
|
||
|
CreatePolicy<T>::destroy(pInstance_);
|
||
|
destroyed_=true;
|
||
|
}
|
||
|
public:
|
||
|
static T* instance()
|
||
|
{
|
||
|
if (!pInstance_)
|
||
|
{
|
||
|
Lock lock(&mutex_);
|
||
|
if (!pInstance_)
|
||
|
{
|
||
|
if (destroyed_)
|
||
|
{
|
||
|
onDeadReference();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pInstance_=CreatePolicy<T>::create();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return pInstance_;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template <typename T,
|
||
|
template <typename T> class CreatePolicy> Mutex singleton<T,CreatePolicy>::mutex_;
|
||
|
template <typename T,
|
||
|
template <typename T> class CreatePolicy> T* singleton<T,CreatePolicy>::pInstance_=0;
|
||
|
template <typename T,
|
||
|
template <typename T> class CreatePolicy> bool singleton<T,CreatePolicy>::destroyed_=false;
|
||
|
|
||
|
template <class T> class Handle
|
||
|
{
|
||
|
T* ptr_;
|
||
|
int* pCount_;
|
||
|
public:
|
||
|
T* operator->() {return ptr_;}
|
||
|
const T* operator->() const {return ptr_;}
|
||
|
Handle(T* ptr)
|
||
|
:ptr_(ptr),pCount_(new int(1)) {}
|
||
|
Handle(const Handle& rhs)
|
||
|
:ptr_(rhs.ptr_),pCount_(rhs.pCount_)
|
||
|
{
|
||
|
(*pCount_)++;
|
||
|
}
|
||
|
Handle& operator=(const Handle& rhs)
|
||
|
{
|
||
|
if (ptr_==rhs.ptr_) return *this;
|
||
|
if (--(*pCount_)==0)
|
||
|
{
|
||
|
delete ptr_;
|
||
|
delete pCount_;
|
||
|
}
|
||
|
ptr_=rhs.ptr_;
|
||
|
pCount_=rhs.pCount_;
|
||
|
(*pCount_)++;
|
||
|
return *this;
|
||
|
}
|
||
|
~Handle()
|
||
|
{
|
||
|
if (--(*pCount_)==0)
|
||
|
{
|
||
|
delete ptr_;
|
||
|
delete pCount_;
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
class Mutex
|
||
|
{
|
||
|
private:
|
||
|
pthread_mutex_t mutex_;
|
||
|
public:
|
||
|
Mutex()
|
||
|
{
|
||
|
pthread_mutex_init(&mutex_,0);
|
||
|
}
|
||
|
void lock()
|
||
|
{
|
||
|
pthread_mutex_lock(&mutex_);
|
||
|
}
|
||
|
void unlock()
|
||
|
{
|
||
|
pthread_mutex_unlock(&mutex_);
|
||
|
}
|
||
|
bool trylock()
|
||
|
{
|
||
|
return (pthread_mutex_trylock(&mutex_)==0);
|
||
|
}
|
||
|
~Mutex()
|
||
|
{
|
||
|
pthread_mutex_destroy(&mutex_);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
class Lock
|
||
|
{
|
||
|
private:
|
||
|
Mutex* mutex_;
|
||
|
public:
|
||
|
explicit Lock(Mutex* mutex)
|
||
|
:mutex_(mutex)
|
||
|
{
|
||
|
if (mutex_) mutex_->lock();
|
||
|
}
|
||
|
|
||
|
~Lock()
|
||
|
{
|
||
|
if (mutex_)
|
||
|
mutex_->unlock();
|
||
|
}
|
||
|
private:
|
||
|
Lock();
|
||
|
Lock(const Lock&);
|
||
|
Lock& operator=(const Lock&);
|
||
|
void* operator new(std::size_t);
|
||
|
void* operator new[](std::size_t);
|
||
|
void operator delete(void*);
|
||
|
void operator delete[](void*);
|
||
|
Lock* operator&();
|
||
|
};
|
||
|
|
||
|
class Functor
|
||
|
{
|
||
|
public:
|
||
|
virtual void operator()() const=0;
|
||
|
};
|
||
|
|
||
|
struct timer
|
||
|
{
|
||
|
struct timeval tv_;
|
||
|
timer()
|
||
|
{
|
||
|
gettimeofday (&tv_,0);
|
||
|
}
|
||
|
void start()
|
||
|
{
|
||
|
gettimeofday (&tv_,0);
|
||
|
}
|
||
|
void stop()
|
||
|
{
|
||
|
timeval tv;
|
||
|
gettimeofday (&tv,0);
|
||
|
std::ostringstream s;
|
||
|
long sec=1000*(tv.tv_sec-tv_.tv_sec);
|
||
|
long total_ms=sec+static_cast<long>(0.001*(tv.tv_usec-tv_.tv_usec));
|
||
|
s << "elapsed time is "<<total_ms<<" ms";
|
||
|
std::cout<<s.str()<<std::endl;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//converters
|
||
|
class BadConversion : public std::runtime_error
|
||
|
{
|
||
|
public:
|
||
|
BadConversion(const std::string& s)
|
||
|
:std::runtime_error(s)
|
||
|
{}
|
||
|
};
|
||
|
|
||
|
template <typename T>
|
||
|
inline std::string toString(const T& x)
|
||
|
{
|
||
|
std::ostringstream o;
|
||
|
if (!(o << x))
|
||
|
throw BadConversion(std::string("toString(")
|
||
|
+ typeid(x).name() + ")");
|
||
|
return o.str();
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
inline void fromString(const std::string& s, T& x,
|
||
|
bool failIfLeftoverChars = true)
|
||
|
{
|
||
|
std::istringstream i(s);
|
||
|
char c;
|
||
|
if (!(i >> x) || (failIfLeftoverChars && i.get(c)))
|
||
|
throw BadConversion("fromString("+s+")");
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
inline bool space (char c)
|
||
|
{
|
||
|
return isspace(c);
|
||
|
}
|
||
|
|
||
|
inline bool not_space (char c)
|
||
|
{
|
||
|
return !isspace(c);
|
||
|
}
|
||
|
|
||
|
inline std::string trim_left(const std::string& str)
|
||
|
{
|
||
|
typedef std::string::const_iterator iter;
|
||
|
iter i = find_if(str.begin(),str.end(),not_space);
|
||
|
return std::string(i,str.end());
|
||
|
}
|
||
|
inline std::string trim_right(const std::string& str)
|
||
|
{
|
||
|
std::string::size_type idx=str.find_last_not_of(" ");
|
||
|
return str.substr(0,idx+1);
|
||
|
}
|
||
|
inline std::string trim(const std::string& str)
|
||
|
{
|
||
|
return trim_left(trim_right(str));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
#endif //UTILS_HPP
|