(btw: Das geht aus der Hilfe leider nicht so richtig hervor. Könnte man noch mit aufnehmen)
Ich habe einige Prozeduren, die verschachtelt sind, aber ggf. auch separat aufgerufen werden. Von daher sperrt sich jede Prozedur selbst mittels Lock/UnlockMutex. Das geht soweit gut, auch wenn sich mehrere dieser Prozeduren mehrfach selbst aufrufen.
Wenns dann irgendwo aber mal hängt suche ich nach einer Debuggermöglichkeit, um die Stelle herauszufinden wo evtl. ein Unlock vergessen wurde. Die Debuggerfunktionen und Hilfsfenster habe ich ehrlich gesagt bisher nicht so richtig bis in die Tiefe genutzt. Gibt das der Debugger her, dass man solche Fehler schnell auffindet?
In meinem Fall ist es leider nicht so, dass man das Problem einfach so nachstellen kann. Hier wird ein Customgadget (module) sowohl von einem thread "bedient" als auch gleichzeitig manuell über die GUI von mir. Und irgendwann gibts dann einen deadlock wo alles einfriert. Eine manuelle Fehlersuche wird an der Stelle zu einem ziemlichen rumstochern.
Nachtrag: Ich erweitere meine Frage mal etwas, da ich gerade ein Verständnisproblem habe
Es geht um ein Customgadget mit sagen wir mal folgenden Funktionen:
- Create
- Draw
- Free
Das Ganze ist in einem Module realisiert und die drei Prozeduren sind public.
Da das Customgadget mit mehreren Instanzen genutzt werden können soll, wird bei Create() intern eine Gadgetstruktur allokiert, in der alle nötigen Parameter gespeichert werden.
Das könnte z.B. so aussehen:
Code: Alles auswählen
*GraphGadget = AllocateStructure(GraphGadget)
If *GraphGadget <> 0
With *GraphGadget
\iGadgetX = x
\iGadgetY = y
\iGadgetHeight = iGadgetHeight
\iGadgetWidth = iGadgetWidth
\iGadgetBorderSize = iGadgetBorderSize
\iGadgetBorderColour = iGadgetBorderColour
... usw
Code: Alles auswählen
; Parametercheck
If *GraphGadget = 0
ProcedureReturn
EndIf
With *GraphGadget
; irgendwelche Aufräumarbeiten
EndWith
FreeStructure(*GraphGadget)
Das hat nichts gebracht, es kam dabei trotzdem zum deadlock (irgendwann). Was mir einleuchtet ist, dass ich, um an den Mutex zu gelangen, erst einmal in die Struktur des betreffenden Gadget greifen muss.
Also so z.B.:
Code: Alles auswählen
Procedure Draw(*GraphGadget.GraphGadget)
; Parametercheck
If *GraphGadget = 0 : ProcedureReturn : EndIf
; Wait until the Gadget is unlocked
LockMutex(*GraphGadget\iMutex)
; Mach was....
UnlockMutex(*GraphGadget\iMutex)
EndProcedure
Daher dachte ich mir, dass ich für das gesamte Modul einen Globalen Mutex benutze.
Code: Alles auswählen
Global.i iMutex
Ich könnte je eine globale Init() und DeInit() Prozedur schreiben, die man vor Erzeugung der ersten Instanz bzw. nach Freigabe der letzten Instanz des Customgadgets aufrufen muss, aber das kommt mir zu ungeschmeidig vor.
Man könnte noch einen globalen Mutex-Zähler mitlaufen lassen, der in Create() und Free() jeweils angepasst wird. Aber ist das der richtige Weg, wenn man ein multiaufrufsicheres Customgadget schreiben möchte?