Threads and the Rulbus Device Class Library
[User Manual]

Multithreading

Because the Rulbus Device Class Library is used on a multitasking--multithreading operating system, attention must be given to the effects this may have. For example, it should not be possible that in one thread a Rulbus device just selected its rack, followed by a second device in another thread setting one of its registers, assuming that its rack still is selected.

The Rulbus Device Class Library enforces the following:

Serialized means that an operation is completed before it will be performed again. To this end semaphores are used.

Access to the Rulbus devices is not protected, so programs must adhere to the following rule:

It is allowed to create a Rulbus device in one thread (process) and use it from another thread (process).

Example

The following program example shows the use of three threads, two of which control their own DAC. One thread generates a square wave voltage, the other thread generates a sawtooth voltage. Error handling has been omitted for clarity.

/*
 * threads.cpp - use Rulbus Device Library from three threads.
 *
 * Compile: bcc32 -tWM threads.cpp rulbusdcl-omf-static.lib winutils-omf-static.lib
 */

#include <conio.h>                      // for kbhit()
#include <cstring>                      // for std::stricmp()
#include <iostream>                     // for std::cout
#include <windows.h>                    // for DWORD HANDLE, Sleep()

#include "rdcl/rb8510_dac12.h"          // for class RB8510_Dac12 etc.
#include "rdcl/RulbusInterface.h"       // for class TheRulbusInterface etc.

const char *title = "Threads  1.0  use Rulbus DLL from three threads.\n";

enum { E_OK, E_OPT, E_ARG, };           // program return codes

static int           threads   ( );
static HANDLE        mkThread  ( const char *msg, DWORD WINAPI (*ThreadFunc)(LPVOID), Rulbus::RB8510_Dac12Ptr pDac );
static DWORD  WINAPI SquareWave( LPVOID arg );
static DWORD  WINAPI SawTooth  ( LPVOID arg );

/*
 * main - the program.
 */

int main( int argc, char *argv[] )
{
   std::cout << title << std::endl;

   return threads();
}

/*
 * threads - create a separate thread for each of two DAC channels
 *           and generate a square wave and a sawtooth.
 *
 *      100% |--    --    --
 *           |  |  |  |  |  |
 *       50% |   --    --
 *           | /| /| /| /| /
 *        0% |/_|/_|/_|/_|/___
 */

static volatile int runthread = 1;

static int threads()
{
   Rulbus::TheRulbusInterface::instance().printOn( std::cout );

   std::cout << "\nGenerating waveforms on DAC channels 0 & 1.\n";

   /*
    * open two DACs:
    */

   const int    rack = 0, adr0 = 0xD0, adr1 = 0xD2;
   const int bipolar = 1; const float  vpb  = 5e-3;

   Rulbus::RB8510_Dac12 dac0( "dac-0", adr0, rack, bipolar, vpb );
   Rulbus::RB8510_Dac12 dac1( "dac-1", adr1, rack, bipolar, vpb );

   /*
    * create and resume threads:
    */

   HANDLE thread0 = mkThread( "DAC channel-0", SquareWave, &dac0 );
   HANDLE thread1 = mkThread( "DAC channel-1", SawTooth  , &dac1 );

   std::cout << "\n\nPress a key to stop...\n\n";

   ResumeThread( thread0 );
   ResumeThread( thread1 );

   /*
    * wait for key pressed; eat character:
    */

   while (!kbhit() )
     Sleep( 10 );

   (void) getch();

   /*
    *  stop and remove threads and close DACs:
    */

   runthread = 0; Sleep( 10 );

   CloseHandle( thread0 );
   CloseHandle( thread1 );

   return E_OK;
}

/*
 * mkThread - create a thread.
 */

static HANDLE mkThread( const char *msg, DWORD WINAPI (*ThreadFunc)(LPVOID), Rulbus::RB8510_Dac12Ptr pDac )
{
   std::cout << "\ncreating thread for " << msg;

   DWORD id;

   return CreateThread(
      NULL,             // pointer to thread security attributes
      0,                // initial thread stack size, in bytes
      ThreadFunc,       // pointer to thread function
      pDac,             // argument for new thread
      CREATE_SUSPENDED, // creation flags
      &id               // pointer to returned thread identifier
   );
}

/*
 * SquareWave - generate a square wave voltage.
 */

static DWORD WINAPI SquareWave( LPVOID arg )
{
   Rulbus::RB8510_Dac12Ref dac = *reinterpret_cast<Rulbus::RB8510_Dac12Ptr>( arg );

   std::cout << "thread function: squarewave on "; dac.printOn( std::cout );

   while ( runthread )
   {
      dac.setValue( 2048 ); Sleep(50);
      dac.setValue( 4095 ); Sleep(50);
   }

   return 0;
}

/*
 * SawTooth - generate a sawtooth voltage.
 */

static DWORD WINAPI SawTooth( LPVOID arg )
{
   Rulbus::RB8510_Dac12Ref dac = *reinterpret_cast<Rulbus::RB8510_Dac12Ptr>( arg );

   std::cout << "thread function: sawtooth on "; dac.printOn( std::cout );

   while ( runthread )
   {
      for( int n = 0; n <= 2047; n = (n + 50) % 2048 )
      {
         dac.setValue( n ); Sleep(1);
      }
   }

   return 0;
}

/*
 * End of file
 */

previous top next


Generated on Tue Oct 12 14:12:01 2004 for Rulbus Device Class Library for Microsoft Windows by doxygen 1.3.4