It was mentioned in the previous article that the VCL includes TCriticalSection object used to prevent simultaneous access to global objects / variables. I want to show you that there is not any “magic” in the VCL. All things that can be done with the VCL also can be done without it, using only Win32 API functions. Now let’s create own version of TCriticalSection object.
Win32 API routines.
Like all Win32 objects a critical section object is opaque. Only Win32 subsystem “knows” an object internal structure and can access all the data an object contains directly. Win32 usually exports support routines that user-mode processes can call to manipulate an object.
The process is responsible for allocating the memory used by a critical section object. Typically, this is done by simply declaring a variable of type TRTLCriticalSection. Before the threads of the process can use it, the critical section object must be initialized by using the InitializeCriticalSection function.
A thread uses the EnterCriticalSection function to request ownership and the LeaveCriticalSection function to release its ownership. If the critical section object is currently owned by another thread, EnterCriticalSection waits indefinitely(!!!!) for ownership.
Once a thread owns a critical section object, it can make additional calls to EnterCriticalSection without blocking its execution. This prevents a thread from deadlocking itself while waiting for a critical section object that it already owns. To release its ownership, the thread must call LeaveCriticalSection once for each time that it entered the critical section.
Any thread of the process can use the DeleteCriticalSection function to release the system resources that were allocated when the critical section object was initialized. After this function has been called, the critical section object can no longer be used for synchronization.
uses Windows; type TILCriticalSection = class private FSection: TRTLCriticalSection; public constructor Create; destructor Destroy; override; procedure Enter; procedure Leave; end; implementation constructor TILCriticalSection.Create; begin inherited Create; InitializeCriticalSection(FSection); end; destructor TILCriticalSection.Destroy; begin DeleteCriticalSection(FSection); inherited Destroy; end; procedure TILCriticalSection.Enter; begin EnterCriticalSection(FSection); end; procedure TILCriticalSection.Leave; begin LeaveCriticalSection(FSection); end; end.
You can see that TILCriticalSection is a simple wrapper for Win32 Critical section object. The critical section object initialization is implemented in constructor. TILCriticalSection.Destroy() deletes critical section freeing all allocated system resources. Usage of Enter() and Leave() methods is clear.