[PATCH 5/6] gdb/continuations: use lambdas instead of function pointers

Tankut Baris Aktemur tankut.baris.aktemur@intel.com
Wed Apr 21 12:57:30 GMT 2021


Use lambdas and std::list to track inferior continuations.  This is a
refactoring.

gdb/ChangeLog:
2021-04-21  Tankut Baris Aktemur  <tankut.baris.aktemur@intel.com>

	* inferior.h (class inferior) <continuations>: Change the type
	to be an std::list of std::function's.
	Update the references and uses below.
	* continuations.c (struct continuation): Delete.
	(make_continuation): Delete.
	(do_my_continuations_1): Delete.
	(do_my_continuations): Delete.
	(discard_my_continuations_1): Delete.
	(discard_my_continuations): Delete.
	(add_inferior_continuation): Update.
	(do_all_inferior_continuations): Update.
	(discard_all_inferior_continuations): Update.
	* continuations.h (add_inferior_continuation): Update to take
	an std::function as the parameter.
	* infcmd.c (struct attach_command_continuation_args): Delete.
	(attach_command_continuation): Delete.
	(attach_command_continuation_free_args): Delete.
	(attach_command): Update.
	(notice_new_inferior): Update.
---
 gdb/continuations.c | 96 +++++----------------------------------------
 gdb/continuations.h | 24 ++++--------
 gdb/infcmd.c        | 45 ++++-----------------
 gdb/inferior.h      |  4 +-
 4 files changed, 26 insertions(+), 143 deletions(-)

diff --git a/gdb/continuations.c b/gdb/continuations.c
index 8fe81a75ba9..a552203e106 100644
--- a/gdb/continuations.c
+++ b/gdb/continuations.c
@@ -22,98 +22,15 @@
 #include "inferior.h"
 #include "continuations.h"
 
-struct continuation
-{
-  struct continuation *next;
-  continuation_ftype *function;
-  continuation_free_arg_ftype *free_arg;
-  void *arg;
-};
-
-/* Add a new continuation to the continuation chain.  Args are
-   FUNCTION to run the continuation up with, and ARG to pass to
-   it.  */
-
-static void
-make_continuation (struct continuation **pmy_chain,
-		   continuation_ftype *function,
-		   void *arg,  void (*free_arg) (void *))
-{
-  struct continuation *newobj = XNEW (struct continuation);
-
-  newobj->next = *pmy_chain;
-  newobj->function = function;
-  newobj->free_arg = free_arg;
-  newobj->arg = arg;
-  *pmy_chain = newobj;
-}
-
-static void
-do_my_continuations_1 (struct continuation **pmy_chain)
-{
-  struct continuation *ptr;
-
-  while ((ptr = *pmy_chain) != NULL)
-    {
-      *pmy_chain = ptr->next;	/* Do this first in case of recursion.  */
-      (*ptr->function) (ptr->arg);
-      if (ptr->free_arg)
-	(*ptr->free_arg) (ptr->arg);
-      xfree (ptr);
-    }
-}
-
-static void
-do_my_continuations (struct continuation **list)
-{
-  struct continuation *continuations;
-
-  if (*list == NULL)
-    return;
-
-  /* Copy the list header into another pointer, and set the global
-     list header to null, so that the global list can change as a side
-     effect of invoking the continuations and the processing of the
-     preexisting continuations will not be affected.  */
-
-  continuations = *list;
-  *list = NULL;
-
-  /* Work now on the list we have set aside.  */
-  do_my_continuations_1 (&continuations);
-}
-
-static void
-discard_my_continuations_1 (struct continuation **pmy_chain)
-{
-  struct continuation *ptr;
-
-  while ((ptr = *pmy_chain) != NULL)
-    {
-      *pmy_chain = ptr->next;
-      if (ptr->free_arg)
-	(*ptr->free_arg) (ptr->arg);
-      xfree (ptr);
-    }
-}
-
-static void
-discard_my_continuations (struct continuation **list)
-{
-  discard_my_continuations_1 (list);
-  *list = NULL;
-}
-
 /* Add a continuation to the continuation list of INFERIOR.  The new
    continuation will be added at the front.  */
 
 void
-add_inferior_continuation (continuation_ftype *hook, void *args,
-			   continuation_free_arg_ftype *free_arg)
+add_inferior_continuation (std::function<void ()> &&cont)
 {
   struct inferior *inf = current_inferior ();
 
-  make_continuation (&inf->continuations, hook, args, free_arg);
+  inf->continuations.emplace_front (std::move (cont));
 }
 
 /* Do all continuations of the current inferior.  */
@@ -122,7 +39,12 @@ void
 do_all_inferior_continuations ()
 {
   struct inferior *inf = current_inferior ();
-  do_my_continuations (&inf->continuations);
+  while (!inf->continuations.empty ())
+    {
+      auto &cont = inf->continuations.front ();
+      inf->continuations.pop_front ();
+      cont ();
+    }
 }
 
 /* Get rid of all the inferior-wide continuations of INF.  */
@@ -130,5 +52,5 @@ do_all_inferior_continuations ()
 void
 discard_all_inferior_continuations (struct inferior *inf)
 {
-  discard_my_continuations (&inf->continuations);
+  inf->continuations.clear ();
 }
diff --git a/gdb/continuations.h b/gdb/continuations.h
index 39130c65f0f..4dc15494ae1 100644
--- a/gdb/continuations.h
+++ b/gdb/continuations.h
@@ -20,29 +20,19 @@
 #ifndef CONTINUATIONS_H
 #define CONTINUATIONS_H
 
+#include <functional>
+
 struct inferior;
 
 /* To continue the execution commands when running gdb asynchronously.
-   A continuation structure contains a pointer to a function to be called
-   to finish the command, once the target has stopped.  Such mechanism is
-   used by the attach command and the remote target when a new inferior
-   is detected.  */
-
-/* Prototype of the continuation callback functions.  ARG is the
-   continuation argument registered in the corresponding
-   add_*_continuation call.  */
-typedef void (continuation_ftype) (void *arg);
-
-/* Prototype of the function responsible for releasing the argument
-   passed to the continuation callback functions, either when the
-   continuation is called, or discarded.  */
-typedef void (continuation_free_arg_ftype) (void *);
+   A continuation is a closure (i.e.  a lambda) to be called to finish
+   the command, once the target has stopped.  Such mechanism is used
+   by the attach command and the remote target when a new inferior is
+   detected.  */
 
 /* Inferior specific (any thread) continuations.  */
 
-extern void add_inferior_continuation (continuation_ftype *,
-				       void *,
-				       continuation_free_arg_ftype *);
+extern void add_inferior_continuation (std::function<void ()> &&cont);
 extern void do_all_inferior_continuations ();
 extern void discard_all_inferior_continuations (struct inferior *inf);
 
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 5c3ee02cb9d..e06db492b07 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -2540,30 +2540,6 @@ attach_post_wait (int from_tty, enum attach_post_wait_mode mode)
     }
 }
 
-struct attach_command_continuation_args
-{
-  int from_tty;
-  enum attach_post_wait_mode mode;
-};
-
-static void
-attach_command_continuation (void *args)
-{
-  struct attach_command_continuation_args *a
-    = (struct attach_command_continuation_args *) args;
-
-  attach_post_wait (a->from_tty, a->mode);
-}
-
-static void
-attach_command_continuation_free_args (void *args)
-{
-  struct attach_command_continuation_args *a
-    = (struct attach_command_continuation_args *) args;
-
-  xfree (a);
-}
-
 /* "attach" command entry point.  Takes a program started up outside
    of gdb and ``attaches'' to it.  This stops it cold in its tracks
    and allows us to start debugging it.  */
@@ -2661,8 +2637,6 @@ attach_command (const char *args, int from_tty)
      E.g. Mach 3 or GNU hurd.  */
   if (!target_attach_no_wait ())
     {
-      struct attach_command_continuation_args *a;
-
       /* Careful here.  See comments in inferior.h.  Basically some
 	 OSes don't ignore SIGSTOPs on continue requests anymore.  We
 	 need a way for handle_inferior_event to reset the stop_signal
@@ -2671,11 +2645,10 @@ attach_command (const char *args, int from_tty)
       inferior->control.stop_soon = STOP_QUIETLY_NO_SIGSTOP;
 
       /* Wait for stop.  */
-      a = XNEW (struct attach_command_continuation_args);
-      a->from_tty = from_tty;
-      a->mode = mode;
-      add_inferior_continuation (attach_command_continuation, a,
-				 attach_command_continuation_free_args);
+      add_inferior_continuation ([=] ()
+	{
+	  attach_post_wait (from_tty, mode);
+	});
 
       /* Let infrun consider waiting for events out of this
 	 target.  */
@@ -2719,7 +2692,6 @@ notice_new_inferior (thread_info *thr, int leave_running, int from_tty)
 
   if (thr->executing)
     {
-      struct attach_command_continuation_args *a;
       struct inferior *inferior = current_inferior ();
 
       /* We're going to install breakpoints, and poke at memory,
@@ -2730,11 +2702,10 @@ notice_new_inferior (thread_info *thr, int leave_running, int from_tty)
       inferior->control.stop_soon = STOP_QUIETLY_REMOTE;
 
       /* Wait for stop before proceeding.  */
-      a = XNEW (struct attach_command_continuation_args);
-      a->from_tty = from_tty;
-      a->mode = mode;
-      add_inferior_continuation (attach_command_continuation, a,
-				 attach_command_continuation_free_args);
+      add_inferior_continuation ([=] ()
+	{
+	  attach_post_wait (from_tty, mode);
+	});
 
       return;
     }
diff --git a/gdb/inferior.h b/gdb/inferior.h
index 9ca510e4e6e..fc072b3576f 100644
--- a/gdb/inferior.h
+++ b/gdb/inferior.h
@@ -22,6 +22,7 @@
 #define INFERIOR_H 1
 
 #include <exception>
+#include <list>
 
 struct target_waitstatus;
 struct frame_info;
@@ -32,7 +33,6 @@ struct regcache;
 struct ui_out;
 struct terminal_info;
 struct target_desc_info;
-struct continuation;
 struct inferior;
 struct thread_info;
 
@@ -510,7 +510,7 @@ class inferior : public refcounted_object
 
   /* What is left to do for an execution command after any thread of
      this inferior stops.  */
-  continuation *continuations = NULL;
+  std::list<std::function<void ()> > continuations;
 
   /* True if setup_inferior wasn't called for this inferior yet.
      Until that is done, we must not access inferior memory or
-- 
2.17.1



More information about the Gdb-patches mailing list