ThreadID() und GetCurrentThreadID_()

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benubi
Beiträge: 187
Registriert: 22.10.2004 17:51
Wohnort: Berlin, Wedding

ThreadID() und GetCurrentThreadID_()

Beitrag von Benubi »

Hallo!

ich ziele darauf ab einen Reads-Write Lock zu programmieren (multiple Leser, ein Schreiber). Ich bin mir noch nicht sicher ob ich ausschließlich PB Objekte nutzen möchte, oder etwas selbst auf dem Low Level schreiben will - bei Letzterem komme ich schon etwas ins Trudeln. Ein Konzept für so einen RW Lock, der auch multiple Selbst-Locks zulässt (also wenn der aktuelle Schreiber nochmal schreiben oder lesen will z.B.), benötigt da die ThreadID damit diese in einer Liste aufgenommen oder beim Unlock() rausgenommen wird.

Lange Rede kurzer Sinn: beim Versuch mir die ThreadID's über die API zu holen erhalte ich verschiedene Werte bei ThreadId() und by GetCurrentThreadID() unter Windows. Unter Linux funktioniert das aber mit pthread_self_() als GetCurrentThreadID_() pendant, mit der Eigenart dass der Main-Thread dem B Thread im dem Beispiel identisch sind (vermutlich normales fork() verhalten, weiss nicht).

Bug oder feature? Das dürfte keine Probleme bei meinem Vorhaben verursachen, ich dachte aber es sollte mal angesprochen werden. Mache ich bei Windows was falsch?

Code: Alles auswählen

; ==============================================================
; === (c) 2022 by benubi                                     ===
; ==============================================================
;
; Source: GetCurrentThreadID.pb
; Thread: -/-
; Author: benubi
; Date: 28/10/2022
; OS: All
; License: 100% free
;
; ==============================================================
; Description, Beschreibung
;
; EN    Access the current thread & process ID's
;
; FR    Accès aux identifiants des tâches & procéssus courants
;
; DE    Zugriff auf laufende Thread & Prozess ID's
;
;
; ==============================================================
;
Procedure.i GetCurrentThreadID() ; Returns the OS' ThreadID of the calling thread. This is a different value from ThreadID().
  CompilerSelect #PB_Compiler_OS
      
    CompilerCase #PB_OS_Windows
      
      ProcedureReturn GetCurrentThreadId_() ; WINDOWS
      
    CompilerCase #PB_OS_Linux
      
      
      ProcedureReturn pthread_self_() ; Linux / Posix
      
    CompilerCase #PB_OS_MacOS
      
      
      ProcedureReturn pthread_self_() ; MacOS / Posix
      
    CompilerCase #PB_OS_AmigaOS
      
      
      ProcedureReturn pthread_self_() ; AmigaOS / Posix
      
  CompilerEndSelect
EndProcedure


Procedure.i GetProcessID() ; Returns the current ProcessID of the running executable
  
  CompilerSelect #PB_Compiler_OS
      
    CompilerCase #PB_OS_Windows
      
      ProcedureReturn GetCurrentProcessId_() ; Windows
      
    CompilerCase #PB_OS_Linux
      
      ProcedureReturn getpid_() ; Linux / Posix
      
    CompilerCase #PB_OS_MacOS
      
      ProcedureReturn getpid_() ; MacOS / Posix
      
    CompilerCase #PB_OS_AmigaOS
      
      ProcedureReturn getpid_() ; AmigaOS / Posix
      
      
  CompilerEndSelect
  
EndProcedure




CompilerIf #PB_Compiler_IsMainFile
  ; ==============================================================
  ; ==============================================================
  ; Demo
  ; ==============================================================
  ; ==============================================================
  
  CompilerIf Not #PB_Compiler_Thread
    DebuggerWarning("WARNING: ThreadSafe is OFF. It should be turned ON or the Debug-strings could mess up.") 
  CompilerEndIf 
  
  Procedure A_Proc(abc)
    Debug LSet("",100,"-")
    Debug #PB_Compiler_Procedure + "-ProcessID: " + GetProcessID()
    Debug #PB_Compiler_Procedure + "-ThreadID : " + GetCurrentThreadID() 
 
  EndProcedure
  Procedure B_Proc(abc)
    Debug LSet("",100,"-")
    Debug #PB_Compiler_Procedure + "-ProcessID: " + GetProcessID()
    Debug #PB_Compiler_Procedure + "-ThreadID : " + GetCurrentThreadID()
  EndProcedure
  
  Define th1, th2
  
  Debug "Main process ID: " + GetProcessID()  
  Debug "Main thread ID : " + GetCurrentThreadID() ; <- main thread / process thread
  
  th1 = CreateThread(@A_Proc(), 0)
  th2 = CreateThread(@B_Proc(), 0)
  
  Debug "A_proc Th1:"+th1+"  Th1-ID : "+ThreadID(th1) 
  Debug "B_Proc Th2:"+th2+"  Th2-ID : "+ThreadID(th2) 
  
  
  If IsThread(th1)
    WaitThread(th1)
  EndIf
  If IsThread(th2)
    WaitThread(th2)
  EndIf
  Debug LSet("",100,"-")
  Debug "Good bye."
  End 
  
CompilerEndIf
Benutzeravatar
mk-soft
Beiträge: 3855
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: ThreadID() und GetCurrentThreadID_()

Beitrag von mk-soft »

Windows:
Die PB Funktion ThreadID liefert das Handle vom Thread zurück und nicht die Windows Thread ID
Sollte vielleicht besser im der PB-Hilfe stehen ...

Code: Alles auswählen

  Import ""
    GetThreadId(Handle)
  EndImport
  
  Debug "A_proc Th1:"+th1+" Handle: " + ThreadID(th1) + " Th1-ID : " + GetThreadId(ThreadID(th1))
  Debug "B_Proc Th2:"+th2+" Handle: " + ThreadID(th2) + " Th2-ID : " + GetThreadId(ThreadID(th2)) 
Zuletzt geändert von mk-soft am 28.10.2022 16:45, insgesamt 1-mal geändert.
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: ThreadID() und GetCurrentThreadID_()

Beitrag von NicTheQuick »

Ich hab nur Linux zum Testen. Aber ich habe dort für Main, A_Proc und B_Proc immer unterschiedliche Thread-IDs, also ich sehe da keine Eigenart wie du mit dem Main-Thread und B-Thread.

Beispielausgabe:
Main process ID: 558676
Main thread ID : 140710817711936
A_proc Th1:140710757975616 Th1-ID : 140710757975616
B_Proc Th2:140710756922944 Th2-ID : 140710756922944
----------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------
A_Proc-ProcessID: 558676
B_Proc-ProcessID: 558676
A_Proc-ThreadID : 140710757975616
B_Proc-ThreadID : 140710756922944
----------------------------------------------------------------------------------------------------
Good bye.
Im Übrigens ist LockMutex() schon Reentrant. Du musst da also nichts eigenes bauen. Multiple Selbstlocks sind möglich.

Code: Alles auswählen

mutex.i = CreateMutex()

LockMutex(mutex)
LockMutex(mutex)
Debug "Ha! Doppelt abgesperrt."
UnlockMutex(mutex)
UnlockMutex(mutex)
Benutzeravatar
mk-soft
Beiträge: 3855
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: ThreadID() und GetCurrentThreadID_()

Beitrag von mk-soft »

Bei Linux und macOS ist alles gleich. Nur unter Windows wird mit der PB-Funktion ThreadID das Handle vom Thread zurückgegeben und nicht die Window Thread ID
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benubi
Beiträge: 187
Registriert: 22.10.2004 17:51
Wohnort: Berlin, Wedding

Re: ThreadID() und GetCurrentThreadID_()

Beitrag von Benubi »

Danke für die Antworten!

@mk-soft
Wenn jemand unter Windows programmieren würde um unter der WinAPI mit Threads was zu machen, würde er das Handle oder die Window Thread ID benutzen? Ist der Code dann so OK, oder sollte ich lieber unter Windows das Handle zurrückgeben lassen; wie würde ich dann da rankommen, zweite API Funktion aufrufen vermutlich?



@NicTheQuick
Ich glaube ich muß das mit dem Mutex etwas mehr experimentieren. Re-entrant heisst ja nicht direkt multiple readers - single writer, aber es ist ja schon die halbe Sache quasi. Vermutlich brauche ich 2 Mutexes, einen um die Readers zu verwalten, der nur kurz was checkt, und den klassischen Writer der von Haus dann re-entrant ist. Cool!

Ich habe den Linux Output (über VirtualBox) wieder gecheckt, ICH DACHTE da sind wieder die Main-Thread-ID und der B/A_Proc-Thread-ID gleich, sie ähneln sich aber nur sehr. Ich wahr nicht aufmerksam genug. :freak:
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: ThreadID() und GetCurrentThreadID_()

Beitrag von NicTheQuick »

Für das "single-writer"-"multi-reader"-lock würde ich normalerweise Bedingungsvariablen und einen Mutex nutzen. Aber da Purebasic keine Bedingungsvariablen kennt, sondern nur Mutexe und Semaphoren, kannst du das Problem auch mit zwei Mutexen und einem Integer nachbauen. Hier ist ein Pseudo-Code auf Wikipedia: https://en.wikipedia.org/wiki/Readers%E ... wo_mutexes
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: ThreadID() und GetCurrentThreadID_()

Beitrag von NicTheQuick »

Hier findest du noch einen Post von mir bezüglich Bedingungsvariablen unter Linux: https://www.purebasic.fr/english/viewto ... 04#p475504

Nur, falls du das noch ausbauen willst. Ich weiß nicht wie das dann unter Windows funktioniert. Ich wünsche mir schon lange, dass Purebasic das nativ mitliefert. An vielen Stellen sind die einfach viel besser.

Und das hier könnte interessant sein für Windows: https://learn.microsoft.com/en-us/windo ... -variables
Benubi
Beiträge: 187
Registriert: 22.10.2004 17:51
Wohnort: Berlin, Wedding

Re: ThreadID() und GetCurrentThreadID_()

Beitrag von Benubi »

Danke! Ich werde wohl das Wikipedia Beispiel nachbauen.

Das Einfachste wäre vermutlich wenn PB ein neues Schlüsselwort wie z.B. Synchronize einführen würde, für atomare Operationen bei Variablen, oder eine vollständige Atomic Bibliothek welche diese Funktionalität zur Verfügung stellt sowie diese Bedingungsvariablen.

Ich habe selbst ein paar Tage probiert mir so eine eigene Mutex und Semaphore Library zu bauen, und sowas ähnliches wie diese Bedingungsvariablen (WaitSignal/WaitForNull); hat auch teilweise funktioniert, aber insbesondere auf der Assembler Seite ist das nicht einfach, da musste ich in gcc source codes rumlesen und sowas. Dann habe ich mir ARM-Assembler kurz angesehen und da ist selbstverständlich alles anders als bei x86/x64, und ein anderes Byte Ordering ebenso falls man interoperabel sein möchte.... Ich habe ja nicht mal von "normalem" Assembler Ahnung. Tja, wird wohl erstmal nix mit dem perfekten Eigenbräu.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: ThreadID() und GetCurrentThreadID_()

Beitrag von NicTheQuick »

In der Richtung musst du auch gar nichts mehr selbst brauen. Wenn du dich nicht gerade in Compiler-Bau spezialisieren möchtest, sind diese Kenntnisse ziemlich unnütz, es reicht vollkommen sie auf Pseudo-Code-Basis verstanden zu haben. Alles, was du für Threads brauchst, gibt es schon und bietet dir dein Betriebssystem in der Regel an.

Aber ich kann verstehe, dass Selber-Machen einfach Spaß macht. :-)
Antworten