Add `GDBDebugger >> #waitForAllEventsProcessed` and `#waitForAllCommandsProcessed`
authorJan Vrany <jan.vrany@fit.cvut.cz>
Wed, 23 Jan 2019 21:38:06 +0000
changeset 170 6cf990ac2cad
parent 169 a3d1f59e3bfd
child 171 de7559c2ba7f
Add `GDBDebugger >> #waitForAllEventsProcessed` and `#waitForAllCommandsProcessed` These methods are meant mainly for synchronization in tests, NOT for normal user code. Uses should avoid calling these.
GDBConnection.st
GDBDebugger.st
tests/libInit.cc
--- a/GDBConnection.st	Sat Jan 19 23:25:55 2019 +0000
+++ b/GDBConnection.st	Wed Jan 23 21:38:06 2019 +0000
@@ -390,6 +390,42 @@
     "Modified: / 02-10-2018 / 13:37:30 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
+!GDBConnection methodsFor:'queries'!
+
+hasPendingCommands
+    | anyCommandEventPending |
+
+    "/ This is more tricky. There are pending commands if:
+    "/ 
+    "/  * there's at least one GDBCommandEvent in event queue
+    "/    (command it sent on API level but not yet sent to GDB), or
+    "/  * there's at least one outstanding command (command has been
+    "/    sent to GDB but response not yet arrived), or
+    "/  * there's at least one GDBCommandResultEvent (command response
+    "/    was received but not yet dispatched and handled.
+    "/ 
+    "/ 
+    outstandingCommands notEmpty ifTrue:[ ^ true ].
+
+    "/ Here, synchronization is required since we iterate over
+    "/ collection...
+    eventQueueLock critical:[
+        anyCommandEventPending := eventQueue anySatisfy:[:e|e class == GDBCommandEvent or:[e class == GDBCommandResultEvent ] ]
+    ].
+    ^ anyCommandEventPending
+
+    "Created: / 23-01-2019 / 20:50:12 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+hasPendingEvents
+
+    "/ Note that there's no obligation for this information to
+    "/ be 100% accurate, so no need for symchronization here.
+    ^ eventQueue notEmpty.
+
+    "Created: / 23-01-2019 / 20:41:29 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
 !GDBConnection class methodsFor:'documentation'!
 
 version_HG
--- a/GDBDebugger.st	Sat Jan 19 23:25:55 2019 +0000
+++ b/GDBDebugger.st	Wed Jan 23 21:38:06 2019 +0000
@@ -1143,6 +1143,34 @@
     ].
 
     "Created: / 09-04-2018 / 15:45:03 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+hasPendingCommands
+    "Return `true` if there are commands being sent but not yet
+     processed, `false` otherwise. By 'processed' we mean that 
+     command result event not yet arrived or is waiting in a queue
+     to be dispatched.
+
+     Note that by the nature of event queues and threads, 
+     return value may be obsolete by the time client uses
+     it. Use with caution!!
+    "
+    ^ connection hasPendingCommands
+
+    "Created: / 23-01-2019 / 20:41:02 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+hasPendingEvents
+    "Return `true` if there are events in a queue wating
+     to be dispatched, `false` otherwise.
+
+     Note that by the nature of event queues and threads, 
+     return value may be obsolete by the time client uses
+     it. Use with caution!!
+    "
+    ^ connection hasPendingEvents
+
+    "Created: / 23-01-2019 / 20:38:23 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
 !GDBDebugger methodsFor:'testing'!
@@ -1179,6 +1207,40 @@
     ].
 
     "Created: / 07-02-2018 / 11:34:23 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+waitUntilAlCommandsProcessed
+    "BLock caller until all commands are processed. This method is provided
+     mainly for use in tests or synchronization. Normal code should avoid 
+     using this.
+    "
+
+    self 
+        assert:Processor activeProcess ~~ connection eventDispatchProcess
+        message:'Cannot wait from within event dispatching process. Would deadlock'.           
+
+    "/ Since this method is not required to be 100% accurate, polling seems
+    "/ like an easy and safe approach. It's not meant for normal usage, anyway.
+    [ self hasPendingCommands ] whileTrue:[ Delay waitForMilliseconds: 100 ].
+
+    "Created: / 23-01-2019 / 21:03:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+waitUntilAllEventsProcessed
+    "BLock caller until all events are processed. This method is provided
+     mainly for use in tests or synchronization. Normal code should avoid 
+     using this.
+    "
+
+    self 
+        assert:Processor activeProcess ~~ connection eventDispatchProcess
+        message:'Cannot wait from within event dispatching process. Would deadlock'.           
+
+    "/ Since this method is not required to be 100% accurate, polling seems
+    "/ like an easy and safe approach. It's not meant for normal usage, anyway.
+    [ self hasPendingEvents ] whileTrue:[ Delay waitForMilliseconds: 100 ].
+
+    "Created: / 23-01-2019 / 21:03:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
 !GDBDebugger class methodsFor:'documentation'!
--- a/tests/libInit.cc	Sat Jan 19 23:25:55 2019 +0000
+++ b/tests/libInit.cc	Wed Jan 23 21:38:06 2019 +0000
@@ -23,7 +23,7 @@
 extern void _GDBMIPrinterTests_Init(int pass, struct __vmData__ *__pRT__, OBJ snd);
 extern void _GDBTransientDataHolderTests_Init(int pass, struct __vmData__ *__pRT__, OBJ snd);
 extern void _jv_137libgdbs_137tests_Init(int pass, struct __vmData__ *__pRT__, OBJ snd);
-extern void _GDBDebuggerTestsR_Init(int pass, struct __vmData__ *__pRT__, OBJ snd);
+extern void _GDBDebuggerTests_Init(int pass, struct __vmData__ *__pRT__, OBJ snd);
 
 
 
@@ -45,7 +45,7 @@
     _GDBMIPrinterTests_Init(pass,__pRT__,snd);
     _GDBTransientDataHolderTests_Init(pass,__pRT__,snd);
     _jv_137libgdbs_137tests_Init(pass,__pRT__,snd);
-    _GDBDebuggerTestsR_Init(pass,__pRT__,snd);
+    _GDBDebuggerTests_Init(pass,__pRT__,snd);
 
 
   __END_PACKAGE__();