I've written a very lightweight read-write spin lock, just for
protecting interface instances.
I have put it in use in my program, and it seems working fine.
But I am not sure if it really works, becuase I have not yet
experienced this hypothetical race condition even without any
synchronization...
(most likely becuase I don't have a dual-core cpu...)
If anyone got some free time, please help me bug check it.
AdamWu
(*** Start of code ***)
// Simple Multi-read Exclusive-write spin lock
// NOTE: This object is designed to synchronize VERY VERY small pieces of
code.
// For efficiency reason, it does not have much error correction
capability.
// HOW IT WORKS: It basically keeps track of the number of reader thread
by
// the (positive) value of an integer; and the writer thread by
setting
// the integer to -1.
TRWSpinLock = Class
Private
rSyncInt: Integer;
Public
Constructor Create;
Destructor Destroy; Override;
Class Procedure ReadSync(Var SyncInt: Integer); Overload;
Register;
Class Procedure WriteSync(Var SyncInt: Integer); Overload;
Register;
Class Procedure ReadDone(Var SyncInt: Integer); Overload;
Register;
Class Procedure WriteDone(Var SyncInt: Integer); Overload;
Register;
Procedure ReadSync; Overload; Inline;
Procedure WriteSync; Overload; Inline;
Procedure ReadDone; Overload; Inline;
Procedure WriteDone; Overload; Inline;
END;
Class Procedure TRWSpinLock.ReadSync(Var SyncInt: Integer);
{ @SyncInt: EDX }
ASM
@@Back:
MOV EAX, [ SyncInt ]
TEST EAX, EAX
JS @@Spin
MOV ECX, EAX
INC ECX
LOCK CMPXCHG [ SyncInt ], ECX
JZ @@Done
@@Spin:
PAUSE
JMP @@Back
@@Done:
END;
Class Procedure TRWSpinLock.WriteSync(Var SyncInt: Integer);
{ @SyncInt: EDX }
ASM
@@Back:
MOV EAX, [ SyncInt ]
TEST EAX, EAX
JNZ @@Spin
MOV ECX, -1
LOCK CMPXCHG [ SyncInt ], ECX
JZ @@Done
@@Spin:
PAUSE
JMP @@Back
@@Done:
END;
Class Procedure TRWSpinLock.ReadDone(Var SyncInt: Integer);
{ @SyncInt: EDX }
ASM
MOV EAX, -1
LOCK XADD [ SyncInt ], EAX
END;
Class Procedure TRWSpinLock.WriteDone(Var SyncInt: Integer);
{ @SyncInt: EDX }
ASM
XOR EAX, EAX
LOCK XCHG [ SyncInt ], EAX
END;
Constructor TRWSpinLock.Create;
BEGIN
Inherited;
//rSyncInt:= 0;
END;
Destructor TRWSpinLock.Destroy;
BEGIN
WriteSync;
Inherited;
END;
Procedure TRWSpinLock.ReadSync;
BEGIN
ReadSync(rSyncInt);
END;
Procedure TRWSpinLock.WriteSync;
BEGIN
WriteSync(rSyncInt);
END;
Procedure TRWSpinLock.ReadDone;
BEGIN
ReadDone(rSyncInt);
END;
Procedure TRWSpinLock.WriteDone;
BEGIN
WriteDone(rSyncInt);
END;
(*** End of code ***)
To use the spinlock to protect interface instances:
* This class has ability to sync on both enternal and internal counters
For external counters, it is your responsibility to initialize it to
zero,
and make sure it does not get clobbered while used for sync purposes.
* Use Read__() when making new references;
Example:
TRWSpinLock.ReadSync(RWCounter);
NewIntf:= ProtectedIntf;
TRWSpinLock.ReadDone;
* Use Write__() when releasing references;
TRWSpinLock.WriteSync(RWCounter);
ProtectedIntf:= NIL;
TRWSpinLock.WriteDone;
* There are no support for transition between "read" and "write".
* Don't EVER mix and match __Sync() and __Done() calls.
------
.dlrow eht htiw thgir s'lla ,nevaeh sih ni si doG
_________________________________________________________________
享用世界上最大的电子邮件系统― MSN Hotmail。 http://www.hotmail.com
_______________________________________________
Delphi mailing list -> [email protected]
http://www.elists.org/mailman/listinfo/delphi