mapnik/include/utils.hpp
2005-06-14 15:06:59 +00:00

308 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