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).
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 |