Changeset 20396

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

Merge updates from the trunk:

r20393: Updated information about threads on Windows (we no longer use

NSPR for that) and with new features & old bugs of singletons.

r20394: Updated documentation pertaining to synchronization primitives.

r20395: Removed a note about signal handling that is no longer true.

Files:

Legend:

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

    r19951 r20396  
    4444 
    4545      <para>Internally, VPR wraps platform-specific APIs such as BSD sockets, 
    46       POSIX threads, and Win32 overlapped I/O. Depending upon how it is 
    47       compiled, it may also wrap the <ulink 
     46      POSIX threads, Win32 threads, and Win32 overlapped I/O. Depending upon 
     47      how it is compiled, it may also wrap the <ulink 
    4848      url="http://www.mozilla.org/projects/nspr/index.html">Netscape Portable 
    4949      Runtime</ulink> (<glossterm linkend="gloss.nspr">NSPR</glossterm>), 
     
    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> 
     
    12541251               <programlisting>thread-&gt;resume();</programlisting> 
    12551252 
    1256                <para>On successful completion, both methods return 
    1257                <constant>vpr::ReturnStatus::Succeed</constant>. If the 
    1258                operation could not be performed for some reason, 
    1259                <constant>vpr::ReturnStatus::Fail</constant> is returned to 
    1260                indicate error status.</para> 
     1253               <para>If something goes wrong when suspending or resuming, 
     1254               <exceptionname>vpr::IllegalArgumentException</exceptionname><indexterm> 
     1255                     <primary>exceptions</primary> 
     1256 
     1257                     <secondary>vpr::IllegalArgumentException</secondary> 
     1258                  </indexterm> is thrown. Otherwise, these methods return 
     1259               nothing upon successful completion.</para> 
    12611260            </section> 
    12621261 
     
    13001299thread-&gt;setPrio(prio);</programlisting> 
    13011300 
    1302                <para>On successful completion, both methods return 
    1303                <constant>vpr::ReturnStatus::Succeed</constant>. If the 
    1304                operation could not be performed for some reason, 
    1305                <constant>vpr::ReturnStatus::Fail</constant> is returned to 
    1306                indicate error status.</para> 
     1301               <para>If something goes wrong when querying or changing the 
     1302               priority of the thread, 
     1303               <exceptionname>vpr::IllegalArgumentException</exceptionname><indexterm> 
     1304                     <primary>exceptions</primary> 
     1305 
     1306                     <secondary>vpr::IllegalArgumentException</secondary> 
     1307                  </indexterm> is thrown. Otherwise, these methods return 
     1308               nothing upon successful completion.</para> 
    13071309            </section> 
    13081310 
     
    13461348               operating system, and the thread is expected to handle it 
    13471349               properly. This version of the <methodname>kill()</methodname> 
    1348                method returns <constant>vpr::ReturnStatus::Succeed</constant> 
    1349                if the signal is sent successfully. Otherwise, 
    1350                <constant>vpr::ReturnStatus::Fail</constant> is returned to 
    1351                indicate that an error occurred.</para> 
     1350               method throws 
     1351               <exceptionname>vpr::IllegalArgumentException</exceptionname><indexterm> 
     1352                     <primary>exceptions</primary> 
     1353 
     1354                     <secondary>vpr::IllegalArgumentException</secondary> 
     1355                  </indexterm> if an error occurs. Otherwise, this method 
     1356               returns nothing upon successful compltion.</para> 
    13521357            </section> 
    13531358 
     
    14531458                     around Netscape Portable Runtime threads</para> 
    14541459                  </listitem> 
     1460 
     1461                  <listitem> 
     1462                     <para><classname>vpr::ThreadWin32</classname>: A wrapper 
     1463                     around Win32 threads</para> 
     1464                  </listitem> 
    14551465               </itemizedlist> 
    14561466 
     
    14711481               <classname>vpr::Thread</classname> interface. For example, if 
    14721482               compiling on Win32, the class 
    1473                <classname>vpr::ThreadNSPR</classname> is 
     1483               <classname>vpr::ThreadWin32</classname> is 
    14741484               <type>typedef</type>'d to be 
    14751485               <classname>vpr::Thread</classname>. Since the interface is 
     
    14921502                  Portable Runtime</ulink> (NSPR) threads<indexterm> 
    14931503                        <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> 
     1504                     </indexterm>. NSPR threads do not support all the 
     1505                  features we have, however, because they took the 
     1506                  lowest-common-denominator approach. As with all technology, 
     1507                  there is a trade-off in relieving some of our work load by 
     1508                  using an existing cross-platform thread implementation: our 
     1509                  interface becomes limited to what features that 
     1510                  implementation provides. It remains to be seen exactly how 
     1511                  much of VPR's threading subsystem will be removed, and those 
     1512                  programmers who choose to use it should be careful to watch 
     1513                  the mailing lists for discussions and announcements about 
     1514                  changes.</para> 
    15081515               </note> 
    15091516            </section> 
     
    24542461               <para>The semaphore <varname>sema</varname> now controls access 
    24552462               to only four resources.</para> 
     2463 
     2464               <para>Creation of a semaphore can fail, and if it does, the 
     2465               <classname>vpr::Semaphore</classname> constructor throws an 
     2466               exception of type 
     2467               <exceptionname>vpr::ResourceException</exceptionname><indexterm> 
     2468                     <primary>exceptions</primary> 
     2469 
     2470                     <secondary>vpr::ResourceException</secondary> 
     2471                  </indexterm>. If creation of the semaphore succeeds, then 
     2472               lock and unlock operations on that semaphore are guaranteed to 
     2473               succeed.</para> 
    24562474            </section> 
    24572475 
     
    24752493               blocking call, so if the semaphore's value is less than or 
    24762494               equal to 0, the thread requesting the lock will block until the 
    2477                semaphore's value is greater than 0. If the lock is acquired, 
    2478                <constant>vpr::ReturnStatus::Succeed</constant> is returned. If 
    2479                the attempt to lock the semaphore fails for some reason, 
    2480                <constant>vpr::ReturnStatus::Fail</constant> is 
    2481                returned.</para> 
     2495               semaphore's value is greater than 0. If the acquisition of the 
     2496               semaphore would cause a deadlock (because the thread already 
     2497               holds the semaphore lock), 
     2498               <exceptionname>vpr::DeadlockException</exceptionname><indexterm> 
     2499                     <primary>exceptions</primary> 
     2500 
     2501                     <secondary>vpr::DeadlockException</secondary> 
     2502                  </indexterm> is thrown. Otherwise, the method is guaranteed 
     2503               to return when the lock is acquired.</para> 
    24822504            </section> 
    24832505 
     
    24972519               <programlisting>sema.release();</programlisting> 
    24982520 
    2499                <para>If the locked semaphore is released successfully, 
    2500                <constant>vpr::ReturnStatus::Succeed</constant> is returned. 
    2501                Otherwise, <constant>vpr::ReturnStatus::Fail</constant> is 
    2502                returned.</para> 
     2521               <para>This method is guaranteed to return successfully.</para> 
    25032522            </section> 
    25042523 
     
    25352554                     <para><classname>vpr::SemaphoreNSPR</classname>: An 
    25362555                     implementation of semaphores using NSPR primitives</para> 
     2556                  </listitem> 
     2557 
     2558                  <listitem> 
     2559                     <para><classname>vpr::SemaphoreWin32</classname>: A 
     2560                     wrapper around Win32 semaphores</para> 
    25372561                  </listitem> 
    25382562               </itemizedlist> 
     
    26252649               <programlisting>vpr::Mutex mutex;</programlisting> 
    26262650 
    2627                <para>There is nothing more to say this time.</para> 
     2651               <para>Creation of a mutex can fail, and if it does, the 
     2652               <classname>vpr::Mutex</classname> constructor throws an 
     2653               exception of type 
     2654               <exceptionname>vpr::ResourceException</exceptionname><indexterm> 
     2655                     <primary>exceptions</primary> 
     2656 
     2657                     <secondary>vpr::ResourceException</secondary> 
     2658                  </indexterm>. If creation of the mutex succeeds, then lock 
     2659               and unlock operations on that mutex are guaranteed to 
     2660               succeed.</para> 
    26282661            </section> 
    26292662 
     
    26472680               blocking call, so if the mutex is already locked by another 
    26482681               thread, the thread requesting the lock will block until the 
    2649                mutex is released by the other thread. If the lock is acquired, 
    2650                <constant>vpr::ReturnStatus::Succeed</constant> is returned. If 
    2651                the attempt to lock the semaphore fails for some reason, 
    2652                <constant>vpr::ReturnStatus::Fail</constant> is 
    2653                returned.</para> 
     2682               mutex is released by the other thread. If the acquisition of 
     2683               the mutex would cause a deadlock (because the thread already 
     2684               holds the mutex), 
     2685               <exceptionname>vpr::DeadlockException</exceptionname><indexterm> 
     2686                     <primary>exceptions</primary> 
     2687 
     2688                     <secondary>vpr::DeadlockException</secondary> 
     2689                  </indexterm> is thrown. Otherwise, the method is guaranteed 
     2690               to return when the lock is acquired.</para> 
    26542691            </section> 
    26552692 
     
    26712708               as follows:</para> 
    26722709 
    2673                <programlisting>mutex.tryAcquire();</programlisting> 
    2674  
    2675                <para>If the mutex is locked, 
    2676                <constant>vpr::ReturnStatus::Succeed</constant> is returned. 
    2677                Otherwise, <constant>vpr::ReturnStatus::Fail</constant> is 
    2678                returned. The call does not block.</para> 
     2710               <programlisting>const bool locked = mutex.tryAcquire();</programlisting> 
     2711 
     2712               <para>If the mutex is locked, <constant>true</constant> is 
     2713               returned. Otherwise, <constant>false</constant> is returned. 
     2714               The call does not block.</para> 
    26792715            </section> 
    26802716 
     
    26932729               follows:</para> 
    26942730 
    2695                <programlisting>int state = mutex.test();</programlisting> 
     2731               <programlisting>const bool locked = mutex.test();</programlisting> 
    26962732 
    26972733               <para>If the mutex is <emphasis>not</emphasis> locked, 
    2698                <constant>vpr::ReturnStatus::Fail</constant> is returned. 
    2699                Otherwise, <constant>vpr::ReturnStatus::Succeed</constant> is 
    2700                returned.</para> 
     2734               <constant>false</constant> is returned. Otherwise, 
     2735               <constant>true</constant> is returned.</para> 
    27012736            </section> 
    27022737 
     
    27162751               <programlisting>mutex.release();</programlisting> 
    27172752 
    2718                <para>If the locked mutex is released successfully, 
    2719                <constant>vpr::ReturnStatus::Succeed</constant> is returned. 
    2720                Otherwise, <constant>vpr::ReturnStatus::Fail</constant> is 
    2721                returned.</para> 
     2753               <para>This method is guaranteed to return successfully.</para> 
    27222754            </section> 
    27232755 
     
    27562788                     <para><classname>vpr::MutexNSPR</classname>: A wrapper 
    27572789                     around NSPR mutexes</para> 
     2790                  </listitem> 
     2791 
     2792                  <listitem> 
     2793                     <para><classname>vpr::MutexWin32</classname>: A wrapper 
     2794                     around Win32 mutexes</para> 
    27582795                  </listitem> 
    27592796               </itemizedlist> 
     
    28502887               <programlisting>vpr::CondVar cv;</programlisting> 
    28512888 
     2889               <para>Creation of a condition variable can fail, and if it 
     2890               does, the <classname>vpr::CondVar</classname> constructor 
     2891               throws an exception of type 
     2892               <exceptionname>vpr::ResourceException</exceptionname><indexterm> 
     2893                     <primary>exceptions</primary> 
     2894 
     2895                     <secondary>vpr::ResourceException</secondary> 
     2896                  </indexterm>. If creation of the condition variable 
     2897               succeeds, then lock and unlock operations on that condition 
     2898               variable are guaranteed to succeed.</para> 
     2899 
    28522900               <para>In addition to the <classname>vpr::CondVar</classname> 
    28532901               instance, there is usually some associated variable whose value 
     
    28792927               locked by another thread, the thread requesting the lock will 
    28802928               block until the mutex is released by the other thread. If the 
    2881                lock is acquired, 
    2882                <constant>vpr::ReturnStatus::Succeed</constant> is returned. If 
    2883                the attempt to lock the semaphore fails for some reason, 
    2884                <constant>vpr::ReturnStatus::Fail</constant> is 
    2885                returned.</para> 
     2929               acquisition of the condition variable's lock would cause a 
     2930               deadlock (because the thread already holds the lock), 
     2931               <exceptionname>vpr::DeadlockException</exceptionname><indexterm> 
     2932                     <primary>exceptions</primary> 
     2933 
     2934                     <secondary>vpr::DeadlockException</secondary> 
     2935                  </indexterm> is thrown. Otherwise, the method is guaranteed 
     2936               to return when the lock is acquired.</para> 
     2937            </section> 
     2938 
     2939            <section> 
     2940               <title>Attempting to Lock a Condition Variable</title> 
     2941 
     2942               <indexterm> 
     2943                  <primary>vpr::CondVar</primary> 
     2944 
     2945                  <secondary>locking</secondary> 
     2946 
     2947                  <tertiary>without blocking</tertiary> 
     2948               </indexterm> 
     2949 
     2950               <para>If there is a need to lock a condition variable's mutex 
     2951               only when the call would <emphasis>not</emphasis> block, a 
     2952               method is provided to do this. It is called 
     2953               <methodname>tryAcquire()</methodname>, and it will not block if 
     2954               the mutex is already locked. It works as follows:</para> 
     2955 
     2956               <programlisting>const bool locked = cv.tryAcquire();</programlisting> 
     2957 
     2958               <para>If the condition variable's mutex is locked, 
     2959               <constant>true</constant> is returned. Otherwise, 
     2960               <constant>false</constant> is returned. The call does not 
     2961               block.</para> 
    28862962            </section> 
    28872963 
     
    29012977               <programlisting>cv.release();</programlisting> 
    29022978 
    2903                <para>If the locked condition variable is released 
    2904                successfully, <constant>vpr::ReturnStatus::Succeed</constant> 
    2905                is returned. Otherwise, 
    2906                <constant>vpr::ReturnStatus::Fail</constant> is 
    2907                returned.</para> 
     2979               <para>This method is guaranteed to return successfully.</para> 
    29082980 
    29092981               <para>Prior to calling 
     
    30463118         the handler for the given set of signals with the operating 
    30473119         system.</para> 
    3048  
    3049          <para>At this time, the signal handling abstraction has not been put 
    3050          into use in any Juggler Project code. As such, it is not well tested, 
    3051          and it should be considered a work in progress.</para> 
    30523120      </chapter> 
    30533121   </part> 
     
    30833151            actually uses instances of those classes. The use of sim sockets 
    30843152            versus real sockets is made when VPR is compiled, in the same way 
    3085             that the threading abstraction (NSPR versus POSIX versus SPROC) is 
    3086             chosen at compile time. Ideally, user code should not have to 
    3087             change at all to use sim sockets, thus making it possible to tes
    3088             network algorithms with exactly the same code as would be used 
    3089             with real sockets.</para> 
     3153            that the threading abstraction (NSPR versus POSIX versus Win32 
     3154            versus SPROC) is chosen at compile time. Ideally, user code should 
     3155            not have to change at all to use sim sockets, thus making i
     3156            possible to test network algorithms with exactly the same code as 
     3157            would be used with real sockets.</para> 
    30903158 
    30913159            <para>Of course, the real world is not ideal. While it is very 
     
    32523320 
    32533321         <para>A <firstterm>singleton</firstterm> is a common design pattern 
    3254          <xref linkend="ref.design.patterns" />. In VPR, the class 
     3322         <xref linkend="ref.design.patterns" />. VPR offers two ways to 
     3323         implement a singleton, both of which come from the header 
     3324         <filename>vpr/Util/Singleton.h</filename>. Libraries such as <ulink 
     3325         url="http://sourceforge.net/projects/loki-lib/">Loki</ulink> offer 
     3326         other approaches.</para> 
     3327 
     3328         <para>The first way of creating a singleton using VPR is to use the C 
     3329         preprocessor approach. In this case, we utilize two macros: 
     3330         <literal>vprSingletonHeader()</literal><indexterm> 
     3331               <primary>macros</primary> 
     3332 
     3333               <secondary>vprSingletonHeader</secondary> 
     3334            </indexterm> and <literal>vprSingletonImp()</literal><indexterm> 
     3335               <primary>macros</primary> 
     3336 
     3337               <secondary>vprSingletonImp</secondary> 
     3338            </indexterm>. One goes in the class declaration (in the header 
     3339         file), and the other goes with the class definition (in the 
     3340         <filename>.cpp</filename> file). The basic usage of these macros is 
     3341         shown in <xref linkend="example.vprSingletonHeader" /> and <xref 
     3342         linkend="example.vprSingletonImp" />.</para> 
     3343 
     3344         <example id="example.vprSingletonHeader"> 
     3345            <title>Use of <literal>vprSingletonHeader()</literal></title> 
     3346 
     3347            <programlisting>#include &lt;boost/noncopyable.hpp&gt; 
     3348#include &lt;vpr/Util/Singleton.h&gt; 
     3349 
     3350class MySingleton : boost::noncopyable 
     3351
     3352public: 
     3353   // Public operations ... 
     3354   void doSomething(); 
     3355 
     3356private: 
     3357   // Prevent instantiation by user code. 
     3358   MySingleton() 
     3359   { 
     3360      // Some constructor actions ... 
     3361   } 
     3362 
     3363   // Bring in the singleton declaration pieces. 
     3364   vprSingletonHeader(MySingleton); 
     3365};</programlisting> 
     3366         </example> 
     3367 
     3368         <example id="example.vprSingletonImp"> 
     3369            <title>Use of <literal>vprSingletonImp()</literal></title> 
     3370 
     3371            <programlisting>#include "MySingleton.h" 
     3372 
     3373// Bring in the singleton definition pieces. 
     3374vprSingletonImp(MySingleton); 
     3375 
     3376void MySingleton::doSomething() 
     3377
     3378   // Do something ... 
     3379}</programlisting> 
     3380         </example> 
     3381 
     3382         <para>In some cases, an object may need to perform some 
     3383         initialization steps after being instantiated. In that case, use the 
     3384         macro <literal>vprSingletonHeaderWithInitFunc()</literal><indexterm> 
     3385               <primary>macros</primary> 
     3386 
     3387               <secondary>vprSingletonHeaderWithInitFunc</secondary> 
     3388            </indexterm> instead of <literal>vprSingletonHeader()</literal> 
     3389         and <literal>vprSingletonImpWithInitFunc()</literal><indexterm> 
     3390               <primary>macros</primary> 
     3391 
     3392               <secondary>vprSingletonImpWithInitFunc</secondary> 
     3393            </indexterm> instead of <literal>vprSingletonImp()</literal>. An 
     3394         example of this is shown in <xref 
     3395         linkend="example.vprSingletonHeaderWithInitFunc" /> and <xref 
     3396         linkend="example.vprSingletonImpWithInitFunc" />. The initialization 
     3397         method must take no parameters and return nothing.</para> 
     3398 
     3399         <example id="example.vprSingletonHeaderWithInitFunc"> 
     3400            <title>Use of 
     3401            <literal>vprSingletonHeaderWithInitFunc()</literal></title> 
     3402 
     3403            <programlisting>#include &lt;boost/noncopyable.hpp&gt; 
     3404#include &lt;vpr/Util/Singleton.h&gt; 
     3405 
     3406class MySingleton : boost::noncopyable 
     3407
     3408public: 
     3409   // Public operations ... 
     3410   void doSomething(); 
     3411 
     3412private: 
     3413   // Prevent instantiation by user code. 
     3414   MySingleton() 
     3415   { 
     3416      // Some constructor actions ... 
     3417   } 
     3418 
     3419   void init() 
     3420   { 
     3421      // Perform initialization operations ... 
     3422   } 
     3423 
     3424   // Bring in the singleton declaration pieces. 
     3425   vprSingletonHeaderWithInitFunc(MySingleton, init); 
     3426};</programlisting> 
     3427         </example> 
     3428 
     3429         <example id="example.vprSingletonImpWithInitFunc"> 
     3430            <title>Use of 
     3431            <literal>vprSingletonImpWithInitFunc()</literal></title> 
     3432 
     3433            <programlisting>#include "MySingleton.h" 
     3434 
     3435// Bring in the singleton definition pieces. 
     3436vprSingletonImp(MySingleton); 
     3437 
     3438void MySingleton::doSomething() 
     3439
     3440   // Do something ... 
     3441}</programlisting> 
     3442         </example> 
     3443 
     3444         <para>In VPR 1.1 and beyond, the destructor for singleton objects is 
     3445         called when the application exits. This can result in some 
     3446         undesirable behavior if one singleton depends on another, thus 
     3447         meaning that the order in which they are deleted can make a 
     3448         difference. Without any specific ordering being imposed, singleton 
     3449         objects are deleted in the reverse order in which they were 
     3450         instantiated. Since it is not always possible to control the order of 
     3451         instantiation, it can be useful to control the order of destruction. 
     3452         This can be done by setting the <quote>lifetime</quote> or 
     3453         <quote>longevity</quote> of a singleton. The higher the longevity, 
     3454         the later that the singleton will be deleted when the application is 
     3455         exiting. This is accomplished using either 
     3456         <literal>vprSingletonImpLifetime()</literal><indexterm> 
     3457               <primary>macros</primary> 
     3458 
     3459               <secondary>vprSingletonImpLifetime</secondary> 
     3460            </indexterm> or 
     3461         <literal>vprSingletonImpLifetimeWithInitFunc()</literal><indexterm> 
     3462               <primary>macros</primary> 
     3463 
     3464               <secondary>vprSingletonImpLifetimeWithInitFunc</secondary> 
     3465            </indexterm>. The macro used must be paired with either 
     3466         <literal>vprSingletonHeader()</literal> or 
     3467         <literal>vprSingletonHeaderWithInitFunc()</literal>. Usage of 
     3468         <literal>vprSingletonImpLifetime()</literal> is shown in <xref 
     3469         linkend="example.vprSingletonImpLifetime" />.</para> 
     3470 
     3471         <example id="example.vprSingletonImpLifetime"> 
     3472            <title>Use of <literal>vprSingletonImpLifetime()</literal></title> 
     3473 
     3474            <programlisting>#include "MySingleton.h" 
     3475 
     3476// Bring in the singleton definition pieces. Delete it early 
     3477// in the application exit process. 
     3478vprSingletonImpLifetime(MySingleton, 10); 
     3479 
     3480void MySingleton::doSomething() 
     3481
     3482   // Do something ... 
     3483}</programlisting> 
     3484         </example> 
     3485 
     3486         <para>The other approach uses a template class called 
    32553487         <classname>vpr::Singleton&lt;T&gt;<indexterm> 
    32563488               <primary>classes</primary> 
    32573489 
    32583490               <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; 
     3491            </indexterm></classname>. An example of its use is shown in <xref 
     3492         linkend="example.vpr.Singleton.template" />.</para> 
     3493 
     3494         <example id="example.vpr.Singleton.template"> 
     3495            <title>Use of 
     3496            <classname>vpr::Singleton&lt;T&gt;</classname></title> 
     3497 
     3498            <programlisting linenumbering="numbered">#include &lt;boost/noncopyable.hpp&gt; 
     3499#include &lt;vpr/Util/Singleton.h&gt; 
     3500 
     3501class MySingleton 
     3502   : public vpr::Singleton&lt;MySingleton&gt; 
     3503   , boost::noncopyable 
    32633504{ 
    32643505public: 
     
    32783519      // Some constructor actions ... 
    32793520   } 
    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    } 
    32913521};</programlisting> 
    3292  
    3293          <para>Getting a reference to the singleton (and calling the 
     3522         </example> 
     3523 
     3524         <warning> 
     3525            <para>Singletons implemented using 
     3526            <classname>vpr::Singleton&lt;T&gt;</classname> do not work across 
     3527            DLLs on <productname class="registered">Microsoft 
     3528            Windows</productname> or shared libraries 
     3529            (<filename>.dylib</filename> files) on Mac OS X. If the singleton 
     3530            is for internal use only, such as in the case of an application, 
     3531            then using <classname>vpr::Singleton&lt;T&gt;</classname> is fine. 
     3532            Otherwise, the C preprocessor approach must be used.</para> 
     3533         </warning> 
     3534 
     3535         <para>In all singleton implementations, getting a reference to the 
     3536         singleton object (and calling the 
    32943537         <methodname>doSomething()</methodname> method) is then done using the 
    32953538         following syntax:</para> 
    32963539 
    32973540         <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> 
    33053541      </chapter> 
    33063542 
     
    34043640         termios serial I/O. When compiling on Windows, where only NSPR is 
    34053641         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> 
     3642         NSPR for socket I/O. Moreover, the simulated sockets can be mixed 
     3643         with any of the threading subsystems using this paradigm.</para> 
    34093644      </appendix> 
    34103645