Changeset 20393

Show
Ignore:
Timestamp:
06/29/07 17:15:56 (1 year ago)
Author:
patrick
Message:

Updated information about threads on Windows (we no longer use NSPR for
that) and with new features & old bugs of singletons.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • juggler/trunk/modules/vapor/doc/programmer.guide/programmer.guide.xml

    r19952 r20393  
    739739            <para>The serial port abstraction is handled differently than the 
    740740            other I/O abstraction components. We wrap two serial port 
    741             interfaces: termios and Win32 overlapped I/O<footnote> 
    742                   <para>This is the only Win32-native code in VPR. All other 
    743                   Win32 interfaces are handled by NSPR.</para> 
    744                </footnote>. Because NSPR does not provide a serial port layer, 
    745             we have to allow the termios to be used with NSPR on UNIX-based 
    746             platforms. While this makes the implementation a little clumsy and 
    747             the build system a little more complicated, it has little if any 
    748             impact on users. The point of the abstraction is to hide the 
    749             low-level details to provide a consistent interface across 
    750             platforms.</para> 
     741            interfaces: termios and Win32 overlapped I/O. Because NSPR does 
     742            not provide a serial port layer, we have to allow the termios to 
     743            be used with NSPR on UNIX-based platforms. While this makes the 
     744            implementation a little clumsy and the build system a little more 
     745            complicated, it has little if any impact on users. The point of 
     746            the abstraction is to hide the low-level details to provide a 
     747            consistent interface across platforms.</para> 
    751748         </section> 
    752749      </chapter> 
     
    14531450                     around Netscape Portable Runtime threads</para> 
    14541451                  </listitem> 
     1452 
     1453                  <listitem> 
     1454                     <para><classname>vpr::ThreadWin32</classname>: A wrapper 
     1455                     around Win32 threads</para> 
     1456                  </listitem> 
    14551457               </itemizedlist> 
    14561458 
     
    14711473               <classname>vpr::Thread</classname> interface. For example, if 
    14721474               compiling on Win32, the class 
    1473                <classname>vpr::ThreadNSPR</classname> is 
     1475               <classname>vpr::ThreadWin32</classname> is 
    14741476               <type>typedef</type>'d to be 
    14751477               <classname>vpr::Thread</classname>. Since the interface is 
     
    14921494                  Portable Runtime</ulink> (NSPR) threads<indexterm> 
    14931495                        <primary>NSPR</primary> 
    1494                      </indexterm>. We have removed the Win32-specific threads 
    1495                   because NSPR already supports that implementation. Further 
    1496                   implementations may be removed in favor of using what NSPR 
    1497                   offers. Doing this will offload much of our efforts onto the 
    1498                   NSPR. NSPR threads do not support all the features we have, 
    1499                   however, because they took the lowest-common-denominator 
    1500                   approach. As with all technology, there is a trade-off in 
    1501                   relieving some of our work load by using an existing 
    1502                   cross-platform thread implementation: our interface becomes 
    1503                   limited to what features that implementation provides. It 
    1504                   remains to be seen exactly how much of VPR's threading 
    1505                   subsystem will be removed, and those programmers who choose 
    1506                   to use it should be careful to watch the mailing lists for 
    1507                   discussions and announcements about changes.</para> 
     1496                     </indexterm>. NSPR threads do not support all the 
     1497                  features we have, however, because they took the 
     1498                  lowest-common-denominator approach. As with all technology, 
     1499                  there is a trade-off in relieving some of our work load by 
     1500                  using an existing cross-platform thread implementation: our 
     1501                  interface becomes limited to what features that 
     1502                  implementation provides. It remains to be seen exactly how 
     1503                  much of VPR's threading subsystem will be removed, and those 
     1504                  programmers who choose to use it should be careful to watch 
     1505                  the mailing lists for discussions and announcements about 
     1506                  changes.</para> 
    15081507               </note> 
    15091508            </section> 
     
    32523251 
    32533252         <para>A <firstterm>singleton</firstterm> is a common design pattern 
    3254          <xref linkend="ref.design.patterns" />. In VPR, the class 
     3253         <xref linkend="ref.design.patterns" />. VPR offers two ways to 
     3254         implement a singleton, both of which come from the header 
     3255         <filename>vpr/Util/Singleton.h</filename>. Libraries such as <ulink 
     3256         url="http://sourceforge.net/projects/loki-lib/">Loki</ulink> offer 
     3257         other approaches.</para> 
     3258 
     3259         <para>The first way of creating a singleton using VPR is to use the C 
     3260         preprocessor approach. In this case, we utilize two macros: 
     3261         <literal>vprSingletonHeader()</literal><indexterm> 
     3262               <primary>macros</primary> 
     3263 
     3264               <secondary>vprSingletonHeader</secondary> 
     3265            </indexterm> and <literal>vprSingletonImp()</literal><indexterm> 
     3266               <primary>macros</primary> 
     3267 
     3268               <secondary>vprSingletonImp</secondary> 
     3269            </indexterm>. One goes in the class declaration (in the header 
     3270         file), and the other goes with the class definition (in the 
     3271         <filename>.cpp</filename> file). The basic usage of these macros is 
     3272         shown in <xref linkend="example.vprSingletonHeader" /> and <xref 
     3273         linkend="example.vprSingletonImp" />.</para> 
     3274 
     3275         <example id="example.vprSingletonHeader"> 
     3276            <title>Use of <literal>vprSingletonHeader()</literal></title> 
     3277 
     3278            <programlisting>#include &lt;boost/noncopyable.hpp&gt; 
     3279#include &lt;vpr/Util/Singleton.h&gt; 
     3280 
     3281class MySingleton : boost::noncopyable 
     3282
     3283public: 
     3284   // Public operations ... 
     3285   void doSomething(); 
     3286 
     3287private: 
     3288   // Prevent instantiation by user code. 
     3289   MySingleton() 
     3290   { 
     3291      // Some constructor actions ... 
     3292   } 
     3293 
     3294   // Bring in the singleton declaration pieces. 
     3295   vprSingletonHeader(MySingleton); 
     3296};</programlisting> 
     3297         </example> 
     3298 
     3299         <example id="example.vprSingletonImp"> 
     3300            <title>Use of <literal>vprSingletonImp()</literal></title> 
     3301 
     3302            <programlisting>#include "MySingleton.h" 
     3303 
     3304// Bring in the singleton definition pieces. 
     3305vprSingletonImp(MySingleton); 
     3306 
     3307void MySingleton::doSomething() 
     3308
     3309   // Do something ... 
     3310}</programlisting> 
     3311         </example> 
     3312 
     3313         <para>In some cases, an object may need to perform some 
     3314         initialization steps after being instantiated. In that case, use the 
     3315         macro <literal>vprSingletonHeaderWithInitFunc()</literal><indexterm> 
     3316               <primary>macros</primary> 
     3317 
     3318               <secondary>vprSingletonHeaderWithInitFunc</secondary> 
     3319            </indexterm> instead of <literal>vprSingletonHeader()</literal> 
     3320         and <literal>vprSingletonImpWithInitFunc()</literal><indexterm> 
     3321               <primary>macros</primary> 
     3322 
     3323               <secondary>vprSingletonImpWithInitFunc</secondary> 
     3324            </indexterm> instead of <literal>vprSingletonImp()</literal>. An 
     3325         example of this is shown in <xref 
     3326         linkend="example.vprSingletonHeaderWithInitFunc" /> and <xref 
     3327         linkend="example.vprSingletonImpWithInitFunc" />. The initialization 
     3328         method must take no parameters and return nothing.</para> 
     3329 
     3330         <example id="example.vprSingletonHeaderWithInitFunc"> 
     3331            <title>Use of 
     3332            <literal>vprSingletonHeaderWithInitFunc()</literal></title> 
     3333 
     3334            <programlisting>#include &lt;boost/noncopyable.hpp&gt; 
     3335#include &lt;vpr/Util/Singleton.h&gt; 
     3336 
     3337class MySingleton : boost::noncopyable 
     3338
     3339public: 
     3340   // Public operations ... 
     3341   void doSomething(); 
     3342 
     3343private: 
     3344   // Prevent instantiation by user code. 
     3345   MySingleton() 
     3346   { 
     3347      // Some constructor actions ... 
     3348   } 
     3349 
     3350   void init() 
     3351   { 
     3352      // Perform initialization operations ... 
     3353   } 
     3354 
     3355   // Bring in the singleton declaration pieces. 
     3356   vprSingletonHeaderWithInitFunc(MySingleton, init); 
     3357};</programlisting> 
     3358         </example> 
     3359 
     3360         <example id="example.vprSingletonImpWithInitFunc"> 
     3361            <title>Use of 
     3362            <literal>vprSingletonImpWithInitFunc()</literal></title> 
     3363 
     3364            <programlisting>#include "MySingleton.h" 
     3365 
     3366// Bring in the singleton definition pieces. 
     3367vprSingletonImp(MySingleton); 
     3368 
     3369void MySingleton::doSomething() 
     3370
     3371   // Do something ... 
     3372}</programlisting> 
     3373         </example> 
     3374 
     3375         <para>In VPR 1.1 and beyond, the destructor for singleton objects is 
     3376         called when the application exits. This can result in some 
     3377         undesirable behavior if one singleton depends on another, thus 
     3378         meaning that the order in which they are deleted can make a 
     3379         difference. Without any specific ordering being imposed, singleton 
     3380         objects are deleted in the reverse order in which they were 
     3381         instantiated. Since it is not always possible to control the order of 
     3382         instantiation, it can be useful to control the order of destruction. 
     3383         This can be done by setting the <quote>lifetime</quote> or 
     3384         <quote>longevity</quote> of a singleton. The higher the longevity, 
     3385         the later that the singleton will be deleted when the application is 
     3386         exiting. This is accomplished using either 
     3387         <literal>vprSingletonImpLifetime()</literal><indexterm> 
     3388               <primary>macros</primary> 
     3389 
     3390               <secondary>vprSingletonImpLifetime</secondary> 
     3391            </indexterm> or 
     3392         <literal>vprSingletonImpLifetimeWithInitFunc()</literal><indexterm> 
     3393               <primary>macros</primary> 
     3394 
     3395               <secondary>vprSingletonImpLifetimeWithInitFunc</secondary> 
     3396            </indexterm>. The macro used must be paired with either 
     3397         <literal>vprSingletonHeader()</literal> or 
     3398         <literal>vprSingletonHeaderWithInitFunc()</literal>. Usage of 
     3399         <literal>vprSingletonImpLifetime()</literal> is shown in <xref 
     3400         linkend="example.vprSingletonImpLifetime" />.</para> 
     3401 
     3402         <example id="example.vprSingletonImpLifetime"> 
     3403            <title>Use of <literal>vprSingletonImpLifetime()</literal></title> 
     3404 
     3405            <programlisting>#include "MySingleton.h" 
     3406 
     3407// Bring in the singleton definition pieces. Delete it early 
     3408// in the application exit process. 
     3409vprSingletonImpLifetime(MySingleton, 10); 
     3410 
     3411void MySingleton::doSomething() 
     3412
     3413   // Do something ... 
     3414}</programlisting> 
     3415         </example> 
     3416 
     3417         <para>The other approach uses a template class called 
    32553418         <classname>vpr::Singleton&lt;T&gt;<indexterm> 
    32563419               <primary>classes</primary> 
    32573420 
    32583421               <secondary>vpr::Singleton&lt;T&gt;</secondary> 
    3259             </indexterm></classname> provides a template-based implementation 
    3260          of this pattern. An example of its use is as follows:</para> 
    3261  
    3262          <programlisting linenumbering="numbered">class MySingleton : public vpr::Singleton&lt;MySingleton&gt; 
     3422            </indexterm></classname>. An example of its use is shown in <xref 
     3423         linkend="example.vpr.Singleton.template" />.</para> 
     3424 
     3425         <example id="example.vpr.Singleton.template"> 
     3426            <title>Use of 
     3427            <classname>vpr::Singleton&lt;T&gt;</classname></title> 
     3428 
     3429            <programlisting linenumbering="numbered">#include &lt;boost/noncopyable.hpp&gt; 
     3430#include &lt;vpr/Util/Singleton.h&gt; 
     3431 
     3432class MySingleton 
     3433   : public vpr::Singleton&lt;MySingleton&gt; 
     3434   , boost::noncopyable 
    32633435{ 
    32643436public: 
     
    32783450      // Some constructor actions ... 
    32793451   } 
    3280  
    3281    // Prevent copying. 
    3282    MySingleton(const MySingleton&amp; o) 
    3283    { 
    3284       ; 
    3285    } 
    3286  
    3287    MySingleton&amp; operator=(const MySingleton&amp; o) 
    3288    { 
    3289       ; 
    3290    } 
    32913452};</programlisting> 
    3292  
    3293          <para>Getting a reference to the singleton (and calling the 
     3453         </example> 
     3454 
     3455         <warning> 
     3456            <para>Singletons implemented using 
     3457            <classname>vpr::Singleton&lt;T&gt;</classname> do not work across 
     3458            DLLs on <productname class="registered">Microsoft 
     3459            Windows</productname> or shared libraries 
     3460            (<filename>.dylib</filename> files) on Mac OS X. If the singleton 
     3461            is for internal use only, such as in the case of an application, 
     3462            then using <classname>vpr::Singleton&lt;T&gt;</classname> is fine. 
     3463            Otherwise, the C preprocessor approach must be used.</para> 
     3464         </warning> 
     3465 
     3466         <para>In all singleton implementations, getting a reference to the 
     3467         singleton object (and calling the 
    32943468         <methodname>doSomething()</methodname> method) is then done using the 
    32953469         following syntax:</para> 
    32963470 
    32973471         <programlisting>MySingleton::instance()-&gt;doSomething();</programlisting> 
    3298  
    3299          <para>There is some old code in 
    3300          <filename>vpr/Util/Singleton.h</filename> for a singleton 
    3301          implementation based on macros defined by the C preprocessor. We 
    3302          maintain this code for backwards compatibility, but we recommend that 
    3303          new code use the template-based implementation described 
    3304          above.</para> 
    33053472      </chapter> 
    33063473 
     
    34043571         termios serial I/O. When compiling on Windows, where only NSPR is 
    34053572         used, the domain specifies the use of native Win32 serial I/O and 
    3406          NSPR for everything else. Moreover, the simulated sockets can be 
    3407          mixed with any of the threading subsystems using this 
    3408          paradigm.</para> 
     3573         NSPR for socket I/O. Moreover, the simulated sockets can be mixed 
     3574         with any of the threading subsystems using this paradigm.</para> 
    34093575      </appendix> 
    34103576