home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bc45 / owlsrc.pak / APPDICT.CPP next >
Encoding:
C/C++ Source or Header  |  1997-07-24  |  10.5 KB  |  428 lines

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