home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / threads.zip / readme.txt < prev   
Text File  |  1996-02-27  |  12KB  |  308 lines

  1.  
  2. DISCLAIMER
  3. ----------
  4.  
  5. Nothing in this package should be take to imply any plans are in place
  6. to satisfy any of the requirements listed in this document.  The
  7. interfaces and functions supplied by this prototype will certainly
  8. change before this type of support appears in the product, if it ever
  9. appears in the product.
  10.  
  11. Support will be provided only as time allows and given our current
  12. release schedule it looks like there will be no time for supporting
  13. this package.
  14.  
  15. We are however interested in feedback and comments.  Especially
  16. regarding your requirements for multi-threaded support in the Visual
  17. Builder and the notification framework.  Send comments to Steve
  18. Wasleski (WASLESKI at CARY).
  19.  
  20.  
  21. MOTIVATIONS
  22. -----------
  23.  
  24. During the development of a Conversational Communication Class Library
  25. for VisualAge C++ the following problems were encountered and had to
  26. be solved.  The solution to these problems is contained in this package.
  27.  
  28. 1) The VisualAge C++ Visual Builder and Open Class Library notification
  29.    framework do not support multi-threaded parts.
  30.  
  31. 2) Background (non-GUI) threads or applications (server applications in
  32.    a client/server solution, for example) are also not supported.  This
  33.    is primarily due to the user interface classes being the only source
  34.    of asynchronous events that start a chain of notifications.
  35.  
  36. The Conversational Communication Class Library is not in this package.
  37. It may be available in a later version of VisualAge C++.  Interested
  38. IBMers can get a driver.  Contact Paul Morris (RPMORRIS at RTPNOTES).
  39.  
  40.  
  41. REQUIREMENTS
  42. ------------
  43.  
  44. The solution to our problem had to meet the following requirements.
  45.  
  46. 1) Application developers that use multi-threaded parts created by
  47.    others should not need to know or care that the part spawns other
  48.    threads to do its work.
  49.  
  50. 2) Notifications from the part must all be asynchronously processed
  51.    on the same thread on which it was created even if the notifyObservers
  52.    call takes place one of the part's spawned threads.
  53.  
  54. 3) Event data must be supported even though the events are processed
  55.    asynchronously rather than synchronously as in the standard
  56.    notification mechanism.
  57.  
  58. 4) This asynchronous notification enables other sources of asynchronous
  59.    events other than the user via the user interface class library.
  60.    This fact must be taken advantage of to support creating background
  61.    threads and applications that can be driven by these new asynchronous
  62.    event sources.
  63.  
  64. These other requirements were identified during the creation of this
  65. prototype, but are not resolved by it.
  66.  
  67. 1) Explicit IThread object support in the visual builder.
  68.  
  69. 2) Asynchronous variable support.  That is, a new kind of variable
  70.    that will change any regular style part's notifications into
  71.    asynchronous notifications.
  72.  
  73. 3) Make a part's notification mechanism (list of observers) reentrant
  74.    on multiple threads rather than a single thread.
  75.  
  76.  
  77. FILES
  78. -----
  79.  
  80. Needed to create and use asynchronous notifiers:
  81.  
  82.   THREADS.ZIP  - Contains all these files except itself. Use
  83.                  PKUNZIP2 -d THREADS.ZIP to unpack into current directory.
  84.   README.TXT   - This file.
  85.   iasyntfy.hpp - The header file for IAsyncNotifier.  Note that
  86.                  IAsyncNotifier is an abstract base class and is a subclass
  87.                  of IStandardNotifier.
  88.   asyncnot.dll - The DLL the contains the implementation of IAsyncNotifier.
  89.   asyncnot.LIB - The import library for asyncnot.dll.
  90.   asyncnot.vbb - Contains the IAsyncNotifier non-visual part.  Note that
  91.                  IAsyncNotifier is an abstract base class.
  92.  
  93. Needed to rebuild the asyncnot.dll (this is all the source code):
  94.  
  95.   asyncnot.def - The module definition file
  96.   asyncnot.mak - Make file generated by WorkFrame/2
  97.   iasynbkg.cpp - Source for queuing to background threads
  98.   iasynbkg.hpp
  99.   iasyngui.cpp - Source for queuing to GUI threads
  100.   iasyngui.hpp
  101.   iasyntfy.cpp - Source code for IAsyncNotifier
  102.   iasyntfy.hpp
  103.   iasynthr.cpp - Abstract base class for queuing
  104.   iasynthr.hpp
  105.   ievntsem.cpp - A little event sem class (thanks to Rick Blevins)
  106.   ievntsem.hpp
  107.  
  108. In the SAMPLE subdirectory:
  109.   counter.vbb  - Contains the sample Counter non-visual part and two visual
  110.                  parts, CountMn and CountWnd, that use it.  Counter is a
  111.                  concrete subclass of IAsyncNotifier.
  112.   counter.hpv  - Declarations of Counter features.
  113.   counter.cpv  - Definitions of Counter features.
  114.  
  115.  
  116. RUNNING THE SAMPLE
  117. ------------------
  118.  
  119. 1) Put the asyncnot.dll in a directory in your LIBPATH.  The current
  120.    directory when you run the sample is okay if you have .; in your LIBPATH.
  121.  
  122. 2) Bring up the Visual Builder and load all the two VBB files (iasynfty.vbb
  123.    and counter.vbb).  I suggest starting the Visual Builder from a command line
  124.    with the current directory being the SAMPLE subdirectory.  The Visual
  125.    Builder exe is ICSVB.EXE.
  126.  
  127. 3) Generate part source for Counter.
  128.  
  129. 4) Generate part source for CountMn and CountWnd.
  130.  
  131. 5) Generate main for CountMn.
  132.  
  133. 6) Make sure the location of iasyntfy.hpp is in the INCLUDE and asyncnot.lib
  134.    is in the LIB environment variables.  Run nmake on CountMn.mak.
  135.  
  136. 7) Run CountMn.exe.
  137.  
  138. 8) When the window comes up, press the 'Create new count window' button.
  139.    A connection is fired that brings up a CountWnd window.  The CountWnd
  140.    part uses the Counter non-visual part that starts a thread that
  141.    increments a counter every second.
  142.  
  143.    Notice that the counter advances, but does not hang the rest of the
  144.    system since it is running on a separate thread.
  145.  
  146. 9) You can create multiple instances of CountWnd by returning to the
  147.    Counter Main Window and pressing the 'Create new count window' button
  148.    again.
  149.  
  150. 10) To exit the sample, close down all the windows.
  151.  
  152.  
  153. HOW TO CREATE MULTI-THREADED NON-VISUAL PARTS
  154. ---------------------------------------------
  155.  
  156. 1) Make your parts subclasses of IAsyncNotifier rather than
  157.    IStandardNotifier.
  158.  
  159. 2) If any of your notifications will have event data, create the
  160.    event data on the heap with the new operator.  (The actual data,
  161.    IString, etc., not the IEventData object.  It can be allocated
  162.    on the stack, since it will be copied INotificationEvent).
  163.    Do not clean up the event data as you normally would after
  164.    notifyObservers returns.  You will get a chance to clean it
  165.    up later as described in number 3.
  166.  
  167. 3) If any of your notifications will have event data, as described
  168.    in number 2, override IAsyncNotifier::notificationCleanUp.  It
  169.    will be called after each notification has really be processed.
  170.    Your declaration will look like this:
  171.  
  172.    virtual const MyClass & notificationCleanUp (
  173.                              const INotificationEvent & anEvent ) const;
  174.  
  175.    Your definition will look like this:
  176.    const MyClass & MyClass :: notificationCleanUp (
  177.                                 const INotificationEvent & anEvent ) const
  178.    {
  179.      // A subclass of MyClass must call MyClass::notificationCleanUp first.
  180.      IAsyncNotifier::notificationCleanUp ( anEvent );
  181.  
  182.      // If this is an event that we have event data that we need to
  183.      // clean up, clean it up.  Note that data types that fit in 4
  184.      // or less bytes will not need cleanup (int, Boolean, unsigned long,
  185.      // etc.).
  186.      switch ( anEvent.notificationId() )
  187.      {
  188.        case MyClass::event1Id :
  189.        {
  190.          MyEvent1Data * eventData = (MyEvent1Data *)(anEvent.eventData().asUnsignedLong());
  191.          delete eventData;
  192.          break;
  193.        }
  194.        case MyClass::event2Id :
  195.        {
  196.          MyEvent2Data * eventData = (MyEvent2Data *)(anEvent.eventData().asUnsignedLong());
  197.          delete eventData;
  198.          break;
  199.        }
  200.      }
  201.  
  202.      return *this;
  203.    }
  204.  
  205.  
  206. HOW TO USE MULTI-THREADED NON-VISUAL PARTS ON GUI THREADS
  207. ---------------------------------------------------------
  208.  
  209. Use them exactly the same way you use standard non-visual parts.
  210. You can create multiple async parts on one thread.
  211.  
  212. Note that an async part does not have to have an action that
  213. explicitly starts its thread(s).  They could be started in
  214. the constructor or as a by-product of normal interaction with
  215. the part.  Therefore, the threading can be completely hidden
  216. even if it is not in our sample.
  217.  
  218.  
  219. HOW TO USE MULTI-THREADED NON-VISUAL PARTS ON BACKGROUND THREADS
  220. ----------------------------------------------------------------
  221.  
  222. Use them same way you would use standard non-visual parts on a
  223. background thread.  You can create multiple async parts on one thread.
  224.  
  225. That is, create a non-visual part (standard or async).  Put other
  226. non-visual subparts (standard and/or async with at least one async
  227. part if the part itself is not async) on this new parts composition
  228. editor.  Interconnect the part and subparts as needed.
  229.  
  230. When you application sees fit, start a background thread (perhaps
  231. inside another async notifier) and create an instance of this new
  232. part on that thread.  Its subparts will be created and you will
  233. have at least one (more depending on the subparts) async notifier
  234. created on this new thread.
  235.  
  236. The rest of this can, probably should, be encapsulated within
  237. your new part.  Do what ever is needed (if anything) at least one
  238. of the async notifiers into a state where it will produce async
  239. events (open a conversation with a remote process, for example).
  240. Finally call IAsyncNotifier::run on this new thread.  Much like
  241. ICurrentApplication::run, it will not return until the thread is
  242. done with its work.  In this case that is defined as all the
  243. IAsyncNotifier instances that were created on the thread have
  244. been deleted.  When IAsyncNotifier::run returns, just run off the
  245. end of your thread and it will terminate.
  246.  
  247.  
  248. HOW TO USE MULTI-THREADED NON-VISUAL PARTS IN BACKGROUND APPLICATIONS
  249. ---------------------------------------------------------------------
  250.  
  251. This is a special case of the last section.
  252.  
  253. The difference is that thread 1 is already started for you.  You just
  254. need to Generate Main for the new part you created as described in the
  255. last section and you will almost be there.
  256.  
  257. In the generated .mak file change /pmtype:pm to /pmtype:vio.
  258.  
  259. In the generated .app file:
  260.  
  261.     Add these lines:
  262.  
  263.     #ifndef _IASYNTFY_
  264.     #include <iasyntfy.hpp>
  265.     #endif
  266.  
  267.     Remove these lines:
  268.  
  269.     #ifndef _IWINDOW_
  270.     #include <iwindow.hpp>
  271.     #endif
  272.  
  273.     #ifndef _IMSGBOX_
  274.     #include <imsgbox.hpp>
  275.     #endif
  276.  
  277.     Change the main function to look like this (removed lines are
  278.     commented and the added line is flagged):
  279.  
  280.     int main(int argc, char ** argv)
  281.     {
  282.        IApplication::current().setArgs(argc, argv);
  283.  
  284.        TestServer1 *iPart;
  285.     // IMessageBox::Response resp = IMessageBox::unknown;
  286.  
  287.     // do {
  288.     //    try {
  289.              iPart = new TestServer1();
  290.              iPart->initializePart();
  291.     //       }
  292.     //    catch (IException& exc) {
  293.     //       resp = IMessageBox(IWindow::desktopWindow()).show(exc);
  294.     //       }
  295.     //    }
  296.     // while (resp == IMessageBox::retry);
  297.  
  298.     // if (resp == IMessageBox::cancel) IApplication::current().exit();
  299.  
  300.     // IApplication::current().run();
  301.        IAsyncNotifier::run();                 // This line was added.
  302.        return 0;
  303.     }   //end main
  304.  
  305. You can, of course, create other background threads if you want in the
  306. manner described in the last section.
  307.  
  308.