00001
00002
00003
00004 #ifndef DORUNTIME_H
00005 #define DORUNTIME_H
00006
00007 #ifndef DO_USE_RUNTIME
00008 #define DO_USE_RUNTIME 1
00009 #endif
00010
00011
00012
00013 #ifdef DO_IMPLEMENT_DORUNTIME
00014 #define DO_IMPLEMENTING // If app has not defined it already
00015 #endif
00016 #include "dynobj/DynObj.h"
00017
00018
00019 #define DORUNTIMEC_TYPE_ID 0xDCCF5000
00020
00021
00022 class DoRunTimeC;
00023
00024
00025 DO_DECL_TYPE_INFO(DoRunTimeC,DORUNTIMEC_TYPE_ID);
00026
00027
00028
00029
00030 #ifndef DO_MAIN
00031 #define DO_MAIN // DoRunTime is always in the main module
00032 #endif
00033
00034 #include "DoBaseI.h"
00035 #include "DoError.h"
00036
00037
00038
00039 #include "DynObj.h"
00040 #include "utils/ExpArr.hpp"
00041 #include "utils/HashTable.hpp"
00042 #include "utils/CharBuf.h"
00043 #if DO_USE_TEMPLATES==1
00044 #include "DoBase.hpp"
00045 #endif
00046 #include "DortInternal.h"
00047
00048 #include "DynObjLib.h"
00049 #include "DoNotifier.hpp"
00050 #include "NamedRef.h"
00051
00052
00053 struct DynObjError;
00054 struct DOError;
00055 class DynStr;
00056 class DoVtblType;
00057 class DynObjLibI;
00058 class DoRunTimeC;
00059
00060 #if DO_USE_TEMPLATES==1
00061
00062 template<>
00063 struct VBaseSelect<DoRunTimeC>{
00064 typedef DoRunTimeI type;
00065 };
00066 #endif
00067
00068
00069
00070 template<>
00071 class HashData<int,DynObjType*> {
00072 public:
00073 HashData( ) : m_v(0) { }
00074 inline int GetKey(){ return m_v ? m_v->_type_id : 0; }
00075 inline void SetKey(int k){ }
00076
00077 DynObjType* m_v;
00078 bool operator == (int k){ return m_v ? m_v->_type_id==k : false; }
00079 };
00080
00081
00082 template<>
00083 class HashData<const char*,DynObjType*> {
00084 public:
00085 HashData( ) : m_v(0) { }
00086 inline const char* GetKey(){ return m_v ? m_v->_type : 0; }
00087 inline void SetKey(const char* k){ }
00088
00089 DynObjType* m_v;
00090 bool operator == (const char* k){
00091 if( !m_v ) return !k;
00092
00093 if( k==m_v->_type ) return true;
00094 if( m_v->_type && k && !strcmp(m_v->_type,k) ) return true;
00095 return false;
00096 }
00097 };
00098
00099
00100
00101 struct DelayedRegisterVTable {
00102 DelayedRegisterVTable( void** vtbl, DynObjType *pdt ) : m_vtbl(vtbl), m_pdt(pdt) { }
00103 void **m_vtbl;
00104 DynObjType *m_pdt;
00105 bool operator==(int id){ return m_pdt && m_pdt->_type_id==id; }
00106 bool operator==(void **vtbl){ return m_vtbl==vtbl; }
00107 bool operator==(DynObjType *pdt){ return m_pdt==pdt; }
00108 };
00109
00110
00111
00112 class OwnedDynObjLib;
00113
00114
00120
00121 class DoRunTimeC : public DoRunTimeI, public Notifier, public NamedRef,
00122 public DortInternalI {
00123 friend class OwnedDynObjLib;
00124 public:
00125 DoRunTimeC();
00126 ~DoRunTimeC(){ Dtor(); }
00127 void Dtor();
00128
00132 static DoRunTimeC &GetInstance( bool do_get=true );
00133
00137
00138
00139 virtual DynObjType* docall doGetType( const DynI **pself=0 ) const;
00140 virtual void* docall doQueryI( const char *type );
00141 virtual void docall doDestroy( ){ delete this; }
00142
00144
00145 virtual MallocI* docall GetMalloc() const { return m_pmalloc; }
00146 virtual TextIoI* docall GetTextIo() const { return m_ptio; }
00148
00155 virtual DynObj* docall Create( const char *lib, const char *type, int type_id, const DynI* pdi_init=NULL );
00156
00158
00159 virtual int docall GetLastErrCode( int thid=-1 );
00160 virtual bool docall GetLastErrStr( DynStr& ds, int thid=-1 );
00161 virtual bool docall SetLastError( int err_code, const char *err_msg );
00162 virtual int docall GetThreadId( );
00164
00166 virtual DynI* docall LoadLib( const char *lib_name, DynI* pdi_init );
00168 virtual bool docall UnloadLib( const char *lib_name );
00170 virtual DynObjLibI* docall GetLib( const char *lib );
00171 virtual const char* docall GetLoadError( ){ return m_cb_load_err; }
00172
00174
00175 virtual DynObjType* docall GetTypeOf( void **vtbl );
00176 virtual DynObjType* docall FindTypeFromName( const char *type, const char *header=NULL );
00177 virtual DynObjType* docall FindTypeFromId( int type_id );
00179
00180 virtual int docall GenerateTypeId();
00181
00183
00187
00188
00195 bool AddDOLib( DynObjLib *pdol );
00196
00197
00202 const char* LoadLib( const char *lib_name );
00203
00208 DynI* LoadLib( const char *lib_name, DynI* pdi_init, int mod_flags );
00209
00210 enum { MU_Ok=0, MU_LibNotFound, MU_CallerNotFound, Mu_ModuleNotFound, MU_NoPerm, MU_NotOwned, MU_HasInstances, MU_DanglingOk, MU_DanglingReject };
00211 int MayUnload( const char* lib_name );
00212
00220 bool UnloadDanglingLib( const char* lib_name );
00221
00226 DynObjLib *GetMainLib( );
00227
00228
00229
00230
00231
00234 bool SetMalloc( MallocI *pmi );
00235
00238 void SetTextIo( TextIoI *ptio ){ m_ptio=ptio; }
00239
00241 bool IsOk();
00242
00244 bool PrepareShutdown( );
00245
00246 #if DO_USE_TEMPLATES==1
00247
00248 template<class T>
00249 T* Create( doTypeWrapper<T>, const char *lib, const DynI* pdi_init=NULL ) {
00250 if( !IsOk() || m_tmp_disable<0 ) return NULL;
00251
00252 int type_id = doTypeInfo<T>::Id();
00253 const char* type = doTypeInfo<T>::Name();
00254
00255 DynObjType *pdt_create = NULL;
00256 DynObj *pdo = CreateGetType( lib, type, type_id, pdi_init, &pdt_create );
00257 if( pdo )
00258
00259 return (T*)::doGetObj( (void*)pdo, type_id, pdt_create );
00260 else
00261 return NULL;
00262 }
00263 #endif // DO_USE_TEMPLATES==1
00264
00266
00267
00269 virtual bool docall RegisterModule( DoModuleC *pmi );
00270 virtual bool docall UnRegisterModule( DoModuleC *pmi );
00271 virtual DoModuleC* docall GetModuleByIndex( int ix );
00272
00274 virtual bool docall RegisterTypeVTable( void **vtbl, DynObjType *pdt );
00275 virtual bool docall UnRegisterTypeVTable( void **vtbl );
00276 virtual int docall MergeTypes( doModuleData *pmod_data );
00277 virtual bool docall UnMergeTypes( doModuleData *pmod_data );
00278 virtual bool docall IsValidType( DynObjType *pdt );
00279 virtual DoModuleC* docall GetModuleByAddr( const void* paddr );
00280 virtual DoModuleC* docall GetModuleForType( DoModuleC* pmod_caller, int type_id );
00281
00283 virtual bool docall SetObjectError( const void *pvo, const char *err_str, int err_code );
00284 virtual bool docall ClearObjectError( const void *pvo );
00285 virtual const char* docall GetObjectError( const void *pvo, int *perr_code );
00286
00287 virtual void docall OnObjectCreate( DynObj *pdo, DoModuleC *pmod );
00288 virtual void docall OnObjectDestroy( DynObj *pdo, DoModuleC *pmod );
00289 virtual void docall TempDisableCreate( bool disable );
00290
00291 virtual void docall SetModuleTempPermissions( DynObjLibI* plib, const void* base, int flags );
00292 virtual void docall ResetModuleTempPermissions( );
00293
00294 virtual bool docall TrackDynObj( DynObj *pdo, NotifiableI *pni, bool begin_track, DynObjType *pdt );
00295
00296 virtual int docall AllocTypeItemTypeId( );
00297
00298 virtual void* docall MainAlloc( int size );
00299 virtual bool docall MainFree( void* pmem );
00300
00301 protected:
00302
00303
00304 bool HasType( DynObjType *pdt );
00305 bool AddType( DynObjType *pdt );
00306 bool RemoveType( DynObjType *pdt );
00307 DynObjType* FindTypeFromNameAndId( const char* type, int type_id );
00308
00309 DynObj* CreateGetType( const char *lib, const char *type, int type_id, const DynI* pdi_init, DynObjType **ppdt );
00310
00311 bool GetUserTypes( ExpArrP<DynObjType*>&arr,
00312 DynObjType **types, int length );
00313 bool SortOutInstantiateTypes( ExpArrP<DynObjType*>&arr,
00314 DynObjType **types, int length,
00315 const char* instantiate_types );
00316
00317 int GetLibFlags( const char* paddr );
00318 DynObjLibI* docall GetLibraryAt( const void* paddr );
00319 bool LibHasType( DynObjLibI *plib, int type_id );
00320
00321 int GetCallerLib( OwnedDynObjLib *&polib, const char* pcaller_addr );
00322 OwnedDynObjLib* GetOwnedLib( const char* lib_name );
00323 int MayUnload( OwnedDynObjLib *polib, OwnedDynObjLib *polib_caller );
00324 bool UnloadLib( const char *lib_name, OwnedDynObjLib *polib_caller );
00325 DynI* SetLoadError( const char* error );
00326
00327 void FreeTrackers( );
00328
00329 MutexI *m_pmut;
00330 MallocI *m_pmalloc;
00331 TextIoI *m_ptio;
00332
00333 DynObjLib *m_lib_last;
00334 ExpArrP<OwnedDynObjLib*> m_libs;
00335 ExpArrPOwn<DynObjLib*> m_libs_dangling;
00336
00337 ExpArrP<DoModuleC*> m_modules;
00338 int m_type_id_nxt;
00339 int m_typeitem_typeid;
00340
00341
00342 int m_tmp_load_cnt;
00343 DynObjLibI* m_tmp_load_lib;
00344 const char* m_tmp_load_base;
00345 int m_tmp_load_flags;
00346 CharBuf m_cb_load_err;
00347
00348
00349 HashTable<void**,DynObjType*> m_vptr2type;
00350 HashTable<int,DynObjType*> m_id2type;
00351 HashTable<const char*,DynObjType*> m_name2type;
00352 ExpArrP<DynObjType*> m_types;
00353
00354 ExpArrPOwn<DelayedRegisterVTable*> m_delayed_vptrs;
00355 ExpArrP<DoBaseNode*> m_bases_unresolved;
00356
00357 HashTable<DynObj*,NotifiableI*> m_trackers;
00358
00359
00360 ExpArrP<DOError*> m_errors;
00361
00362
00363 HashTable<const void*,DOError*> m_obj_errors;
00364 ExpArrPOwn<DOError*> m_oe_allocated;
00365 ExpArrP<DOError*> m_oe_avail;
00366
00367 ExpArrP<char*> m_allocs;
00368
00369 int m_tmp_disable;
00370 };
00371
00373
00374
00375 struct DOError {
00376 DOError(int thid, int err_code, const char *err_str) :
00377 m_thid(thid), m_err_code(err_code), m_err_str(err_str) { }
00378 bool operator == (int thid) { return m_thid==thid; }
00379
00380 int m_thid;
00381 int m_err_code;
00382 CharBuf m_err_str;
00383 };
00384
00385
00386
00387 #if DO_USE_TEMPLATES==1
00388
00389
00390
00391 template<class T,class A, bool dyni_arg>
00392 struct DoCreator;
00393
00394 template<class T,class A>
00395 struct DoCreator<T,A,false> {
00396 static T *Create( A arg ){
00397
00398 DynData dd(arg);
00399 return DoRunTimeC::GetInstance().Create( doTypeWrapper<T>(), NULL, &dd );
00400 }
00401 static T *Create( const char* lib_name, A arg ){
00402 DynObjLibI *plib = DoRunTimeC::GetInstance().GetLib( lib_name );
00403 if( !plib ) return NULL;
00404
00405 DynData dd(arg);
00406 return plib->Create<T>( &dd );
00407 }
00408 };
00409
00410 template<class T,class A>
00411 struct DoCreator<T,A*,true> {
00412 static T *Create( A* parg ){
00413
00414 return DoRunTimeC::GetInstance().Create( doTypeWrapper<T>(), NULL, parg );
00415 }
00416 static T *Create( const char* lib_name, A* parg ){
00417 DynObjLibI *plib = DoRunTimeC::GetInstance().GetLib( lib_name );
00418 if( !plib ) return NULL;
00419 return plib->Create<T>( parg );
00420 }
00421 };
00422
00423 template<class T,class A>
00424 struct DoCreator<T,A&,true> {
00425 static T *Create( A& arg ){
00426
00427 return DoRunTimeC::GetInstance().Create( doTypeWrapper<T>(), NULL, &arg );
00428 }
00429 static T *Create( const char* lib_name, A& arg ){
00430 DynObjLibI *plib = DoRunTimeC::GetInstance().GetLib( lib_name );
00431 if( !plib ) return NULL;
00432 return plib->Create<T>( &arg );
00433 }
00434 };
00435
00437
00438
00447 template <class T, class A>
00448 T *do_new( A arg ){
00449 return DoCreator<T,A,DoIsTypeA<A,DynI>::v>::Create( arg );
00450 }
00451
00452 template <class T, class A>
00453 T *do_new( const char* lib_name, A arg ){
00454 return DoCreator<T,A,DoIsTypeA<A,DynI>::v>::Create( lib_name, arg );
00455 }
00456
00461 template <class T>
00462 T *do_new( ){
00463 return DoCreator<T,DynI*,true>::Create( (DynI*)NULL );
00464 }
00465
00466 #else
00467
00468 #endif // DO_USE_TEMPLATES==1
00469
00470
00471
00472
00473 #ifdef DO_IMPLEMENT_DORUNTIME
00474
00475
00476 DynObjType g_do_vtype_DoRunTimeC("DoRunTimeC","DoRunTimeI",DORUNTIMEC_TYPE_ID,0,sizeof(DoRunTimeC),NULL,NULL,__FILE__);
00477 SideBaseDecl g_do_vtype_sbd_DoRunTimeC_1("DoRunTimeC","NotifierI",sizeof(NotifierI),sidebase_offset<DoRunTimeC,NotifierI>(),NULL,-1,NULL);
00478 SideBaseDecl g_do_vtype_sbd_DoRunTimeC_2("DoRunTimeC","NamedRefI",sizeof(NamedRefI),sidebase_offset<DoRunTimeC,NamedRefI>(),NULL,-1,NULL);
00479 SideBaseDecl g_do_vtype_sbd_DoRunTimeC_3("DoRunTimeC","DortInternalI",sizeof(DortInternalI),sidebase_offset<DoRunTimeC,DortInternalI>(),NULL,-1,NULL);
00480 DynObjType* DoRunTimeC::doGetType( const DynI **pself ) const {
00481 if(pself) *pself=(const DynI*)(const void*)this;
00482 return &g_do_vtype_DoRunTimeC;
00483 }
00484 #endif //DO_IMPLEMENT_...
00485
00486
00487 #endif // DORUNTIME_H
00488
00489