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

Reply via email to