void event_remove(const event_t &criterion) { event_list_t new_list; if (debug_level >= 3) { wcstring desc = event_desc_compact(criterion); debug(3, "unregister: %ls\n", desc.c_str()); } // Because of concurrency issues (env_remove could remove an event that is currently being // executed), env_remove does not actually free any events - instead it simply moves all events // that should be removed from the event list to the killme list, and the ones that shouldn't be // killed to new_list, and then drops the empty events-list. if (s_event_handlers.empty()) return; for (size_t i = 0; i < s_event_handlers.size(); i++) { event_t *n = s_event_handlers.at(i); if (event_match(criterion, *n)) { killme.push_back(n); // If this event was a signal handler and no other handler handles the specified signal // type, do not handle that type of signal any more. if (n->type == EVENT_SIGNAL) { event_t e = event_t::signal_event(n->param1.signal); if (event_get(e, 0) == 1) { signal_handle(e.param1.signal, 0); set_signal_observed(e.param1.signal, 0); } } } else { new_list.push_back(n); } } s_event_handlers.swap(new_list); }
t_callback which_callback(t_lst *events_p, t_event event) { t_callback callback; t_event mask; mask = T_EVENT(~0, NULL); callback = event_match(wrapper_event_match, events_p, &event, &mask); return (NULL); }
static int find_event(struct pevent *pevent, struct event_list **events, char *sys_name, char *event_name) { struct event_format *event; regex_t ereg; regex_t sreg; int match = 0; char *reg; int ret; int i; if (!event_name) { /* if no name is given, then swap sys and name */ event_name = sys_name; sys_name = NULL; } reg = malloc_or_die(strlen(event_name) + 3); sprintf(reg, "^%s$", event_name); ret = regcomp(&ereg, reg, REG_ICASE|REG_NOSUB); free(reg); if (ret) return -1; if (sys_name) { reg = malloc_or_die(strlen(sys_name) + 3); sprintf(reg, "^%s$", sys_name); ret = regcomp(&sreg, reg, REG_ICASE|REG_NOSUB); free(reg); if (ret) { regfree(&ereg); return -1; } } for (i = 0; i < pevent->nr_events; i++) { event = pevent->events[i]; if (event_match(event, sys_name ? &sreg : NULL, &ereg)) { match = 1; add_event(events, event); } } regfree(&ereg); if (sys_name) regfree(&sreg); if (!match) return -1; return 0; }
int event_get(const event_t &criterion, std::vector<event_t *> *out) { int found = 0; for (size_t i = 0; i < s_event_handlers.size(); i++) { event_t *n = s_event_handlers.at(i); if (event_match(criterion, *n)) { found++; if (out) out->push_back(n); } } return found; }
/** * matecomponent_event_source_notify_listeners: * @event_source: the Event Source that will emit the event. * @event_name: Name of the event being emitted * @opt_value: A CORBA_any value that contains the data that is passed * to interested clients, or NULL for an empty value * @opt_ev: A CORBA_Environment where a failure code can be returned, can be NULL. * * This will notify all clients that have registered with this EventSource * (through the addListener or addListenerWithMask methods) of the availability * of the event named @event_name. The @value CORBA::any value is passed to * all listeners. * * @event_name can not contain comma separators, as commas are used to * separate the various event names. */ void matecomponent_event_source_notify_listeners (MateComponentEventSource *event_source, const char *event_name, const CORBA_any *opt_value, CORBA_Environment *opt_ev) { GSList *l, *notify; CORBA_Environment *ev, temp_ev; const MateComponentArg *my_value; g_return_if_fail (MATECOMPONENT_IS_EVENT_SOURCE (event_source)); if (!opt_ev) { CORBA_exception_init (&temp_ev); ev = &temp_ev; } else ev = opt_ev; if (!opt_value) my_value = matecomponent_arg_new (MATECOMPONENT_ARG_NULL); else my_value = opt_value; notify = NULL; for (l = event_source->priv->listeners; l; l = l->next) { ListenerDesc *desc = (ListenerDesc *) l->data; if (desc->event_masks == NULL || event_match (event_name, desc->event_masks)) { notify = g_slist_prepend ( notify, CORBA_Object_duplicate (desc->listener, ev)); } } matecomponent_object_ref (MATECOMPONENT_OBJECT (event_source)); for (l = notify; l; l = l->next) { MateComponent_Listener_event (l->data, event_name, my_value, ev); CORBA_Object_release (l->data, ev); } matecomponent_object_unref (MATECOMPONENT_OBJECT (event_source)); g_slist_free (notify); if (!opt_ev) CORBA_exception_free (ev); if (!opt_value) matecomponent_arg_release ((MateComponentArg *) my_value); }
void event_remove(event_t *criterion) { size_t i; event_list_t new_list; CHECK(criterion,); /* Because of concurrency issues (env_remove could remove an event that is currently being executed), env_remove does not actually free any events - instead it simply moves all events that should be removed from the event list to the killme list, and the ones that shouldn't be killed to new_list, and then drops the empty events-list. */ if (events.empty()) return; for (i=0; i<events.size(); i++) { event_t *n = events.at(i); if (event_match(criterion, n)) { killme.push_back(n); /* If this event was a signal handler and no other handler handles the specified signal type, do not handle that type of signal any more. */ if (n->type == EVENT_SIGNAL) { event_t e = event_t::signal_event(n->param1.signal); if (event_get(&e, 0) == 1) { signal_handle(e.param1.signal, 0); } } } else { new_list.push_back(n); } } signal_block(); events.swap(new_list); signal_unblock(); }
int event_get(const event_t &criterion, std::vector<event_t *> *out) { size_t i; int found = 0; if (events.empty()) return 0; for (i=0; i<events.size(); i++) { event_t *n = events.at(i); if (event_match(criterion, *n)) { found++; if (out) out->push_back(n); } } return found; }
/** * matecomponent_event_source_has_listener: * @event_source: the Event Source that will emit the event. * @event_name: Name of the event being emitted * * This method determines if there are any listeners for * the event to be broadcast. This can be used to detect * whether it is worth constructing a potentialy expensive * state update, before sending it to no-one. * * Return value: TRUE if it's worth sending, else FALSE **/ gboolean matecomponent_event_source_has_listener (MateComponentEventSource *event_source, const char *event_name) { GSList *l; gboolean notify; g_return_val_if_fail (MATECOMPONENT_IS_EVENT_SOURCE (event_source), FALSE); notify = FALSE; for (l = event_source->priv->listeners; l; l = l->next) { ListenerDesc *desc = (ListenerDesc *) l->data; if (desc->event_masks == NULL || event_match (event_name, desc->event_masks)) { notify = TRUE; break; } } return notify; }
/** Perform the specified event. Since almost all event firings will not be matched by even a single event handler, we make sure to optimize the 'no matches' path. This means that nothing is allocated/initialized unless needed. */ static void event_fire_internal(const event_t &event) { event_list_t fire; /* First we free all events that have been removed, but only if this invocation of event_fire_internal is not a recursive call. */ if (is_event <= 1) event_free_kills(); if (events.empty()) return; /* Then we iterate over all events, adding events that should be fired to a second list. We need to do this in a separate step since an event handler might call event_remove or event_add_handler, which will change the contents of the \c events list. */ for (size_t i=0; i<events.size(); i++) { event_t *criterion = events.at(i); /* Check if this event is a match */ if (event_match(*criterion, event)) { fire.push_back(criterion); } } /* No matches. Time to return. */ if (fire.empty()) return; if (signal_is_blocked()) { /* Fix for https://github.com/fish-shell/fish-shell/issues/608. Don't run event handlers while signals are blocked. */ event_t *heap_event = new event_t(event); input_common_add_callback(fire_event_callback, heap_event); return; } /* Iterate over our list of matching events */ for (size_t i=0; i<fire.size(); i++) { event_t *criterion = fire.at(i); int prev_status; /* Check if this event has been removed, if so, dont fire it */ if (event_is_killed(*criterion)) continue; /* Fire event */ wcstring buffer = criterion->function_name; for (size_t j=0; j < event.arguments.size(); j++) { wcstring arg_esc = escape_string(event.arguments.at(j), 1); buffer += L" "; buffer += arg_esc; } // debug( 1, L"Event handler fires command '%ls'", buffer.c_str() ); /* Event handlers are not part of the main flow of code, so they are marked as non-interactive */ proc_push_interactive(0); prev_status = proc_get_last_status(); parser_t &parser = parser_t::principal_parser(); block_t *block = new event_block_t(event); parser.push_block(block); parser.eval(buffer, io_chain_t(), TOP); parser.pop_block(); proc_pop_interactive(); proc_set_last_status(prev_status); } /* Free killed events */ if (is_event <= 1) event_free_kills(); }
/** Perform the specified event. Since almost all event firings will not be matched by even a single event handler, we make sure to optimize the 'no matches' path. This means that nothing is allocated/initialized unless needed. */ static void event_fire_internal(const event_t *event) { size_t i, j; event_list_t fire; /* First we free all events that have been removed */ event_free_kills(); if (events.empty()) return; /* Then we iterate over all events, adding events that should be fired to a second list. We need to do this in a separate step since an event handler might call event_remove or event_add_handler, which will change the contents of the \c events list. */ for (i=0; i<events.size(); i++) { event_t *criterion = events.at(i); /* Check if this event is a match */ if (event_match(criterion, event)) { fire.push_back(criterion); } } /* No matches. Time to return. */ if (fire.empty()) return; /* Iterate over our list of matching events */ for (i=0; i<fire.size(); i++) { event_t *criterion = fire.at(i); int prev_status; /* Check if this event has been removed, if so, dont fire it */ if (event_is_killed(criterion)) continue; /* Fire event */ wcstring buffer = criterion->function_name; if (event->arguments.get()) { for (j=0; j< event->arguments->size(); j++) { wcstring arg_esc = escape_string(event->arguments->at(j), 1); buffer += L" "; buffer += arg_esc; } } // debug( 1, L"Event handler fires command '%ls'", buffer.c_str() ); /* Event handlers are not part of the main flow of code, so they are marked as non-interactive */ proc_push_interactive(0); prev_status = proc_get_last_status(); parser_t &parser = parser_t::principal_parser(); block_t *block = new event_block_t(event); parser.push_block(block); parser.eval(buffer, io_chain_t(), TOP); parser.pop_block(); proc_pop_interactive(); proc_set_last_status(prev_status); } /* Free killed events */ event_free_kills(); }
int wrapper_event_match(t_event *elem1, t_event *elem2, t_event *mask) { return (event_match(*elem1, *elem2, mask)); }