home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / OWLSRC.PAK / APPDICT.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  11.9 KB  |  484 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // Copyright (c) 1991, 1997 by Borland International, All Rights Reserved
  4. //
  5. //$Revision:   10.7  $
  6. //
  7. // Implementation of class TAppDictionary, a dictionary of associations
  8. // between pids (Process IDs) and TApplication pointers.
  9. // Used to support GetApplicationObject().
  10. //----------------------------------------------------------------------------
  11. #include <owl/pch.h>
  12. #if !defined(OWL_APPDICT_H)
  13. # include <owl/appdict.h>
  14. #endif
  15. #if !defined(OWL_APPLICAT_H)
  16. # include <owl/applicat.h>
  17. #endif
  18. #if defined(BI_APP_DLL)
  19. # include <dos.h>
  20. # include <string.h>
  21. #endif
  22.  
  23. // Defining LOCALALLOC_TABLE instructs OWL to use LocalAlloc for the table
  24. //
  25. //#define LOCALALLOC_TABLE  
  26.  
  27. OWL_DIAGINFO;
  28.  
  29. #if defined(BI_NAMESPACE)
  30. namespace OWL {
  31. #endif
  32.  
  33. // Global dictionary used by OWL for EXE Application lookup
  34. //
  35. TAppDictionary& _OWLFUNC 
  36. OWLGetAppDictionary()
  37. {
  38.   static TAppDictionary OwlAppDictionary;
  39.   return OwlAppDictionary;
  40. };
  41.  
  42. #if defined(BI_NAMESPACE)
  43. } // namespace OWL
  44. #endif
  45.  
  46. //----------------------------------------------------------------------------
  47.  
  48. //
  49. // Dictionary implementation used to associate Pids (hTasks) with running Owl
  50. // apps when Owl is in a DLL or used by a DLL. 32bit only needs this when
  51. // running win32s (no per-instance data) since per-instance data makes it
  52. // unnecesasry
  53. //
  54. #if defined(BI_APP_DLL) || defined(BI_PLAT_WIN32)
  55.  
  56. #if defined(BI_NAMESPACE)
  57. namespace OWL {
  58. #endif
  59.  
  60. //
  61. // Abstract Base for dictionary implementation
  62. //
  63. class TAppDictImp {
  64.   public:
  65.     virtual ~TAppDictImp() {}
  66.  
  67.     virtual void                       Add(unsigned pid, TApplication* app) = 0;
  68.     virtual void                       Remove(unsigned pid) = 0;
  69.     virtual TAppDictionary::TEntry*    Lookup(unsigned pid) = 0;
  70.     virtual TAppDictionary::TEntry*    Lookup(TApplication* app) = 0;
  71.     virtual void                       Iterate(TAppDictionary::TEntryIterator) = 0;
  72.     virtual int                        GetCount() const = 0;
  73. };
  74.  
  75. //
  76. // Pid based Dictionary implementation for Win16, or Win32 w/o perinstance data
  77. //
  78. class TAppDictPidImp : public TAppDictImp {
  79.   public:
  80.     TAppDictPidImp();
  81.    ~TAppDictPidImp();
  82.  
  83.     void                       Add(unsigned pid, TApplication* app);
  84.     void                       Remove(unsigned pid);
  85.     TAppDictionary::TEntry*    Lookup(unsigned pid);
  86.     TAppDictionary::TEntry*    Lookup(TApplication* app);
  87.     void                       Iterate(TAppDictionary::TEntryIterator iter);
  88.     int                        GetCount() const;
  89.  
  90.   private:
  91.     enum {DefDictionarySize      = 10};
  92.     enum {DefDictionaryIncrement = 10};
  93.  
  94.     static TAppDictionary::TEntry*  AllocTable(int count);
  95.     static void                     FreeTable(TAppDictionary::TEntry* table);
  96.     TAppDictionary::TEntry*         GrowTable();
  97.  
  98.     int      NumEntries;
  99.     TAppDictionary::TEntry*         Table;
  100. };
  101.  
  102. #if defined(BI_PLAT_WIN32)
  103. //
  104. // Fast, small, per-instance data based Dictionary implementation (32bit only)
  105. //
  106. class TAppDictInstImp : public TAppDictImp {
  107.   public:
  108.     TAppDictInstImp() {Entry.App = 0;}
  109.  
  110.     void                       Add(unsigned pid, TApplication* app) {Entry.App = app;}
  111.     void                       Remove(unsigned) {Entry.App = 0;}
  112.     TAppDictionary::TEntry*    Lookup(unsigned) {return &Entry;}
  113.     TAppDictionary::TEntry*    Lookup(TApplication* app) {return &Entry;}
  114.     void                       Iterate(TAppDictionary::TEntryIterator iter)
  115.                                  {(*iter)(Entry);}
  116.     int                        GetCount() const {return Entry.App ? 1 : 0;}
  117.  
  118.   private:
  119.     TAppDictionary::TEntry     Entry;
  120. };
  121. #endif
  122.  
  123. #if defined(BI_NAMESPACE)
  124. } // namespace OWL
  125. #endif
  126.  
  127. //----------------------------------------------------------------------------
  128. // TAppDictionary implementation for DLLs only. EXE version is all inline.
  129. // Flat model must implement here, not inline, because same lib is used by DLLs
  130. //
  131.  
  132. //
  133. // Application dictionary constructor
  134. //
  135. TAppDictionary::TAppDictionary()
  136. {
  137. #if defined(BI_PLAT_WIN32)
  138.   if (TSystem::SupportsInstanceData())
  139.     Imp = new TAppDictInstImp();   // Could also use this case if linked to exe
  140.   else
  141.     Imp = new TAppDictPidImp();
  142. #else
  143.   Imp = new TAppDictPidImp();
  144. #endif
  145. }
  146.  
  147. //
  148. //
  149. //
  150. TAppDictionary::~TAppDictionary()
  151. {
  152.   DeleteCondemned();
  153.   delete Imp;
  154. }
  155.  
  156. //
  157. // Lookup and return the app assiciated with a given pid. May return 0.
  158. //
  159. TApplication*
  160. TAppDictionary::GetApplication(unsigned pid)
  161. {
  162.   if (!pid)
  163.     pid = ::GetCurrentProcessId();
  164.   TAppDictionary::TEntry* entry = Imp->Lookup(pid);
  165.   return entry ? entry->App : 0;
  166. }
  167.  
  168. //
  169. // Add an app to this dictionary
  170. //
  171. void
  172. TAppDictionary::Add(TApplication* app, unsigned pid)
  173. {
  174.   if (!pid)
  175.     pid = ::GetCurrentProcessId();
  176.   Imp->Add(pid, app);
  177. }
  178.  
  179. //
  180. // Remove a given app from this dictionary
  181. //
  182. void
  183. TAppDictionary::Remove(TApplication* app)
  184. {
  185.   TAppDictionary::TEntry* entry = Imp->Lookup(app);
  186.   if (entry) {
  187.     entry->App = 0;
  188.     entry->Pid = 0;
  189.   }
  190. }
  191.  
  192. //
  193. // Remove the app associated with a given pid from this dictionary
  194. //
  195. void
  196. TAppDictionary::Remove(unsigned pid)
  197. {
  198.   TAppDictionary::TEntry* entry = Imp->Lookup(pid);
  199.   if (entry) {
  200.     entry->App = 0;
  201.     entry->Pid = 0;
  202.   }
  203. }
  204.  
  205. //
  206. // Mark an app in this dictionary as being condemned by zeroing its pid.
  207. // Can then be deleted later.
  208. //
  209. void
  210. TAppDictionary::Condemn(TApplication* app)
  211. {
  212.   TAppDictionary::TEntry* entry = Imp->Lookup(app);
  213.   if (entry)
  214.     entry->Pid = 0;
  215. }
  216.  
  217. //
  218. //
  219. //
  220. static void _DeleteCondemnedIter(TAppDictionary::TEntry& entry)
  221. {
  222.   if (!entry.Pid) {
  223.     delete entry.App;
  224.     entry.App = 0;
  225.   }
  226. }
  227.  
  228. //
  229. // Iterate over the entries, invoking the supplied callback function.
  230. //
  231. void
  232. TAppDictionary::Iterate(TAppDictionary::TEntryIterator iter)
  233. {
  234.   Imp->Iterate(iter);
  235. }
  236.  
  237. //
  238. // Delete all of the condemned app objects in this dictionary
  239. //
  240. bool
  241. TAppDictionary::DeleteCondemned()
  242. {
  243.   Imp->Iterate(_DeleteCondemnedIter);
  244.   return Imp->GetCount() == 0;
  245. }
  246.  
  247. //
  248. // Exported entry for Debugger use
  249. //
  250. extern "C" TApplication* PASCAL _OWLFUNC
  251. GetTaskApplicationObject(unsigned pid)
  252. {
  253.   return OWLGetAppDictionary().GetApplication(pid);
  254. }
  255.  
  256. //----------------------------------------------------------------------------
  257. // TAppDictPidImp for DLL when there are real guts for pid lookup
  258. //
  259.  
  260. //
  261. // Construct an app dictionary implementation that looks up apps based on
  262. // process id
  263. //
  264. TAppDictPidImp::TAppDictPidImp()
  265. {
  266.   Table = AllocTable(DefDictionarySize);
  267.   NumEntries = DefDictionarySize;
  268. }
  269.  
  270. //
  271. // Destruct the app dictionary implementation object
  272. //
  273. TAppDictPidImp::~TAppDictPidImp()
  274. {
  275.   FreeTable(Table);
  276. }
  277.  
  278. //
  279. // Add an app to the dictionary given a process id
  280. //
  281. void
  282. TAppDictPidImp::Add(unsigned pid, TApplication* app)
  283. {
  284.   TAppDictionary::TEntry* freeEntry = 0;  // no free entry yet
  285.   TAppDictionary::TEntry* entry = Table;
  286.  
  287.   // First see if there is already a table; if so, replace the entry
  288.   //
  289.   for (; entry < &Table[NumEntries]; entry++) {
  290.     if (entry->Pid == pid) {
  291.       // Old app gets stomped, user must manage its lifetime
  292.       entry->App = app;        // already in table, update pointers
  293.       return;
  294.     }
  295.     else if (!freeEntry && !entry->Pid) {
  296.       freeEntry = entry;  // remember this first free entry for use later
  297.     }
  298.   }
  299.  
  300.   // Not in table. see if we encountered a free entry in the table
  301.   // if so, use it; otherwise grow the table & put entry in first new slot
  302.   //
  303.   entry = freeEntry ? freeEntry : GrowTable();
  304.   entry->Pid = pid;
  305.   entry->App = app;
  306. }
  307.  
  308. //
  309. // Remove an entry from the dictionary by looking up the process id
  310. //
  311. void
  312. TAppDictPidImp::Remove(unsigned pid)
  313. {
  314.   TAppDictionary::TEntry* entry = Lookup(pid);
  315.   if (entry) {
  316.     entry->App = 0;
  317.     entry->Pid = 0;
  318.   }
  319. }
  320.  
  321. //
  322. // Lookup and return the entry associated with a given pid. May return 0.
  323. //
  324. TAppDictionary::TEntry*
  325. TAppDictPidImp::Lookup(unsigned pid)
  326. {
  327.   for (TAppDictionary::TEntry* entry = Table; entry < Table+NumEntries; entry++)
  328.     if (entry->Pid == pid)
  329.       return entry;
  330.  
  331.   return 0;
  332. }
  333.  
  334. //
  335. // Lookup and return the entry associated with a given app. May return 0.
  336. //
  337. TAppDictionary::TEntry*
  338. TAppDictPidImp::Lookup(TApplication* app)
  339. {
  340.   for (TAppDictionary::TEntry* entry = Table; entry < Table+NumEntries; entry++)
  341.     if (entry->App == app)
  342.       return entry;
  343.  
  344.   return 0;
  345. }
  346.  
  347. //
  348. // Iterate over the entries, invoking the supplied callback function.
  349. //
  350. void
  351. TAppDictPidImp::Iterate(TAppDictionary::TEntryIterator iter)
  352. {
  353.   for (TAppDictionary::TEntry* entry = Table; entry < Table+NumEntries; entry++)
  354.     (*iter)(*entry);
  355. }
  356.  
  357. //
  358. // Return the count of entries in this dictionary.
  359. //
  360. int
  361. TAppDictPidImp::GetCount() const
  362. {
  363.   int i = 0;
  364.   for (TAppDictionary::TEntry* entry = Table; entry < Table+NumEntries; entry++)
  365.     if (entry->App)
  366.       i++;
  367.   return i;
  368. }
  369.  
  370. //
  371. // Allocate the actual table for the dictionary.
  372. // Optionally allocate the table from the local heap so that this DLL always
  373. // owns it, needed only if the RTL 
  374. //
  375. TAppDictionary::TEntry*
  376. TAppDictPidImp::AllocTable(int count)
  377. {
  378.   TAppDictionary::TEntry* entries;
  379. #if defined(LOCALALLOC_TABLE)
  380.   entries = (TAppDictionary::TEntry*)::LocalLock(::LocalAlloc(LMEM_ZEROINIT,
  381.                 count * sizeof(TAppDictionary::TEntry)));
  382.   if (!entries)
  383.     THROW( xalloc(__FILE__ __LINE__, count * sizeof(TAppDictionary::TEntry)) );
  384. #else
  385.   entries = new TAppDictionary::TEntry[count];
  386.   memset(entries, 0, count * sizeof(TAppDictionary::TEntry));
  387. #endif
  388.   return entries;
  389. }
  390.  
  391. //
  392. // Free all memory used by the table itself.
  393. //
  394. void
  395. TAppDictPidImp::FreeTable(TAppDictionary::TEntry* table)
  396. {
  397. #if defined(LOCALALLOC_TABLE)
  398.   if (!table)
  399.     return;
  400. #if defined(BI_PLAT_WIN32)
  401.   HLOCAL  hMem = ::LocalHandle(table);
  402. #else
  403.   HLOCAL  hMem = ::LocalHandle((void NEAR*)FP_OFF(table));  // strip off ds:
  404. #endif
  405.   if (::LocalUnlock(hMem))
  406.     ::LocalFree(hMem);
  407. #else
  408.   delete[] table;
  409. #endif
  410. }
  411.  
  412. //
  413. // Grow the size of the table by DefDictionaryIncrement delta
  414. //
  415. TAppDictionary::TEntry*
  416. TAppDictPidImp::GrowTable()
  417. {
  418.   // Save current table & entry count, & create new ones
  419.   //
  420.   int     oldNumEntries = NumEntries;
  421.   TAppDictionary::TEntry* oldTable = Table;
  422.  
  423.   NumEntries += DefDictionaryIncrement;
  424.   Table = AllocTable(NumEntries);
  425.  
  426.   // Copy old table to new one
  427.   //
  428.   memcpy(Table, oldTable, oldNumEntries * sizeof(TAppDictionary::TEntry));
  429.  
  430.   // Free old table
  431.   //
  432.   FreeTable(oldTable);
  433.  
  434.   // Return pointer to first entry in new block
  435.   //
  436.   return Table + oldNumEntries;
  437. }
  438.  
  439. #else  // 16bit static link exe models 
  440.  
  441. //
  442. // Delete all of the condemned app objects in this dictionary
  443. //
  444. bool TAppDictionary::DeleteCondemned() {
  445.   if (!E.Pid) {
  446.     delete E.App;
  447.     E.App = 0;
  448.   }
  449.   return false;
  450. }
  451.  
  452. #endif  // if/else defined(BI_APP_DLL) || defined(BI_PLAT_WIN32)
  453.  
  454. //----------------------------------------------------------------------------
  455.  
  456. #if defined(BI_NAMESPACE)
  457. namespace OWL {
  458. #endif 
  459.  
  460. //
  461. // Global function that calls GetApplication() on OWL's app-dictionary.
  462. // Used by EXEs, or DLLs statically linking OWL. Never returns 0, will make
  463. // an alias app if needed. Primarily for compatibility
  464. //
  465. TApplication* _OWLFUNC GetApplicationObject(unsigned pid)
  466. {
  467.   TApplication* app = OWLGetAppDictionary().GetApplication(pid);
  468.   if (app)
  469.     return app;
  470.  
  471.   // Make alias app (will add itself to dictionary) because OWL always needs an
  472.   // app around. If the app is non-OWL, no TApplication will have been
  473.   // constructed.
  474.   // Override default constructor argument to prevent overwrite of ::Module,
  475.   // and pass the default dictionary.
  476.   //
  477.   TModule* tempModule;
  478.   return new TApplication("ALIAS", tempModule, &(OWLGetAppDictionary()));
  479. }
  480.  
  481. #if defined(BI_NAMESPACE)
  482. } // namespace OWL
  483. #endif 
  484.