2011. március 28., hétfő
Create a thread-safe wrapper class for TCustomIniFile descendents
Problem/Question/Abstract:
How to create a thread-safe wrapper class for TCustomIniFile descendents
Answer:
{Unit ThreadSafeWrapperU:
Declares and implements a simple thread-safe wrapper class as base class
for classes that need to serialize access to some internal object.
Author Dr. Peter Below
Version 1.0 created 18 Oktober 2000
Current revision: 1.0
Last modified: 18 Oktober 2000
Last review: 18.04.2001}
unit ThreadSafeWrapperU;
interface
uses SyncObjs;
type
{This is a class from which classes wrapping some data object in a thread-safe
manner can be derived. The derived class should add a public
Function Lock: Sometype;
that calls InternalLock and then returns a reference for the protected object (kept in a private field ).
Access to the protected object will typically take the form
with wrapper.lock do
try
stuff
finally
wrapper.Unlock;
end;}
TThreadSafeWrapper = class
private
FGuardian: TCriticalSection;
protected
{Enter the critical section}
procedure InternalLock;
public
{Create the critical section}
constructor Create; virtual;
{Destroy the critical section}
destructor Destroy; override;
{Leave the critical section}
procedure Unlock;
end;
implementation
constructor TThreadSafeWrapper.Create;
begin
FGuardian := TCriticalSection.Create;
inherited;
end;
destructor TThreadSafeWrapper.Destroy;
begin
FGuardian.Free;
inherited;
end;
procedure TThreadSafeWrapper.InternalLock;
begin
FGuardian.Acquire;
end;
procedure TThreadSafeWrapper.Unlock;
begin
FGuardian.Release;
end;
end.
{ThreadSafeInifileU:
Implements a thread-safe wrapper class for TCustomInifile descendents.
Author Dr. Peter Below
Version 1.0 created 24.12.2000
Version 1.01 created 25.04.2001, added most of the public inifile methods to wrap
access to the internal inifile
Current revision: 1.01
Last modified: 24.12.2000
Last review: 25.04.2001}
unit ThreadSafeInifileU;
interface
uses
Windows, Classes, ThreadSafeWrapperU, Inifiles;
type
{Enumerated type for TCustomInifile descendents to use}
TIniType = (itRegistryInifile, itInifile, itMemInifile);
{A thread-safe inifile class. The default inifile class used if none is specified in
the constructor is TRegistryInifile}
TThreadsafeInifile = class(TThreadSafeWrapper)
private
FIni: TCustomInifile;
public
constructor Create(aFilename: string; aClass: TIniType = itRegistryInifile;
aAccess: LongWord = KEY_READ or KEY_WRITE); reintroduce;
destructor Destroy; override;
function Lock: TCustomInifile;
function SectionExists(const Section: string): Boolean;
function ReadString(const Section, Ident, Default: string): string;
procedure WriteString(const Section, Ident, Value: string);
function ReadInteger(const Section, Ident: string; Default: Longint): Longint;
procedure WriteInteger(const Section, Ident: string; Value: Longint);
function ReadBool(const Section, Ident: string; Default: Boolean): Boolean;
procedure WriteBool(const Section, Ident: string; Value: Boolean);
function ReadDate(const Section, Ident: string; Default: TDateTime): TDateTime;
function ReadDateTime(const Section, Ident: string; Default: TDateTime):
TDateTime;
function ReadFloat(const Section, Ident: string; Default: Double): Double;
function ReadTime(const Section, Ident: string; Default: TDateTime): TDateTime;
procedure WriteDate(const Section, Ident: string; Value: TDateTime);
procedure WriteDateTime(const Section, Ident: string; Value: TDateTime);
procedure WriteFloat(const Section, Ident: string; Value: Double);
procedure WriteTime(const Section, Ident: string; Value: TDateTime);
procedure ReadSection(const Section: string; Strings: TStrings);
procedure ReadSections(Strings: TStrings);
procedure ReadSectionValues(const Section: string; Strings: TStrings);
procedure EraseSection(const Section: string);
procedure DeleteKey(const Section, Ident: string);
function ValueExists(const Section, Ident: string): Boolean;
end;
implementation
uses
Registry;
{TThreadsafeInifile.Create:
Create the custom ini file descendent.
Parameters:
aFilename: The name to use.
aClass: Defines the class to use.
aAccess: The desired access if aclass is itRegistryInifile.
We have a slight problem here since TCustomInifile.Create is not a virtual constructor.
So we need a somewhat cumbersome Case construct to create the correct class of
TCustomInifile descendent.
Created 24.12.2000 by P. Below}
constructor TThreadsafeInifile.Create(aFilename: string; aClass: TIniType =
itRegistryInifile;
aAccess: DWord = KEY_READ or KEY_WRITE);
begin
inherited Create;
case aClass of
itRegistryInifile:
FIni := TRegistryInifile.Create(aFilename, aAccess);
itInifile:
FIni := TInifile.Create(aFilename);
itMemInifile:
FIni := TMemInifile.Create(aFilename);
end;
end;
{TThreadsafeInifile.Destroy:
Destroy the internal inifile object.
Created 24.12.2000 by P. Below}
destructor TThreadsafeInifile.Destroy;
begin
FIni.Free;
inherited;
end;
{TThreadsafeInifile.Lock:
Aquire access to the ini file and return its reference. Must be paired with an Unlock call!
Created 24.12.2000 by P. Below}
function TThreadsafeInifile.Lock: TCustomInifile;
begin
InternalLock;
Result := FIni;
end;
function TThreadsafeInifile.SectionExists(const Section: string): Boolean;
begin
InternalLock;
try
Result := FIni.SectionExists(Section);
finally
Unlock;
end;
end;
function TThreadsafeInifile.ReadString(const Section, Ident, Default: string): string;
begin
InternalLock;
try
Result := FIni.ReadString(Section, Ident, Default);
finally
Unlock;
end;
end;
procedure TThreadsafeInifile.WriteString(const Section, Ident, Value: string);
begin
InternalLock;
try
FIni.WriteString(Section, Ident, Value);
finally
Unlock;
end;
end;
function TThreadsafeInifile.ReadInteger(const Section, Ident: string; Default:
Longint): Longint;
begin
InternalLock;
try
Result := FIni.ReadInteger(Section, Ident, Default);
finally
Unlock;
end;
end;
procedure TThreadsafeInifile.WriteInteger(const Section, Ident: string; Value:
Longint);
begin
InternalLock;
try
FIni.WriteInteger(Section, Ident, Value);
finally
Unlock;
end;
end;
function TThreadsafeInifile.ReadBool(const Section, Ident: string; Default: Boolean):
Boolean;
begin
InternalLock;
try
Result := FIni.ReadBool(Section, Ident, Default);
finally
Unlock;
end;
end;
procedure TThreadsafeInifile.WriteBool(const Section, Ident: string; Value: Boolean);
begin
InternalLock;
try
FIni.WriteBool(Section, Ident, Value);
finally
Unlock;
end;
end;
function TThreadsafeInifile.ReadDate(const Section, Ident: string; Default:
TDateTime): TDateTime;
begin
InternalLock;
try
Result := FIni.ReadDate(Section, Ident, Default);
finally
Unlock;
end;
end;
function TThreadsafeInifile.ReadDateTime(const Section, Ident: string;
Default: TDateTime): TDateTime;
begin
InternalLock;
try
Result := FIni.ReadDatetime(Section, Ident, Default);
finally
Unlock;
end;
end;
function TThreadsafeInifile.ReadFloat(const Section, Ident: string; Default: Double):
Double;
begin
InternalLock;
try
Result := FIni.ReadFloat(Section, Ident, Default);
finally
Unlock;
end;
end;
function TThreadsafeInifile.ReadTime(const Section, Ident: string; Default:
TDateTime): TDateTime;
begin
InternalLock;
try
Result := FIni.ReadTime(Section, Ident, Default);
finally
Unlock;
end;
end;
procedure TThreadsafeInifile.WriteDate(const Section, Ident: string; Value:
TDateTime);
begin
InternalLock;
try
FIni.WriteDate(Section, Ident, Value);
finally
Unlock;
end;
end;
procedure TThreadsafeInifile.WriteDateTime(const Section, Ident: string; Value:
TDateTime);
begin
InternalLock;
try
FIni.WriteDatetime(Section, Ident, Value);
finally
Unlock;
end;
end;
procedure TThreadsafeInifile.WriteFloat(const Section, Ident: string; Value: Double);
begin
InternalLock;
try
FIni.WriteFloat(Section, Ident, Value);
finally
Unlock;
end;
end;
procedure TThreadsafeInifile.WriteTime(const Section, Ident: string; Value:
TDateTime);
begin
InternalLock;
try
FIni.WriteTime(Section, Ident, Value);
finally
Unlock;
end;
end;
procedure TThreadsafeInifile.ReadSection(const Section: string; Strings: TStrings);
begin
InternalLock;
try
FIni.ReadSection(Section, Strings);
finally
Unlock;
end;
end;
procedure TThreadsafeInifile.ReadSections(Strings: TStrings);
begin
InternalLock;
try
FIni.ReadSections(Strings);
finally
Unlock;
end;
end;
procedure TThreadsafeInifile.ReadSectionValues(const Section: string; Strings:
TStrings);
begin
InternalLock;
try
FIni.ReadSectionValues(Section, Strings);
finally
Unlock;
end;
end;
procedure TThreadsafeInifile.EraseSection(const Section: string);
begin
InternalLock;
try
FIni.EraseSection(Section);
finally
Unlock;
end;
end;
procedure TThreadsafeInifile.DeleteKey(const Section, Ident: string);
begin
InternalLock;
try
FIni.DeleteKey(Section, Ident);
finally
Unlock;
end;
end;
function TThreadsafeInifile.ValueExists(const Section, Ident: string): Boolean;
begin
InternalLock;
try
Result := FIni.ValueExists(Section, Ident);
finally
Unlock;
end;
end;
end.
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése