Critical Sections selbst erstellen :) [3 Methoden]

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
PureFan
Beiträge: 19
Registriert: 10.09.2004 14:40
Kontaktdaten:

Beitrag von PureFan »

Hier eine andere Variante!
Funktioniert ebenfalls einwandfrei, ist aber sowohl vom Speicherverbrauch als auch Code kleiner ;)

Hier wird ein simples XCHG, welches es schon beim 1. Processor gab, verwendet um zu verhindern, dass der Code von merheren Threads gleichzeitig ausgeführt wird!

Have Fun! :D :D :D :D

Code: Alles auswählen

;- 
;- PureFan's Critical Sections *SPECIAL*
;- 
;- Posted in: German PureBasic Board 
;- Date:      30.04.05 
;- 

Structure Pure_CS 
  Cnt.l 
EndStructure 

Procedure Pure_InitCS(*PCS.Pure_CS) 
  *PCS\Cnt=0 
EndProcedure 

Procedure Pure_EnterCS(*PCS.Pure_CS) 
  !POP Edi           ;POP/PUSH dient zum schnellen Einlesen des Parameters *PCS in das Register EDI 
  !PUSH Edi 
  
  !.loop:
    !PUSH dword 1
    !CALL _Sleep@4
    
    !MOV Esi,1
    !XCHG [Edi],Esi  ;Wir lesen den alten Wert aus und schreiben als neuen 1 rein!
    
  !CMP Esi,0         ;Alter Wert war null, d.h. die vorige CS ist fertig
  !JNE .loop         ;Durch das XCHG haben wir automatisch wieder 1 im Speicher
EndProcedure 
  
Procedure Pure_LeaveCS(*PCS.Pure_CS) 
  !POP Edi           ;POP/PUSH dient zum schnellen Einlesen des Parameters *PCS in das Register EDI 
  !PUSH Edi 
  !MOV dword [Edi],0
EndProcedure 


;/ 
;/ Example for PureFan's Critical Sections 
;/ 

Global SichereStrings.Pure_CS 
Pure_InitCS(SichereStrings) 

Global GlobalerString.s 

Procedure String_Thread(Parameter) 
  Repeat 
    Pure_EnterCS(SichereStrings) 

    lokaler_string.s=GlobalerString+"hallo" 
    GlobalerString.s=Right(lokaler_string.s,100) 

    Pure_LeaveCS(SichereStrings) 
  ForEver 
EndProcedure 

For I=1 To 10 
  CreateThread(@String_Thread(),I) 
Next I 

Repeat 
  Pure_EnterCS(SichereStrings) 

  lokaler_string.s=GlobalerString+"hallo" 
  GlobalerString.s=Right(lokaler_string.s,100) 

  Pure_LeaveCS(SichereStrings) 
ForEver 
EDIT:

Vorteil bei diesem Code im Vergleich zum vorigen:

* 100% Multiprozessor-Fähig
* Ermöglicht auch KillThread/TerminateThread! Einfach die Kill-Befehle in eine Critical-Section! Bei der alten Variante würde das Programm hängen bleiben!
* ... xD
Procedure x(a,b,c):If a:ProcedureReturn b:EndIf:ProcedureReturn c:EndProcedure:For I=0 To 6:T.s+Chr(I&1+x(((I&4)/4+(I&2)/2-I&1+1)&6,1,0)<<1+x(I&1-(I&4)/4,1,0)<<2+x((I+2)&7,0,1)<<3+((4-(I+1)&4)/4)<<4+x(3-(I+3)&3,1,0)<<5+64):Next I:Debug T
Benutzeravatar
PureFan
Beiträge: 19
Registriert: 10.09.2004 14:40
Kontaktdaten:

Beitrag von PureFan »

Hab mich mal wieder drangesetzt, und hier ist das Ergebnis!

Da sieht man mal, mit welchen Commands man alles Critical Sections bauen kann ^^

* XADD ;Methode 1
* XCHG ;Methode 2
* SHR ;Diese neue Methode 3

Außerdem wäre es auch noch mit folgenden möglich (zT auch getestet)
* CMPXCHG
* ADD
* SHL

Code: Alles auswählen

;- 
;- PureFan's Critical Sections *SPECIAL* 
;- 
;- Posted in: German PureBasic Board 
;- Date:      14.05.05 
;- 

Structure Pure_CS 
  Cnt.l 
EndStructure 

;ACHTUNG: Bei dieser Methode muss die Init-Funktion unbedingt genutzt werden!
Procedure Pure_InitCS(*PCS.Pure_CS) 
  *PCS\Cnt=1
EndProcedure 

Procedure Pure_EnterCS(*PCS.Pure_CS) 
  !POP Edi           ;POP/PUSH dient zum schnellen Einlesen des Parameters *PCS in das Register EDI 
  !PUSH Edi 
  
  !.loop: 
  !PUSH dword 1
  !CALL _Sleep@4
  
  !SHR dword[Edi],1
  !JNC .loop
EndProcedure 
  
Procedure Pure_LeaveCS(*PCS.Pure_CS) 
  !POP Edi           ;POP/PUSH dient zum schnellen Einlesen des Parameters *PCS in das Register EDI 
  !PUSH Edi 
  !MOV dword [Edi],1
EndProcedure 

;/ 
;/ Example for PureFan's Critical Sections 
;/ 

Global SichereStrings.Pure_CS 
Pure_InitCS(SichereStrings) 

Global GlobalerString.s 

Procedure String_Thread(Parameter) 
  Repeat 
    Pure_EnterCS(SichereStrings) 

    lokaler_string.s=GlobalerString+"hallo" 
    GlobalerString.s=Right(lokaler_string.s,100) 
    
    Pure_LeaveCS(SichereStrings) 
  ForEver 
EndProcedure 

For I=1 To 10 
  CreateThread(@String_Thread(),I) 
Next I 

Repeat 
  Pure_EnterCS(SichereStrings) 
  
  lokaler_string.s=GlobalerString+"hallo" 
  GlobalerString.s=Right(lokaler_string.s,100) 
  
  Pure_LeaveCS(SichereStrings) 
ForEver
EDIT: Das besondere an der Methode oben ist:
* Threads können auch jederzeit gelöscht werden, wenn KillThread() in einer CriticalSection steht
* Die CriticalSection ist umbaubar in eine Dual-Critical-Section, d.h. jeweils 2 zufällig ausgewählte Threads werden gleichzeitig ausgeführt
* uvm.. ;)


BTW: Hm, mit solchen Codes könnte man ne ganze Homepage füllen xD
Procedure x(a,b,c):If a:ProcedureReturn b:EndIf:ProcedureReturn c:EndProcedure:For I=0 To 6:T.s+Chr(I&1+x(((I&4)/4+(I&2)/2-I&1+1)&6,1,0)<<1+x(I&1-(I&4)/4,1,0)<<2+x((I+2)&7,0,1)<<3+((4-(I+1)&4)/4)<<4+x(3-(I+3)&3,1,0)<<5+64):Next I:Debug T
Benutzeravatar
nicolaus
Moderator
Beiträge: 1175
Registriert: 11.09.2004 13:09
Kontaktdaten:

Beitrag von nicolaus »

@PureFan

einfach genial deine 3 Codes. :allright:
Da ich selber gerade das prob bei MultiProzessoren habe und meine software dann leider immer abstürzt hatte ich mir auch schon gedanken gemacht wie ich das lösen könnte und nun bin ich auf deine beispiele gestossen. werde das dann gleich mal bei mir einbauen und mal hoffen das dann alles gut funktioniert.

gruß nico
Benutzeravatar
nco2k
Beiträge: 892
Registriert: 08.09.2004 23:13

Beitrag von nco2k »

@PureFan
zeig das ganze bitte mal fred. ich bin mir sicher, dass er was damit anfangen kann. :allright:

c ya,
nco2k
~|__/
..o.o.. <--- This is Einkaufswagen. Copy Einkaufswagen into your signature to help him on his way to world domination.
Benutzeravatar
nicolaus
Moderator
Beiträge: 1175
Registriert: 11.09.2004 13:09
Kontaktdaten:

Beitrag von nicolaus »

habe da mal noch ne frage und zwar wie kann ich das in Dual-Critical-Section umbauen? kannste da mal bitte noch ein beispiel bringen? bekomme das gerade nich wirklich hin.

danke schon mal
Benutzeravatar
PureFan
Beiträge: 19
Registriert: 10.09.2004 14:40
Kontaktdaten:

Beitrag von PureFan »

@nco2k:
Bereits getan ;) Wie irgendwo schonmal geschrieben wird (laut Fred) spätestens in 4.0 Threadsicheres Stringhandling vorhanden sein, das zum Teil auf diesen Methoden basiert! ^^

@nicolaus:
Hier ist ein Beispiel!

Pure_InitCS(SichereStrings,2) ;<-- Die 2 hier ist die Anzahl der CriticalSections, die maximal gleichzeitig ausgeführt werden!

Aber ACHTUNG: Wenn String-Befehle innerhalb einer solchen Section, die von zwei Threads gleichzeitig ausgeführt wird, verwendet werden, besteht weiterhin die Gefahr, das das Programm abstürzt!

Code: Alles auswählen

;- 
;- PureFan's Critical Sections *SPECIAL* 
;- 
;- Posted in: German PureBasic Board 
;- Date:      17.05.05 
;- 

Structure Pure_CS 
  Cnt.l 
EndStructure 

;ACHTUNG: Bei dieser Methode muss die Init-Funktion unbedingt genutzt werden! 
Procedure Pure_InitCS(*PCS.Pure_CS,NumThreads.l) 
  
  ;CHANGED: Wir erstellen hier den Wert, der später angibt, wie viele Threads gleichzeitig
  ;laufen!
  ;1 Thread -> %1
  ;2 Threads-> %11
  ;3 Threads-> %111
  ;4 Threads-> %1111
  ;usw.
  *PCS\Cnt=(1<<NumThreads)-1
  
EndProcedure

Procedure Pure_EnterCS(*PCS.Pure_CS) 
  !POP Edi           ;POP/PUSH dient zum schnellen Einlesen des Parameters *PCS in das Register EDI 
  !PUSH Edi 
  
  !.loop: 
  !PUSH dword 1 
  !CALL _Sleep@4 
  
  !SHR dword[Edi],1 
  !JNC .loop
EndProcedure 
  
Procedure Pure_LeaveCS(*PCS.Pure_CS) 
  !POP Edi           ;POP/PUSH dient zum schnellen Einlesen des Parameters *PCS in das Register EDI 
  !PUSH Edi 
  
  ;CHANGED: Wir schieben unsere 1 wieder an den Anfang ;)
  !STC
  !RCL dword[Edi],1
EndProcedure 

;/ 
;/ Example for PureFan's Critical Sections 
;/ 

Global SichereStrings.Pure_CS 
Pure_InitCS(SichereStrings,2)


Global NumThreads.l

Procedure String_Thread(Parameter) 
  Repeat 
    Pure_EnterCS(SichereStrings) 
    NumThreads+1
 
    Delay(1) ;do something here
    
    NumThreads-1
    Pure_LeaveCS(SichereStrings) 
  ForEver 
EndProcedure 

For I=1 To 10 
  CreateThread(@String_Thread(),I) 
Next I 

Repeat
  
  Debug NumThreads   ;Wie viele Sections laufen gerade?
                     ;Hier kann nur ein Wert von 0-2 stehen!
  
ForEver
Procedure x(a,b,c):If a:ProcedureReturn b:EndIf:ProcedureReturn c:EndProcedure:For I=0 To 6:T.s+Chr(I&1+x(((I&4)/4+(I&2)/2-I&1+1)&6,1,0)<<1+x(I&1-(I&4)/4,1,0)<<2+x((I+2)&7,0,1)<<3+((4-(I+1)&4)/4)<<4+x(3-(I+3)&3,1,0)<<5+64):Next I:Debug T
Benutzeravatar
nicolaus
Moderator
Beiträge: 1175
Registriert: 11.09.2004 13:09
Kontaktdaten:

Beitrag von nicolaus »

@PureFan
danke dir für die schnelle antwort!
werds gleich mal testen.
Antworten