ReadWriteLock

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
cxAlex
Beiträge: 2111
Registriert: 26.06.2008 10:42

ReadWriteLock

Beitrag von cxAlex »

Servus.

Hier mal schnell ein Include für einen RW - Lock geschrieben. Der Lock ermöglicht shared und exclusiven Zugriff. Z.B. können dann beliebig viele Threads eine Ressource im Shared Mode lesen, will ein Thread an der Ressource etwas ändern bekommt er exclusiven Zugriff und alle anderen Thread müssen warten bis er fertig ist.

Vielleicht kanns ja jemand brauchen.

Gruß, Alex

Code: Alles auswählen

; ------------------------------------------------------------------------------------
; ReadWrite Lock
; Mutex mit Shared & Excluiven Zugriff
; PB 4.3 +, All Os, Ascii/Unicode, x86/x64
; Author: Alexander Aigner
; ------------------------------------------------------------------------------------

; EnableExplicit

; ------------------------------------------------------------------------------------
; Internal
; ------------------------------------------------------------------------------------

Structure RWL_Data
  ReaderCount.i
  ThreadsWaiting.i
  ResumeSignal.i
  LastReaderSignal.i
  Writer.i
  Mutex.i
EndStructure

Macro _RWL_CheckForWriter(_RWL)
  If _RWL#\Writer
    _RWL#\ThreadsWaiting + 1
    UnlockMutex(_RWL#\Mutex)
    WaitSemaphore(_RWL#\ResumeSignal)
    LockMutex(_RWL#\Mutex)
    _RWL#\ThreadsWaiting-1
  EndIf
EndMacro

; ------------------------------------------------------------------------------------
; Public
; ------------------------------------------------------------------------------------

; Neuen RWLock erstellen
Procedure RWL_New()
  Protected *RWL.RWL_Data
  *RWL = AllocateMemory(SizeOf(RWL_Data))
  With *RWL
    \Mutex = CreateMutex()
    \ResumeSignal = CreateSemaphore()
    \LastReaderSignal = CreateSemaphore()
  EndWith
  ProcedureReturn *RWL
EndProcedure

; RWLock freigeben
Procedure RWL_Free(*RWL.RWL_Data)
  With *RWL
    FreeMutex(\Mutex)
    FreeSemaphore(\ResumeSignal)
    FreeSemaphore(\LastReaderSignal)
    FreeMemory(*RWL)
  EndWith
EndProcedure

; Shared - Zugriff anfordern
Procedure RWL_LockShared(*RWL.RWL_Data)
  With *RWL
    LockMutex(\Mutex)
    _RWL_CheckForWriter(*RWL) ; Prüfen ob Exclusiver Zugriff offen
    \ReaderCount + 1 ; Ein Reader mehr
    UnlockMutex(\Mutex)
  EndWith
EndProcedure

; Shared Zugriff freigeben
Procedure RWL_UnlockShared(*RWL.RWL_Data)
  With *RWL
    LockMutex(\Mutex)
    \ReaderCount-1 ; Ein Reader weniger
    If \ReaderCount<0 ; Kleiner Schutz gegen falsche Verwendung
      \ReaderCount = #Null
    EndIf
    If \Writer And \ReaderCount = #Null
      SignalSemaphore(\LastReaderSignal) ; Fertig Signal für Exclusiven Zugriff
    EndIf
    UnlockMutex(\Mutex)
  EndWith
EndProcedure

; Exclusiven Zugriff anfordern
Procedure RWL_LockExclusive(*RWL.RWL_Data)
  With *RWL
    LockMutex(\Mutex)
    _RWL_CheckForWriter(*RWL) ; Prüfen ob Exclusiver Zugriff offen
    \Writer = #True ; Exclusiv öffnen
    UnlockMutex(\Mutex) 
    If \ReaderCount 
      WaitSemaphore(\LastReaderSignal) ; Warten biss alle shared fertig
    EndIf
  EndWith
EndProcedure

; Exclusiven Zugriff freigeben
Procedure RWL_UnlockExclusive(*RWL.RWL_Data)
  Protected i
  With *RWL
  LockMutex(\Mutex)
  \Writer = #False ; Exclusiv schließen
  For i = 1 To \ThreadsWaiting
    SignalSemaphore(\ResumeSignal) ; Wartende Zugiffe fortsetzen
  Next
  UnlockMutex(\Mutex)
  EndWith
EndProcedure
Projekte: IO.pbi, vcpu
Pausierte Projekte: Easy Network Manager, µC Emulator
Aufgegebene Projekte: ECluster

Bild

PB 5.1 x64/x86; OS: Win7 x64/Ubuntu 10.x x86