delphi tcollection
As I’ve already mentioned in the previous articles, all things that could be done with the VCL also could be done without it, using only Win32 API functions and services. Some VCL classes are only wrappers for appropriate Win32 objects, other add some functionality and service functions. Some Win32 objects are not implemented in the VCL but you still can use them calling Win32 API functions directly. So, let’s look at the mutex object and create own VCL-style wrapper class.

Win32 objects.

All Win32 objects are 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. Object instance is accessed by HANDLE. You can think that a HANDLE is a unique value of type DWORD used by system to identify an object instance. CreateXXX API function returns a handle of newly created object. All of Win32 API functions, which are intended for manipulation of this type of objects, receive the object handle as actual parameter. CloseHandle function should be used to close object HANDLE. The object is destroyed when its last handle is closed. Each Win32 object could have a name. The name is limited to MAX_PATH (255) characters and can contain any character except the backslash path-separator character. Name comparison is case sensitive. All Win32 objects, such as mutexs, events, semaphores, memory-mapped files share the same name space.

Mutex object.

“Mutex” is an abbreviation of “Mutual Execution”. The CreateMutex function creates named or unnamed mutex object. HANDLE returned by CreateMutex can be used in any function that requires a handle of a mutex object. Any thread can call WaitForSingleObject function, which returns when state of the mutex object is signaled. When a wait function returns the waiting thread is released to continue its execution. The state of a mutex object is signaled when no thread owns it. A thread must use WaitForSingleObject function to request ownership. When the mutex’s state is signaled, one waiting thread is granted ownership, the mutex’s state changed to non-signaled and the wait function returns. Only one thread can own a mutex at any given time. The owning thread should use ReleaseMutex function to release its ownership.

Code.

interface
uses windows, sysutils;
type
TILMutex = class
private
FHandle:THandle;
FTimeout: DWORD;
public
constructor Create(Name:String);
destructor Destroy;override;
property Timeout:DWORD read FTimeout write FTimeout;
procedure Lock;
procedure Unlock;
end;

implementation

{ TILMutex }

constructor TILMutex.Create(Name: String);
begin
if Name<>'' then
FHandle:=CreateMutex(nil,false,PChar(Name))
else
FHandle:=CreateMutex(nil,false,nil);
if FHandle=0 then
RaiseLastWin32Error;
FTimeout:=INFINITE;
end;

destructor TILMutex.Destroy;
begin
if FHandle<>0 then
Win32Check(CloseHandle( FHandle));
end;

procedure TILMutex.Lock;
var
wRes:DWORD;
begin
wRes:=WaitForSingleObject(FHandle,FTimeout);
if wRes<>WAIT_OBJECT_0 then
RaiseLastWin32Error;
end;

procedure TILMutex.Unlock;
begin
Win32Check(ReleaseMutex(FHandle));
end;

end.

Code explanation.

You can see that TILMutex is a simple wrapper for Win32 mutex object. Constructor Create creates a new named or unnamed mutex object depending on Name parameter using CreateMutex API function. TILMutex.Destroy closes mutex’s handle using CloseHandle. Lock method tries to obtain ownership using WaitForSingleObject, and Unlock method release ownership using ReleaseMutex. Timeout property determines timeout interval in milliseconds. The default value is INFINITE constant. If default value is used, the WaitForSingleObject time-out interval never elapses.