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

Tankut Baris Aktemur via Gdb-patches
2021-04-21T12:57:58Z

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

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