//---------------------------------------------------------------------------- // ObjectWindows // (C) Copyright 1991, 1994 by Borland International, All Rights Reserved // // Implementation of class TAppDictionary, a dictionary of // associations between pids (Process IDs) and TApplication pointers. // Used to support GetApplicationObject(). //---------------------------------------------------------------------------- #include #include #include #if defined(BI_APP_DLL) # include # include #endif //#define LOCALALLOC_TABLE // define to use local alloc for table // // Global dictionary used by OWL for EXE Application lookup // TAppDictionary _OWLDATA OwlAppDictionary; // // Dictionary implementation used to associate Pids (hTasks) with running Owl // apps when Owl is in a DLL or used by a DLL. 32bit only needs this when // running win32s (no per-instance data) since per-instance data makes it // unnecesasry // #if defined(BI_APP_DLL) || defined(BI_PLAT_WIN32) // // Abstract Base for dictionary implementation // class TAppDictImp { public: virtual ~TAppDictImp() {} virtual void Add(unsigned pid, TApplication* app) = 0; virtual void Remove(unsigned pid) = 0; virtual TAppDictionary::TEntry* Lookup(unsigned pid) = 0; virtual TAppDictionary::TEntry* Lookup(TApplication* app) = 0; virtual void Iterate(TAppDictionary::TEntryIterator) = 0; virtual int GetCount() const = 0; }; // // Pid based Dictionary implementation for Win16, or Win32 w/o perinstance data // class TAppDictPidImp : public TAppDictImp { public: TAppDictPidImp(); ~TAppDictPidImp(); void Add(unsigned pid, TApplication* app); void Remove(unsigned pid); TAppDictionary::TEntry* Lookup(unsigned pid); TAppDictionary::TEntry* Lookup(TApplication* app); void Iterate(TAppDictionary::TEntryIterator iter); int GetCount() const; private: enum {DefDictionarySize = 10}; enum {DefDictionaryIncrement = 10}; static TAppDictionary::TEntry* AllocTable(int count); static void FreeTable(TAppDictionary::TEntry* table); TAppDictionary::TEntry* GrowTable(); int NumEntries; TAppDictionary::TEntry* Table; }; #if defined(BI_PLAT_WIN32) // // Local flag used for Win32 to skip dictionary when per-instance data is // available. Assume per-instance data is only unsupported in Win32s // static int PerInstanceData = !( (::GetVersion()&0x80000000) && (::GetVersion()&0xFF) < 4); // // Fast, small, per-instance data based Dictionary implementation (32bit only) // class TAppDictInstImp : public TAppDictImp { public: TAppDictInstImp() {Entry.App = 0;} void Add(unsigned pid, TApplication* app) {Entry.App = app;} void Remove(unsigned) {Entry.App = 0;} TAppDictionary::TEntry* Lookup(unsigned) {return &Entry;} TAppDictionary::TEntry* Lookup(TApplication* app) {return &Entry;} void Iterate(TAppDictionary::TEntryIterator iter) {(*iter)(Entry);} int GetCount() const {return Entry.App ? 1 : 0;} private: TAppDictionary::TEntry Entry; }; #endif //---------------------------------------------------------------------------- // TAppDictionary implementation for DLLs only. EXE version is all inline. // Flat model must implement here, not inline, because same lib is used by DLLs // // // Application dictionary constructor // TAppDictionary::TAppDictionary() { #if defined(BI_PLAT_WIN32) if (PerInstanceData) // could also use this case if linked to exe Imp = new TAppDictInstImp(); else Imp = new TAppDictPidImp(); #else Imp = new TAppDictPidImp(); #endif } // // // TAppDictionary::~TAppDictionary() { DeleteCondemned(); delete Imp; } // // Lookup and return the app assiciated with a given pid. May return 0. // TApplication* TAppDictionary::GetApplication(unsigned pid) { if (!pid) pid = ::GetCurrentProcessId(); TAppDictionary::TEntry* entry = Imp->Lookup(pid); return entry ? entry->App : 0; } // // Add an app to this dictionary // void TAppDictionary::Add(TApplication* app, unsigned pid) { if (!pid) pid = ::GetCurrentProcessId(); Imp->Add(pid, app); } // // Remove a given app from this dictionary // void TAppDictionary::Remove(TApplication* app) { TAppDictionary::TEntry* entry = Imp->Lookup(app); if (entry) { entry->App = 0; entry->Pid = 0; } } // // Remove the app associated with a given pid from this dictionary // void TAppDictionary::Remove(unsigned pid) { TAppDictionary::TEntry* entry = Imp->Lookup(pid); if (entry) { entry->App = 0; entry->Pid = 0; } } // // Mark an app in this dictionary as being condemned by zeroing its pid. // Can then be deleted later. // void TAppDictionary::Condemn(TApplication* app) { TAppDictionary::TEntry* entry = Imp->Lookup(app); if (entry) entry->Pid = 0; } // // // static void sDeleteCondemnedIter(TAppDictionary::TEntry& entry) { if (!entry.Pid) { delete entry.App; entry.App = 0; } } // // // void TAppDictionary::Iterate(TAppDictionary::TEntryIterator iter) { Imp->Iterate(iter); } // // // bool TAppDictionary::DeleteCondemned() { Imp->Iterate(sDeleteCondemnedIter); return Imp->GetCount() == 0; } // // Exported entry for Debugger use // extern "C" TApplication* PASCAL _OWLFUNC GetTaskApplicationObject(unsigned pid) { return ::OwlAppDictionary.GetApplication(pid); } //---------------------------------------------------------------------------- // TAppDictPidImp for DLL when there are real guts for pid lookup // TAppDictPidImp::TAppDictPidImp() { Table = AllocTable(DefDictionarySize); NumEntries = DefDictionarySize; } // // // TAppDictPidImp::~TAppDictPidImp() { FreeTable(Table); } // // // void TAppDictPidImp::Add(unsigned pid, TApplication* app) { TAppDictionary::TEntry* freeEntry = 0; // no free entry yet // First see if there is already a table; if so, replace the entry // for (TAppDictionary::TEntry* entry = Table; entry < &Table[NumEntries]; entry++) { if (entry->Pid == pid) { // Old app gets stomped, user must manage its lifetime entry->App = app; // already in table, update pointers return; } else if (!freeEntry && !entry->Pid) { freeEntry = entry; // remember this first free entry for use later } } // Not in table. see if we encountered a free entry in the table // if so, use it; otherwise grow the table & put entry in first new slot // entry = freeEntry ? freeEntry : GrowTable(); entry->Pid = pid; entry->App = app; } // // // void TAppDictPidImp::Remove(unsigned pid) { TAppDictionary::TEntry* entry = Lookup(pid); if (entry) { entry->App = 0; entry->Pid = 0; } } // // Lookup and return the entry associated with a given pid. May return 0. // TAppDictionary::TEntry* TAppDictPidImp::Lookup(unsigned pid) { for (TAppDictionary::TEntry* entry = Table; entry < Table+NumEntries; entry++) if (entry->Pid == pid) return entry; return 0; } // // Lookup and return the entry associated with a given app. May return 0. // TAppDictionary::TEntry* TAppDictPidImp::Lookup(TApplication* app) { for (TAppDictionary::TEntry* entry = Table; entry < Table+NumEntries; entry++) if (entry->App == app) return entry; return 0; } // // // void TAppDictPidImp::Iterate(TAppDictionary::TEntryIterator iter) { for (TAppDictionary::TEntry* entry = Table; entry < Table+NumEntries; entry++) (*iter)(*entry); } // // // int TAppDictPidImp::GetCount() const { int i = 0; for (TAppDictionary::TEntry* entry = Table; entry < Table+NumEntries; entry++) if (entry->App) i++; return i; } // // Allocate the table from the local heap so that this DLL always owns it. // TAppDictionary::TEntry* TAppDictPidImp::AllocTable(int count) { TAppDictionary::TEntry* entries; #if defined(LOCALALLOC_TABLE) entries = (TAppDictionary::TEntry*)::LocalLock(::LocalAlloc(LMEM_ZEROINIT, count * sizeof(TAppDictionary::TEntry))); if (!entries) THROW( xalloc(__FILE__ __LINE__, count * sizeof(TAppDictionary::TEntry)) ); #else entries = new TAppDictionary::TEntry[count]; memset(entries, 0, count * sizeof(TAppDictionary::TEntry)); #endif return entries; } // // // void TAppDictPidImp::FreeTable(TAppDictionary::TEntry* table) { #if defined(LOCALALLOC_TABLE) if (!table) return; #if defined(BI_PLAT_WIN32) HLOCAL hMem = ::LocalHandle(table); #else HLOCAL hMem = ::LocalHandle((void NEAR*)FP_OFF(table)); // strip off ds: #endif if (::LocalUnlock(hMem)) ::LocalFree(hMem); #else delete[] table; #endif } // // // TAppDictionary::TEntry* TAppDictPidImp::GrowTable() { // Save current table & entry count, & create new ones // int oldNumEntries = NumEntries; TAppDictionary::TEntry* oldTable = Table; NumEntries += DefDictionaryIncrement; Table = AllocTable(NumEntries); // copy old table to new one // memcpy(Table, oldTable, oldNumEntries * sizeof(TAppDictionary::TEntry)); // Free old table // FreeTable(oldTable); // return pointer to first entry in new block // return Table + oldNumEntries; } #endif // defined(BI_APP_DLL) // // Global function that calls GetApplication() on owl's app-dictionary. // Used by EXEs, or DLLs statically linking Owl. Never returns 0, will make // an alias app if needed. Primarily for compatibility // TApplication* _OWLFUNC GetApplicationObject(unsigned pid) { TApplication* app = ::OwlAppDictionary.GetApplication(pid); if (app) return app; // Make alias app (will add itself to dictionary) because Owl always needs an // app around. If the app is non-Owl, no TApplication will have been // constructed. // Override default constructor argument to prevent overwrite of ::Module, // and pass the default dictionary. // TModule* tempModule; return new TApplication("ALIAS", tempModule, &OwlAppDictionary); }