Main Content

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:

  1. Create a critical section object, using the adaptor kit createCriticalSection() function.

  2. At the point in your code that you want to protect, enter the critical section by calling the ICriticalSection::enter() member function.

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

  1. Create an ICriticalSection object, using the createCriticalSection() function. Adaptors typically create an ICriticalSection 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;
    
  2. At the point in your code that you want to protect, create an IAutoCriticalSection object. The IAutoCriticalSection 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 an IAutoCriticalSection object, that is managed as a Standard Template Library auto_ptr. The code passes a handle to an ICriticalSection object, _mySection, as an argument to the createAutoCriticalSection() function. The second argument to createAutoCriticalSection() specifies that the adaptor should enter the critical section automatically upon creation of the IAutoCriticalSection.

  3. 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. The IAutoCriticalSection leaves the critical section automatically when the code section goes out of scope. You might want to include explicit calls to the leave() 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;
    }