From 1c21617fc888261094851bd94b35fd1bbfaba650 Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Mon, 12 Feb 2018 12:36:16 +0000 Subject: [PATCH 1/3] Use address-indentify tokens instead of counters. Fix some typos. --- gdb/common/observable.h | 58 ++++++++++++++++++++++----------------- gdb/observer.c | 16 +++++------ gdb/record-btrace.c | 22 +++++---------- gdb/tui/tui-hooks.c | 72 ++++++++++++++++++++----------------------------- 4 files changed, 76 insertions(+), 92 deletions(-) diff --git a/gdb/common/observable.h b/gdb/common/observable.h index 118718871fe..f5666c14e5c 100644 --- a/gdb/common/observable.h +++ b/gdb/common/observable.h @@ -42,56 +42,65 @@ extern unsigned int observer_debug; particular, it is therefore not possible to call the attach or detach routines during a notification. */ +/* The type of a key that can be passed to attach, which can be passed + to detach to remove associated observers. Tokens have address + identity, and are thus usually const globals. */ +struct token +{ + token () = default; + + DISABLE_COPY_AND_ASSIGN (token); +}; + template class observable { public: - typedef std::function func_type; - - /* The return type of attach, which can be passed to detach to - remove a listener. */ - typedef size_t token_type; - - /* A "null" value of token_type that can be used as a - sentinel. */ - static constexpr const token_type null_token = size_t (-1); + typedef std::function func_type; explicit observable (const char *name) - : m_count (0), - m_name (name) + : m_name (name) { } DISABLE_COPY_AND_ASSIGN (observable); - /* Attach F as an observable to this observable. A token is - returned which can be used to later remove F. */ - token_type attach (const func_type &f) + /* Attach F as an observer to this observable. F cannot be + detached. */ + void attach (const func_type &f) + { + m_observers.emplace_back (nullptr, f); + } + + /* Attach F as an observer to this observable. T is a reference to + a token that can be used to later remove F. */ + void attach (const func_type &f, const token &t) { - m_observers.emplace_back (m_count, f); - return m_count++; + m_observers.emplace_back (&t, f); } - /* Remove an observer from this observable. F is the token that was - previously returned by "attach". */ - void detach (const token_type &f) + /* Remove observers associated with T from this observable. T is + the token that was previously passed to any number of "attach" + calls. */ + void detach (const token &t) { auto iter = std::remove_if (m_observers.begin (), m_observers.end (), - [=] (const std::pair &e) + [&] (const std::pair &e) { - return e.first == f; + return e.first == &t; }); m_observers.erase (iter, m_observers.end ()); } - /* Notify all observables that are attached to this observer. */ + /* Notify all observers that are attached to this observable. */ void notify (T... args) const { if (observer_debug) - fprintf_unfiltered (gdb_stdlog, "observer %s notify() called\n", + fprintf_unfiltered (gdb_stdlog, "observable %s notify() called\n", m_name); for (auto &&e : m_observers) e.second (args...); @@ -99,8 +108,7 @@ public: private: - size_t m_count; - std::vector> m_observers; + std::vector> m_observers; const char *m_name; }; diff --git a/gdb/observer.c b/gdb/observer.c index d39e3e7462e..7e44c8c0181 100644 --- a/gdb/observer.c +++ b/gdb/observer.c @@ -128,10 +128,10 @@ observer_self_tests () attached. */ notify_check_counters (0, 0, 0); - observable::token_type token1, token2, token3; + const gdb::observers::token token1, token2, token3; /* Now, attach one observer, and send a notification. */ - token2 = test_notification.attach (&test_second_notification_function); + test_notification.attach (&test_second_notification_function, token2); notify_check_counters (0, 1, 0); /* Remove the observer, and send a notification. */ @@ -139,15 +139,15 @@ observer_self_tests () notify_check_counters (0, 0, 0); /* With a new observer. */ - token1 = test_notification.attach (&test_first_notification_function); + test_notification.attach (&test_first_notification_function, token1); notify_check_counters (1, 0, 0); /* With 2 observers. */ - token2 = test_notification.attach (&test_second_notification_function); + test_notification.attach (&test_second_notification_function, token2); notify_check_counters (1, 1, 0); /* With 3 observers. */ - token3 = test_notification.attach (&test_third_notification_function); + test_notification.attach (&test_third_notification_function, token3); notify_check_counters (1, 1, 1); /* Remove middle observer. */ @@ -164,9 +164,9 @@ observer_self_tests () /* Go back to 3 observers, and remove them in a different order... */ - token1 = test_notification.attach (&test_first_notification_function); - token2 = test_notification.attach (&test_second_notification_function); - token3 = test_notification.attach (&test_third_notification_function); + test_notification.attach (&test_first_notification_function, token1); + test_notification.attach (&test_second_notification_function, token2); + test_notification.attach (&test_third_notification_function, token3); notify_check_counters (1, 1, 1); /* Remove the third observer. */ diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c index c0f36268eae..660ce407c96 100644 --- a/gdb/record-btrace.c +++ b/gdb/record-btrace.c @@ -44,9 +44,9 @@ /* The target_ops of record-btrace. */ static struct target_ops record_btrace_ops; -/* A new thread observer enabling branch tracing for the new thread. */ -static gdb::observers::observable::token_type - record_btrace_thread_observer; +/* Token associated with a new-thread observer enabling branch tracing + for the new thread. */ +static const gdb::observers::token record_btrace_thread_observer_token; /* Memory access types used in set/show record btrace replay-memory-access. */ static const char replay_memory_access_read_only[] = "read-only"; @@ -177,8 +177,8 @@ record_btrace_auto_enable (void) { DEBUG ("attach thread observer"); - record_btrace_thread_observer - = gdb::observers::new_thread.attach (record_btrace_enable_warn); + gdb::observers::new_thread.attach (record_btrace_enable_warn, + record_btrace_thread_observer_token); } /* Disable automatic tracing of new threads. */ @@ -186,14 +186,9 @@ record_btrace_auto_enable (void) static void record_btrace_auto_disable (void) { - /* The observer may have been detached, already. */ - if (record_btrace_thread_observer == gdb::observers::new_thread.null_token) - return; - DEBUG ("detach thread observer"); - gdb::observers::new_thread.detach (record_btrace_thread_observer); - record_btrace_thread_observer = gdb::observers::new_thread.null_token; + gdb::observers::new_thread.detach (record_btrace_thread_observer_token); } /* The record-btrace async event handler function. */ @@ -239,9 +234,6 @@ record_btrace_open (const char *args, int from_tty) if (!target_has_execution) error (_("The program is not being run.")); - gdb_assert (record_btrace_thread_observer - == gdb::observers::new_thread.null_token); - disable_chain = make_cleanup (null_cleanup, NULL); ALL_NON_EXITED_THREADS (tp) if (args == NULL || *args == 0 || number_is_in_list (args, tp->global_num)) @@ -3139,6 +3131,4 @@ to see the actual buffer size."), NULL, show_record_pt_buffer_size_value, record_btrace_conf.bts.size = 64 * 1024; record_btrace_conf.pt.size = 16 * 1024; - - record_btrace_thread_observer = gdb::observers::new_thread.null_token; } diff --git a/gdb/tui/tui-hooks.c b/gdb/tui/tui-hooks.c index ba87aec2e15..8d0bc8711a1 100644 --- a/gdb/tui/tui-hooks.c +++ b/gdb/tui/tui-hooks.c @@ -203,21 +203,32 @@ tui_normal_stop (struct bpstats *bs, int print_frame) tui_refresh_frame_and_register_information (/*registers_too_p=*/1); } -/* Observers created when installing TUI hooks. */ -static gdb::observers::observable::token_type - tui_bp_created_observer; -static gdb::observers::observable::token_type - tui_bp_deleted_observer; -static gdb::observers::observable::token_type - tui_bp_modified_observer; -static gdb::observers::observable::token_type - tui_inferior_exit_observer; -static gdb::observers::observable::token_type - tui_before_prompt_observer; -static gdb::observers::observable::token_type - tui_normal_stop_observer; -static gdb::observers::observable::token_type - tui_register_changed_observer; +/* Token associated with observers registered while TUI hooks are + installed. */ +static const gdb::observers::token tui_observers_token; + +/* Attach or detach TUI observers, according to ATTACH. */ + +static void +tui_attach_detach_observers (bool attach) +{ + auto ad = [&] (auto &observable, + const auto &func) + { + if (attach) + observable.attach (func, tui_observers_token); + else + observable.detach (tui_observers_token); + }; + + ad (gdb::observers::breakpoint_created, tui_event_create_breakpoint); + ad (gdb::observers::breakpoint_deleted, tui_event_delete_breakpoint); + ad (gdb::observers::breakpoint_modified, tui_event_modify_breakpoint); + ad (gdb::observers::inferior_exit, tui_inferior_exit); + ad (gdb::observers::before_prompt, tui_before_prompt); + ad (gdb::observers::normal_stop, tui_normal_stop); + ad (gdb::observers::register_changed, tui_register_changed); +} /* Install the TUI specific hooks. */ void @@ -231,20 +242,7 @@ tui_install_hooks (void) = tui_dummy_print_frame_info_listing_hook; /* Install the event hooks. */ - tui_bp_created_observer - = gdb::observers::breakpoint_created.attach (tui_event_create_breakpoint); - tui_bp_deleted_observer - = gdb::observers::breakpoint_deleted.attach (tui_event_delete_breakpoint); - tui_bp_modified_observer - = gdb::observers::breakpoint_modified.attach (tui_event_modify_breakpoint); - tui_inferior_exit_observer - = gdb::observers::inferior_exit.attach (tui_inferior_exit); - tui_before_prompt_observer - = gdb::observers::before_prompt.attach (tui_before_prompt); - tui_normal_stop_observer - = gdb::observers::normal_stop.attach (tui_normal_stop); - tui_register_changed_observer - = gdb::observers::register_changed.attach (tui_register_changed); + tui_attach_detach_observers (true); } /* Remove the TUI specific hooks. */ @@ -253,21 +251,9 @@ tui_remove_hooks (void) { deprecated_print_frame_info_listing_hook = 0; deprecated_query_hook = 0; + /* Remove our observers. */ - gdb::observers::breakpoint_created.detach (tui_bp_created_observer); - tui_bp_created_observer = gdb::observers::breakpoint_created.null_token; - gdb::observers::breakpoint_deleted.detach (tui_bp_deleted_observer); - tui_bp_deleted_observer = gdb::observers::breakpoint_deleted.null_token; - gdb::observers::breakpoint_modified.detach (tui_bp_modified_observer); - tui_bp_modified_observer = gdb::observers::breakpoint_modified.null_token; - gdb::observers::inferior_exit.detach (tui_inferior_exit_observer); - tui_inferior_exit_observer = gdb::observers::inferior_exit.null_token; - gdb::observers::before_prompt.detach (tui_before_prompt_observer); - tui_before_prompt_observer = gdb::observers::before_prompt.null_token; - gdb::observers::normal_stop.detach (tui_normal_stop_observer); - tui_normal_stop_observer = gdb::observers::normal_stop.null_token; - gdb::observers::register_changed.detach (tui_register_changed_observer); - tui_register_changed_observer = gdb::observers::register_changed.null_token; + tui_attach_detach_observers (false); } void -- 2.14.3