Using Critical Sections
This section describes how to use critical sections to protect portions of your
adaptor code. The section describes the adaptor kit's main critical section class,
ICriticalSection
, and the ancillary class,
IAutoCriticalSection
, that you use to manage critical sections.
Topics covered include
Understanding Critical Sections
To prevent sections of code or resources from being accessed simultaneously by
multiple threads, use critical section (ICriticalSecton
) objects.
The basic process for using a critical section has three-steps:
Create a critical section object, using the adaptor kit
createCriticalSection()
function.At the point in your code that you want to protect, enter the critical section by calling the
ICriticalSection::enter()
member function.At the end of the code that you want to protect, leave the critical section by calling the
ICriticalSection::leave()
member function.
While this process might appear simple, using a
ICriticalSection
object directly in this way can expose your
adaptor to problems. For example, if an error occurs in the protected code, the call
to the leave()
function might never be executed. Entering a
critical section and then never leaving it can cause unexpected results.
To make working with critical sections easier, the adaptor kit provides a second
class, called IAutoCriticalSection
, that can help you manage the
critical sections you define.
You first create an ICriticalSection
object and then pass this
object to the createAutoCriticalSection()
function when you
create the IAutoCriticalSection
object. When you create the
object, you automatically enter the critical section without having to call the
enter()
function. When the protected code goes out of scope,
the auto critical section automatically leaves the critical section without your
code having to call the leave()
function.
The auto critical section object ensures that you always exit a critical section.
However, you must also ensure that the auto critical section itself gets deleted. To
do this, the adaptor kit recommends managing the handle to the
IAutoCriticalSection
object, returned by
createAutoCriticalSection()
, as an
auto_ptr
using the std::auto_ptr<>
template class from the Standard Template Library. The auto_ptr
helps ensure that the IAutoCriticalSection
handle is
deleted.
Example: Using a Critical Section
To define a section of code as a critical section, follow this procedure.
Create an
ICriticalSection
object, using thecreateCriticalSection()
function. Adaptors typically create anICriticalSection
object in their constructors — see Implementing Your Adaptor Class Constructor._mySection = imaqkit::createCriticalSection();
The function returns a handle to an
ICriticalSection
object._mySection
, which is declared as a member variable in the adaptor class header file, as follows.imaqkit::ICriticalSection* _mySection;
At the point in your code that you want to protect, create an
IAutoCriticalSection
object. TheIAutoCriticalSection
class guarantees that the critical section objects are released when the protected code goes out of scope, or if an exception occurs. In an adaptor, you typically want to protect the frame acquisition loop in a critical section. Insert this code in the acquisition thread function, just before the frame acquisition loop — see Implementing the Acquisition Thread Function.std::auto_ptr<imaqkit::IAutoCriticalSection> myAutoSection(imaqkit::createAutoCriticalSection(adaptor->_mySection, true));
In this code, the variable
myAutoSection
is a handle to anIAutoCriticalSection
object, that is managed as a Standard Template Libraryauto_ptr
. The code passes a handle to anICriticalSection
object, _mySection
, as an argument to thecreateAutoCriticalSection()
function. The second argument tocreateAutoCriticalSection()
specifies that the adaptor should enter the critical section automatically upon creation of theIAutoCriticalSection
.At the end of the code that you want to protect, leave the critical section. In an adaptor, you want to leave the critical section after the frame acquisition loop is done. Insert this code just before the acquisition thread function breaks out of the frame acquisition loop — see Implementing the Acquisition Thread Function.
You can use the
IAutoCriticaSection::leave()
function but this is not necessary. TheIAutoCriticalSection
leaves the critical section automatically when the code section goes out of scope. You might want to include explicit calls to theleave()
function in your code to help document the extent of your critical section.bool MyDeviceAdaptor::stopCapture(){ // If the device is not acquiring data, return. if (!isAcquiring()) return true; // Get the critical section and enter it. std::auto_ptr<imaqkit::IAutoCriticalSection> GrabSection(imaqkit::createAutoCriticalSection(_grabSection, true)); //********************************************************** // Insert calls to your device's SDK to stop the device, if // necessary. //********************************************************** // Leave the critical section. GrabSection->leave(); return true; }