⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 doruntime.cpp

📁 The library provides supports for run-time loaded plugin classes in C++
💻 CPP
字号:
// Copyright (c) 2007, Arne Steinarson// Licensing for DynObj project - see DynObj-license.txt in this folder#include <stdlib.h>#include <string.h>#include <stdio.h>#include <assert.h>#define EA_ASSERT assert#define DO_IMPLEMENTING#define DO_IMPLEMENT_DORUNTIME#include "DoRunTime.h"//#include "DoBase.hpp"#include "DynObjLib.h"#include "DynStr.h"// Owner of mutex - Diagnostics in case of deadlockint g_mut_own_thid;#include "pi/Thread.h"class MutexC : public MutexI {public:    PI_MUTEX_HANDLE m_mh;    int m_cnt;	MutexC() {         m_mh = piMutexCreate(true);        m_cnt = 0;    }		virtual bool docall Lock() {_CFE_;         bool b = !piMutexLock(m_mh);         if( b && !m_cnt++ ) g_mut_own_thid = piGetThreadId();         return b;    }	virtual bool docall Unlock(){_CFE_; 		bool b = !piMutexUnlock(m_mh);		if( b && !--m_cnt ) g_mut_own_thid = -1;        return b;	}    	virtual bool docall TryLock() {_CFE_; 		bool b = !piMutexTryLock(m_mh); 		if( b && !m_cnt++ ) g_mut_own_thid = piGetThreadId(); 		return b;	}    	bool docall IsOk() {_CFE_; return m_mh!=NULL; }};/*#include <wx/thread.h>class MutexC : public MutexI {public:	MutexC() : m_mut(wxMUTEX_RECURSIVE) { }	bool IsOk(){_CFE_; return true; }		virtual bool docall Lock(){_CFE_;	   bool b = m_mut.Lock()==wxMUTEX_NO_ERROR;	   if( b )		   g_mut_own_thid = wxThread::GetCurrentId(); 		return b;	}	virtual bool docall Unlock(){_CFE_; 	   int prev_thid = g_mut_own_thid;	   g_mut_own_thid = -1;		bool b = m_mut.Unlock()==wxMUTEX_NO_ERROR; 		if( !b )			g_mut_own_thid = prev_thid;	   return b;	}	virtual bool docall TryLock() {_CFE_; 		bool b = m_mut.TryLock()==wxMUTEX_NO_ERROR; 		if( b )		   g_mut_own_thid = wxThread::GetCurrentId(); 		return b;	}		wxMutex m_mut;};*/// Can set another allocator using DoRunTimeI::SetMallocclass MallocC : public MallocI {	virtual void* docall malloc( int size ){_CFE_; 		return malloc(size); 	}	virtual void  docall free( void *pv ){_CFE_; 		free(pv); 	}};class TextIoC : public TextIoI {	virtual int  docall puts(const char *ps){_CFE_; 		return (int)fputs(ps,stdout); 	}	virtual int  docall puterr(const char *ps){_CFE_; 		return (int)fputs(ps,stderr); 	}	virtual int  docall gets(DynStr& ds, bool sync){_CFE_;		int ch;		int cnt = 0;		while( ch=fgetc(stdin) ) {			if( ch=='\n' || ch==EOF ) break;			ds += ch;			cnt++;		}		return (int)cnt; 	}};#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT==1 #include <wx/memory.h>// To run our global destructors before memory dumpwxDebugContextDumpDelayCounter g_debug_do_rt;#endif DoRunTimeC *g_pdort;MutexC 	  *g_pdort_mut;int        g_dort_ok;	// Set to 1 at end of constructor, -1 at end of destructorMutexI *GetDortMutex(){_CFE_; 	// Only create mutex before run time has started	// This gives access to mutex before all global constructors have been run	if( !g_pdort_mut && !g_dort_ok ){		g_pdort_mut = new MutexC;        // Check that mutex creation went OK        DO_ASSERT_MSG( g_pdort_mut->IsOk(), "GetDortMutex - Not OK" );    }	return g_pdort_mut;}// Proto from DynObj.cppvoid doSetRunTime( DoRunTimeI* pdort );// This ensures that we can have an instance before all global constructors are runDoRunTimeC &DoRunTimeC::GetInstance(){_CFE_;	if( !g_pdort && !g_dort_ok ){		g_pdort = new DoRunTimeC;		doSetRunTime( g_pdort );	}	return *g_pdort;}DoRunTimeI *MainGetDort() {_CFE_;	return &DoRunTimeC::GetInstance();}DoRunTimeC &MainGetDortC() {_CFE_;	return DoRunTimeC::GetInstance();}// Assures that the runtime goes down on application shutdownclass DoRunTimeGlobConstr{public:	~DoRunTimeGlobConstr( ){ 		if( g_pdort ){			doSetRunTime( NULL );			g_pdort->doDestroy();			delete g_pdort_mut;			g_pdort_mut = NULL;		    g_pdort = NULL;		}	}} g_dort_glob_constr;DoRunTimeC::DoRunTimeC(){_CFE_;	// Set up interface pointers	static MallocC st_malloc;	static TextIoC st_tio;	m_pmut = GetDortMutex();	m_pmalloc = &st_malloc;	m_ptio = &st_tio;	g_dort_ok = 1;    m_lib_last = NULL;    m_lib_cache_ix = 0;	m_tmp_disable = 0;}void DoRunTimeC::Dtor(){_CFE_;	MutexLocker lock(g_pdort_mut);	g_dort_ok = -1;    m_libs.DeleteAll();}bool DoRunTimeC::IsOk() {_CFE_;    return this && g_dort_ok>0;}void *DoRunTimeC::doGetObj( const char *type ) {_CFE_;	if( g_dort_ok<=0 ) return NULL;	// So that we can return this interface before type init finished		if( !strcmp(type,"NamedRefI") ) return static_cast<NamedRefI*>(this);	// Owned objects?	if( !strcmp(type,"MutexI") ) return m_pmut;	if( !strcmp(type,"MallocI") ) return m_pmalloc;	if( !strcmp(type,"TextIoI") ) return m_ptio;		return DoRunTimeI::doGetObj(type);}	DynObj *DoRunTimeC::Create( const char *lib, const char *type, int type_id, const DynI* pdi_init, int obj_size ){_CFE_;	if( g_dort_ok<=0 || m_tmp_disable>0 ) return NULL;		// Protect object creation with mutex (only 1 object created at a time)    MutexLocker lock(g_pdort_mut);    DynObj *pdo = NULL;    bool found_lib = false;    for( EapIter<DynObjLib*> it(m_libs); it(); it++ ){		if( (!lib || (it()->GetLibName() && !strcmp(lib,it()->GetLibName()))) && 		    it()->Implements(type)>0 ){            found_lib = true;			if( pdo=it()->Create(type,type_id,pdi_init,obj_size) ){                m_lib_last = it();				return pdo;            }		}	}	if( found_lib )		SetLastError(-2, CharBuf(true,"DoRunTimeC: Library for type found but failed Create: ", type) );	else		SetLastError(-3, CharBuf(true,"DoRunTimeC: No matching library for type found: ", type) );	return NULL;}	void DoRunTimeC::TempDisableCreate( bool disable ){_CFE_;	m_tmp_disable += (disable ? 1 : -1); }void DoRunTimeC::OnObjectDestroy( DynObj *pdo ){_CFE_;    if( !pdo ) return;	// Object going out of scope, don't keep error log for it	ClearObjectError( pdo );    // Track back to library that created object    DynObjType *pdt = DI_GET_TYPE(pdo);    if( pdt && pdt->_module->m_pv1 )        ((DynObjLib*)pdt->_module->m_pv1)->OnObjectDestroy( pdo, pdt );}int DoRunTimeC::GetLastErrCode( int thid ){_CFE_;	if( g_dort_ok<=0 ) return false;	MutexLocker lock(g_pdort_mut);	if( thid==-1 )		thid = GetThreadId();			DOError *pe = m_errors.Find(thid);	return pe ? pe->m_err_code : 0;}bool DoRunTimeC::GetLastErrStr( DynStr &ds, int thid ){_CFE_;	if( g_dort_ok<=0 ) return false;	MutexLocker lock(g_pdort_mut);	if( thid==-1 )		thid = GetThreadId();			DOError *pe = m_errors.Find(thid);	if( !pe ) return false;	ds = pe->m_err_str;	return true;}bool DoRunTimeC::SetLastError( int err_code, const char *err_msg ){_CFE_;	if( g_dort_ok<=0 ) return false;	MutexLocker lock(g_pdort_mut);	int thid = GetThreadId();		// Output to stderr	if( err_code ){		if( !err_msg || !*err_msg ) err_msg=" ";		if( m_ptio ){			CharBuf cb;			int el = (int)strlen(err_msg);			cb.Resize(el+32);			if( cb.Get() ){				// \n terminate				sprintf( (char*)cb.Get(), "(Error: 0x%X) - %s%c", err_code, err_msg, err_msg[el-1]=='\n'?' ':'\n' );				m_ptio->puterr(cb);			}			else{				m_ptio->puterr("DoRunTimeC: Mem alloc failure\n");				m_ptio->puterr(err_msg);			}		}	}		DOError *pe = m_errors.Find(thid);    bool did_set = false;	if( !pe ){        if( m_oe_avail.Size() )            pe = m_oe_avail.Pop();        else{            pe = new DOError( GetThreadId(), err_code, err_msg );            if( !pe ) return false;            m_oe_allocated.Push(pe);            did_set = true;        }		m_errors.Push(pe);	}	if( !did_set ){		pe->m_err_code = err_code;		pe->m_err_str = err_msg;	}    	// Check that memory alloc went OK	if( !pe->m_err_str || (err_msg && strcmp(pe->m_err_str,err_msg)) )		return false;		return true;}int DoRunTimeC::GetThreadId( ){_CFE_;    return piGetThreadId();}bool DoRunTimeC::RegisterModule( DoModuleC *pmi ){_CFE_;	if( g_dort_ok<=0 ) return false;	MutexLocker lock(g_pdort_mut);    	if( !pmi || m_modules.Has(pmi) )		return false;	m_modules.Push(pmi);	return true;}bool DoRunTimeC::UnRegisterModule( DoModuleC *pmi ){_CFE_;	if( g_dort_ok<=0 ) return false;	MutexLocker lock(g_pdort_mut);    	int ix = m_modules.IndexOf(pmi);	if( ix<0 ) return false;	m_modules.RemoveIndexUnordered(ix);	return true;}bool DoRunTimeC::RegisterType( void **vtbl, DynObjType *pdt ){_CFE_;	if( g_dort_ok<=0 ) return false;	if( vtbl && pdt ){		MutexLocker lock(g_pdort_mut);		if( !m_types.Lookup(vtbl) ){			m_types.Insert(vtbl,pdt);			return true;		}	}	return false;}bool DoRunTimeC::UnRegisterType( void **vtbl ){_CFE_;	if( g_dort_ok<=0 ) return false;	if( vtbl ){		MutexLocker lock(g_pdort_mut);		return m_types.Remove(vtbl);	}	return false;}DynObjType* DoRunTimeC::GetTypeOf( void **vtbl ){_CFE_;	if( g_dort_ok<=0 ) return NULL;	return m_types.Lookup(vtbl);}bool DoRunTimeC::AddDOLib( DynObjLib *pdol ){_CFE_;	if( g_dort_ok<=0 || !pdol ) return false;		MutexLocker lock(g_pdort_mut);	m_libs.Push(pdol);        // Register types in library (if not done yet)    DynObjType **pdot = pdol->m_pdol_impl->_types;    DynObjType *dot;    for( int ix=0; dot=pdot[ix]; ix++ )		if( dot->_vtbl && !m_types.Lookup(dot->_vtbl) )			m_types.Insert(dot->_vtbl,dot);    	return true;}bool DoRunTimeC::RemoveDOLib( const DynObjLib *pdol ){_CFE_;	if( g_dort_ok<=0 ) return false;		MutexLocker lock(g_pdort_mut);        // Unregister types in library (if not done yet)    DynObjType **pdot = pdol->m_pdol_impl->_types;    DynObjType *dot;    for( int ix=0; dot=pdot[ix]; ix++ )		if( dot->_vtbl && m_types.Lookup(dot->_vtbl) )			m_types.Remove(dot->_vtbl);        // Remove among cached libraries also    for( int ix=0; ix<m_type_libs.Size(); ix++ )        if( m_type_libs[ix]==pdol )            m_type_libs[ix] = NULL;        // Remove from array of libraries	return m_libs.Remove((DynObjLib*)pdol);}const char *DoRunTimeC::LoadLib( const char *lib_name ){_CFE_;	if( g_dort_ok<=0 ) return false;	    DynObjLib *pdol = new DynObjLib(lib_name);	if( !pdol )		return "<Failed new>";    if( !pdol->IsOk() ){		static CharBuf cb_err;		cb_err = pdol->GetError();        delete pdol;        return cb_err;    }    AddDOLib(pdol);	return NULL;}DynObjLib* DoRunTimeC::GetLib( const char *lib ){	return m_libs.Find(lib);}bool DoRunTimeC::SetObjectError( const VObj *pvo, const char *err_str, int err_code ){_CFE_;	if( g_dort_ok<=0 ) return false;	MutexLocker lock(g_pdort_mut);        DOError *pdoe = m_obj_errors.Lookup(pvo);    if( !pdoe ) {        if( m_oe_avail.Size() ){            pdoe = m_oe_avail.Pop();            m_obj_errors.Insert(pvo,pdoe);        }        else {            pdoe = new DOError(GetThreadId(),err_code,err_str);            if( !pdoe ) return false;            m_oe_allocated.Push(pdoe);            m_obj_errors.Insert(pvo,pdoe);            return true;        }    }    else{        pdoe->m_thid = GetThreadId();        pdoe->m_err_code = err_code;        pdoe->m_err_str = err_str;    }    return true;}bool DoRunTimeC::ClearObjectError( const VObj *pvo ) {_CFE_;	if( g_dort_ok<=0 ) return false;	MutexLocker lock(g_pdort_mut);        DOError *pdoe = m_obj_errors.Lookup(pvo);    if( !pdoe ) return true;        m_obj_errors.Remove(pvo);    // Keep unallocated error    m_oe_avail.Push(pdoe);        return true;}const char *DoRunTimeC::GetObjectError( const VObj *pvo, int *perr_code ) {_CFE_;	if( g_dort_ok<=0 ) return NULL;	MutexLocker lock(g_pdort_mut);        DOError *pdoe = m_obj_errors.Lookup(pvo);    if( !pdoe ){        if( perr_code ) *perr_code = 0;        return NULL;    }    if( perr_code ) *perr_code = pdoe->m_err_code;    return pdoe->m_err_str;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -