290 lines
7.6 KiB
C++
290 lines
7.6 KiB
C++
#pragma once
|
|
|
|
namespace pfc {
|
|
template<class T>
|
|
class vartoggle_t {
|
|
T oldval; T & var;
|
|
public:
|
|
vartoggle_t(T & p_var,const T & val) : var(p_var) {
|
|
oldval = var;
|
|
var = val;
|
|
}
|
|
~vartoggle_t() {var = oldval;}
|
|
};
|
|
|
|
template<class T>
|
|
class vartoggle_volatile_t {
|
|
T oldval; volatile T & var;
|
|
public:
|
|
vartoggle_volatile_t(volatile T & p_var,const T & val) : var(p_var) {
|
|
oldval = var;
|
|
var = val;
|
|
}
|
|
~vartoggle_volatile_t() {var = oldval;}
|
|
};
|
|
|
|
typedef vartoggle_t<bool> booltoggle;
|
|
};
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
class fpu_control
|
|
{
|
|
unsigned old_val;
|
|
unsigned mask;
|
|
public:
|
|
inline fpu_control(unsigned p_mask,unsigned p_val)
|
|
{
|
|
mask = p_mask;
|
|
_controlfp_s(&old_val,p_val,mask);
|
|
}
|
|
inline ~fpu_control()
|
|
{
|
|
unsigned dummy;
|
|
_controlfp_s(&dummy,old_val,mask);
|
|
}
|
|
};
|
|
|
|
class fpu_control_roundnearest : private fpu_control
|
|
{
|
|
public:
|
|
fpu_control_roundnearest() : fpu_control(_MCW_RC,_RC_NEAR) {}
|
|
};
|
|
|
|
class fpu_control_flushdenormal : private fpu_control
|
|
{
|
|
public:
|
|
fpu_control_flushdenormal() : fpu_control(_MCW_DN,_DN_FLUSH) {}
|
|
};
|
|
|
|
class fpu_control_default : private fpu_control
|
|
{
|
|
public:
|
|
fpu_control_default() : fpu_control(_MCW_DN|_MCW_RC,_DN_FLUSH|_RC_NEAR) {}
|
|
};
|
|
|
|
#ifdef _M_IX86
|
|
class sse_control {
|
|
public:
|
|
sse_control(unsigned p_mask,unsigned p_val) : m_mask(p_mask) {
|
|
__control87_2(p_val,p_mask,NULL,&m_oldval);
|
|
}
|
|
~sse_control() {
|
|
__control87_2(m_oldval,m_mask,NULL,&m_oldval);
|
|
}
|
|
private:
|
|
unsigned m_mask,m_oldval;
|
|
};
|
|
class sse_control_flushdenormal : private sse_control {
|
|
public:
|
|
sse_control_flushdenormal() : sse_control(_MCW_DN,_DN_FLUSH) {}
|
|
};
|
|
#endif
|
|
|
|
#endif
|
|
|
|
namespace pfc {
|
|
|
|
class releaser_delete {
|
|
public:
|
|
template<typename T> static void release(T* p_ptr) {delete p_ptr;}
|
|
};
|
|
class releaser_delete_array {
|
|
public:
|
|
template<typename T> static void release(T* p_ptr) {delete[] p_ptr;}
|
|
};
|
|
class releaser_free {
|
|
public:
|
|
static void release(void * p_ptr) {free(p_ptr);}
|
|
};
|
|
|
|
//! Assumes t_freefunc to never throw exceptions.
|
|
template<typename T,typename t_releaser = releaser_delete >
|
|
class ptrholder_t {
|
|
private:
|
|
typedef ptrholder_t<T,t_releaser> t_self;
|
|
public:
|
|
inline ptrholder_t(T* p_ptr) : m_ptr(p_ptr) {}
|
|
inline ptrholder_t() : m_ptr(NULL) {}
|
|
inline ~ptrholder_t() {t_releaser::release(m_ptr);}
|
|
inline bool is_valid() const {return m_ptr != NULL;}
|
|
inline bool is_empty() const {return m_ptr == NULL;}
|
|
inline T* operator->() const {return m_ptr;}
|
|
inline T* get_ptr() const {return m_ptr;}
|
|
inline void release() {t_releaser::release(replace_null_t(m_ptr));;}
|
|
inline void attach(T * p_ptr) {release(); m_ptr = p_ptr;}
|
|
inline const t_self & operator=(T * p_ptr) {set(p_ptr);return *this;}
|
|
inline T* detach() {return pfc::replace_null_t(m_ptr);}
|
|
inline T& operator*() const {return *m_ptr;}
|
|
|
|
inline t_self & operator<<(t_self & p_source) {attach(p_source.detach());return *this;}
|
|
inline t_self & operator>>(t_self & p_dest) {p_dest.attach(detach());return *this;}
|
|
|
|
//deprecated
|
|
inline void set(T * p_ptr) {attach(p_ptr);}
|
|
|
|
ptrholder_t(t_self&& other) { m_ptr = other.detach(); }
|
|
const t_self& operator=(t_self&& other) { attach(other.detach()); return this; }
|
|
private:
|
|
ptrholder_t(const t_self &) {throw pfc::exception_not_implemented();}
|
|
const t_self & operator=(const t_self & ) {throw pfc::exception_not_implemented();}
|
|
|
|
T* m_ptr;
|
|
};
|
|
|
|
//avoid "void&" breakage
|
|
template<typename t_releaser>
|
|
class ptrholder_t<void,t_releaser> {
|
|
private:
|
|
typedef void T;
|
|
typedef ptrholder_t<T,t_releaser> t_self;
|
|
public:
|
|
inline ptrholder_t(T* p_ptr) : m_ptr(p_ptr) {}
|
|
inline ptrholder_t() : m_ptr(NULL) {}
|
|
inline ~ptrholder_t() {t_releaser::release(m_ptr);}
|
|
inline bool is_valid() const {return m_ptr != NULL;}
|
|
inline bool is_empty() const {return m_ptr == NULL;}
|
|
inline T* operator->() const {return m_ptr;}
|
|
inline T* get_ptr() const {return m_ptr;}
|
|
inline void release() {t_releaser::release(replace_null_t(m_ptr));;}
|
|
inline void attach(T * p_ptr) {release(); m_ptr = p_ptr;}
|
|
inline const t_self & operator=(T * p_ptr) {set(p_ptr);return *this;}
|
|
inline T* detach() {return pfc::replace_null_t(m_ptr);}
|
|
|
|
inline t_self & operator<<(t_self & p_source) {attach(p_source.detach());return *this;}
|
|
inline t_self & operator>>(t_self & p_dest) {p_dest.attach(detach());return *this;}
|
|
|
|
//deprecated
|
|
inline void set(T * p_ptr) {attach(p_ptr);}
|
|
private:
|
|
ptrholder_t(const t_self &) {throw pfc::exception_not_implemented();}
|
|
const t_self & operator=(const t_self & ) {throw pfc::exception_not_implemented();}
|
|
|
|
T* m_ptr;
|
|
};
|
|
|
|
PFC_NORETURN void crash();
|
|
void outputDebugLine(const char * msg);
|
|
|
|
class debugLog : public string_formatter {
|
|
public:
|
|
~debugLog() { outputDebugLine(this->get_ptr()); }
|
|
};
|
|
#define PFC_DEBUGLOG ::pfc::debugLog()._formatter()
|
|
|
|
|
|
template<typename t_type,t_type p_initval>
|
|
class int_container_helper {
|
|
public:
|
|
int_container_helper() : m_val(p_initval) {}
|
|
t_type m_val;
|
|
};
|
|
|
|
|
|
|
|
//warning: not multi-thread-safe
|
|
template<typename t_base>
|
|
class instanceTracker : public t_base {
|
|
private:
|
|
typedef instanceTracker<t_base> t_self;
|
|
public:
|
|
TEMPLATE_CONSTRUCTOR_FORWARD_FLOOD_WITH_INITIALIZER(instanceTracker,t_base,{g_list += this;});
|
|
|
|
instanceTracker(const t_self & p_other) : t_base( (const t_base &)p_other) {g_list += this;}
|
|
~instanceTracker() {g_list -= this;}
|
|
|
|
typedef pfc::avltree_t<t_self*> t_list;
|
|
static const t_list & instanceList() {return g_list;}
|
|
template<typename t_callback> static void forEach(t_callback & p_callback) {instanceList().enumerate(p_callback);}
|
|
private:
|
|
static t_list g_list;
|
|
};
|
|
|
|
template<typename t_base>
|
|
typename instanceTracker<t_base>::t_list instanceTracker<t_base>::g_list;
|
|
|
|
|
|
//warning: not multi-thread-safe
|
|
template<typename TClass>
|
|
class instanceTrackerV2 {
|
|
private:
|
|
typedef instanceTrackerV2<TClass> t_self;
|
|
public:
|
|
instanceTrackerV2(const t_self & p_other) {g_list += static_cast<TClass*>(this);}
|
|
instanceTrackerV2() {g_list += static_cast<TClass*>(this);}
|
|
~instanceTrackerV2() {g_list -= static_cast<TClass*>(this);}
|
|
|
|
typedef pfc::avltree_t<TClass*> t_instanceList;
|
|
static const t_instanceList & instanceList() {return g_list;}
|
|
template<typename t_callback> static void forEach(t_callback & p_callback) {instanceList().enumerate(p_callback);}
|
|
private:
|
|
static t_instanceList g_list;
|
|
};
|
|
|
|
template<typename TClass>
|
|
typename instanceTrackerV2<TClass>::t_instanceList instanceTrackerV2<TClass>::g_list;
|
|
|
|
|
|
struct objDestructNotifyData {
|
|
bool m_flag;
|
|
objDestructNotifyData * m_next;
|
|
|
|
};
|
|
class objDestructNotify {
|
|
public:
|
|
objDestructNotify() : m_data() {}
|
|
~objDestructNotify() {
|
|
set();
|
|
}
|
|
|
|
void set() {
|
|
objDestructNotifyData * w = m_data;
|
|
while(w) {
|
|
w->m_flag = true; w = w->m_next;
|
|
}
|
|
}
|
|
objDestructNotifyData * m_data;
|
|
};
|
|
|
|
class objDestructNotifyScope : private objDestructNotifyData {
|
|
public:
|
|
objDestructNotifyScope(objDestructNotify &obj) : m_obj(&obj) {
|
|
m_next = m_obj->m_data;
|
|
m_obj->m_data = this;
|
|
}
|
|
~objDestructNotifyScope() {
|
|
if (!m_flag) m_obj->m_data = m_next;
|
|
}
|
|
bool get() const {return m_flag;}
|
|
PFC_CLASS_NOT_COPYABLE_EX(objDestructNotifyScope)
|
|
private:
|
|
objDestructNotify * m_obj;
|
|
|
|
};
|
|
|
|
|
|
class bigmem {
|
|
public:
|
|
enum {slice = 1024*1024};
|
|
bigmem() : m_size() {}
|
|
~bigmem() {clear();}
|
|
|
|
void resize(size_t newSize);
|
|
size_t size() const {return m_size;}
|
|
void clear();
|
|
void read(void * ptrOut, size_t bytes, size_t offset);
|
|
void write(const void * ptrIn, size_t bytes, size_t offset);
|
|
uint8_t * _slicePtr(size_t which);
|
|
size_t _sliceCount();
|
|
size_t _sliceSize(size_t which);
|
|
private:
|
|
array_t<uint8_t*> m_data;
|
|
size_t m_size;
|
|
|
|
PFC_CLASS_NOT_COPYABLE_EX(bigmem)
|
|
};
|
|
|
|
|
|
double exp_int( double base, int exp );
|
|
}
|