mirror of
https://github.com/fish-shell/fish-shell
synced 2024-11-11 15:37:24 +00:00
Make the list of event handlers thread safe
This commit is contained in:
parent
ead16958b2
commit
bc103c2ea6
1 changed files with 18 additions and 15 deletions
|
@ -84,7 +84,7 @@ class pending_signals_t {
|
|||
static pending_signals_t s_pending_signals;
|
||||
|
||||
/// List of event handlers.
|
||||
static event_handler_list_t s_event_handlers;
|
||||
static owning_lock<event_handler_list_t> s_event_handlers;
|
||||
|
||||
/// Variables (one per signal) set when a signal is observed. This is inspected by a signal handler.
|
||||
static volatile sig_atomic_t s_observed_signals[NSIG] = {};
|
||||
|
@ -204,23 +204,23 @@ void event_add_handler(std::shared_ptr<event_handler_t> eh) {
|
|||
set_signal_observed(eh->desc.param1.signal, true);
|
||||
}
|
||||
|
||||
s_event_handlers.push_back(std::move(eh));
|
||||
s_event_handlers.acquire()->push_back(std::move(eh));
|
||||
}
|
||||
|
||||
void event_remove_function_handlers(const wcstring &name) {
|
||||
ASSERT_IS_MAIN_THREAD();
|
||||
auto begin = s_event_handlers.begin(), end = s_event_handlers.end();
|
||||
s_event_handlers.erase(std::remove_if(begin, end,
|
||||
[&](const shared_ptr<event_handler_t> &eh) {
|
||||
return eh->function_name == name;
|
||||
}),
|
||||
end);
|
||||
auto handlers = s_event_handlers.acquire();
|
||||
auto begin = handlers->begin(), end = handlers->end();
|
||||
handlers->erase(std::remove_if(begin, end,
|
||||
[&](const shared_ptr<event_handler_t> &eh) {
|
||||
return eh->function_name == name;
|
||||
}),
|
||||
end);
|
||||
}
|
||||
|
||||
event_handler_list_t event_get_function_handlers(const wcstring &name) {
|
||||
ASSERT_IS_MAIN_THREAD();
|
||||
auto handlers = s_event_handlers.acquire();
|
||||
event_handler_list_t result;
|
||||
for (const shared_ptr<event_handler_t> &eh : s_event_handlers) {
|
||||
for (const shared_ptr<event_handler_t> &eh : *handlers) {
|
||||
if (eh->function_name == name) {
|
||||
result.push_back(eh);
|
||||
}
|
||||
|
@ -247,7 +247,7 @@ static void event_fire_internal(parser_t &parser, const event_t &event) {
|
|||
|
||||
// Capture the event handlers that match this event.
|
||||
event_handler_list_t fire;
|
||||
for (const auto &handler : s_event_handlers) {
|
||||
for (const auto &handler : *s_event_handlers.acquire()) {
|
||||
// Check if this event is a match.
|
||||
if (handler_matches(*handler, event)) {
|
||||
fire.push_back(handler);
|
||||
|
@ -256,8 +256,11 @@ static void event_fire_internal(parser_t &parser, const event_t &event) {
|
|||
|
||||
// Iterate over our list of matching events. Fire the ones that are still present.
|
||||
for (const shared_ptr<event_handler_t> &handler : fire) {
|
||||
// Only fire if this event is still present
|
||||
if (!contains(s_event_handlers, handler)) {
|
||||
// Only fire if this event is still present.
|
||||
// TODO: this is kind of crazy. We want to support removing (and thereby suppressing) an
|
||||
// event handler from another, but we also don't want to hold the lock across callouts. How
|
||||
// can we make this less silly?
|
||||
if (!contains(*s_event_handlers.acquire(), handler)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -365,7 +368,7 @@ static const wchar_t *event_name_for_type(event_type_t type) {
|
|||
}
|
||||
|
||||
void event_print(io_streams_t &streams, maybe_t<event_type_t> type_filter) {
|
||||
event_handler_list_t tmp = s_event_handlers;
|
||||
event_handler_list_t tmp = *s_event_handlers.acquire();
|
||||
std::sort(tmp.begin(), tmp.end(),
|
||||
[](const shared_ptr<event_handler_t> &e1, const shared_ptr<event_handler_t> &e2) {
|
||||
const event_description_t &d1 = e1->desc;
|
||||
|
|
Loading…
Reference in a new issue