static INLINE void send_event(part_evtlist_t *evlist, void **val, bool (*match_func)(void **a, void **b)) { elistdata_t eld_p; mempart_evt_t *reg_event = get_first_event(evlist, &eld_p); while (reg_event != NULL) { struct evt_info_s *evt = ®_event->evt_reg; if (reg_event->onlist == &evlist->active) { /* if this event has been deactivated, don't send it */ if (evt->flags & evtflags_DEACTIVATE) { deactivate_event(evlist, (part_evt_t *)reg_event); } /* check for event send conditions */ else if (reg_event->evt_dest.rcvid > 0) { void **compare_val_p = GET_COMPARE_VAL_P(evt); CRASHCHECK(compare_val_p == NULL); /* * if the caller did not provide a match function, or a match * function was provided and it returns TRUE, deliver the event */ if ((match_func == NULL) || (match_func(compare_val_p, val) == bool_t_TRUE)) { int r; struct sigevent se = evt->sig; // make a local copy /* * if the caller has set evtflags_SIGEV_FLAG_SIGINFO, we * can return some useful information */ if (evt->flags & evtflags_SIGEV_FLAG_SIGINFO) { se.sigev_value.sival_ptr = *val; } r = apm_deliver_event(®_event->evt_dest, &se); if (r == EOK) reg_event->undeliverable_count = 0; else if (r == ESRCH) ++reg_event->undeliverable_count; if ((reg_event->undeliverable_count > ORPHAN_RETRY_COUNT) || (!(evt->flags & evtflags_REARM))) { /* remove the event from the list */ deactivate_event(evlist, (part_evt_t *)reg_event); } } } } reg_event = get_next_event(evlist, reg_event, &eld_p); } }
// * Must be called when deleting a patch or track. (why?) // * Can't there be hanging notes, or other undefined behaviors, when the event callback is not called? // Returns true if everything was cleared. bool SCHEDULER_clear(void){ //printf("TODO: Implermnet SCHEDULER_clear\n"); const int max_to_remove = 20; // 2048/20 = 102.4. 102.4 * 64 frames / (48000 frames / seconds) = 0.1365 seconds. I.e. we should never wait more than approx. 0.14 seconds for all events to be cleared. int num_removed = 0; while(g_queue_size>0 && num_removed < max_to_remove){ event_t *event = get_first_event(); remove_first_event(); release_event(event); num_removed++; } if (g_queue_size > 0) return false; else return true; }
void SCHEDULER_called_per_block(int64_t reltime){ int64_t end_time = g_current_time + reltime; while(g_queue_size>0){ event_t *event = get_first_event(); int64_t event_time = event->time >> SCHEDULER_NUM_PRIORITY_BITS; // remove priority bits. if(event_time < end_time){ remove_first_event(); { event->callback(scheduler_to_seq_time(event_time), &event->args[0]); // note that the callback can also schedule new events } release_event(event); }else break; } g_current_time = end_time; }
static INLINE void send_delta_events(part_evtlist_t *evlist, memsize_t cur_size, memsize_t prev_size, bool (*compare_func)(memsize_t delta, memsize_t last_sz, memsize_t cur_sz)) { elistdata_t eld_p; mempart_evt_t *reg_event = get_first_event(evlist, &eld_p); while (reg_event != NULL) { struct evt_info_s *evt = ®_event->evt_reg; if (reg_event->onlist == &evlist->active) { memsize_t *delta_p = GET_DELTA_P(evt); CRASHCHECK(delta_p == NULL); initial_delta_conditions_check(reg_event, prev_size, (void *)compare_func); /* if this event has been deactivated, don't send it */ if (evt->flags & evtflags_DEACTIVATE) { deactivate_event(evlist, (part_evt_t *)reg_event); } /* check for event send conditions */ else if ((reg_event->evt_dest.rcvid > 0) && ((compare_func == NULL) || (compare_func(*delta_p, reg_event->evt_data.size, cur_size) == bool_t_TRUE))) { int r; struct sigevent se = evt->sig; // make a local copy /* * if the caller has set evtflags_SIGEV_FLAG_SIGINFO, we * can return some useful information */ if (evt->flags & evtflags_SIGEV_FLAG_SIGINFO) { /* * if the 'cur_size' is too large to fit in the sival_int field * then send back UINT_MAX. This otherwise illegal size value * (because UINT_MAX & (__PAGESIZE - 1) != 0) will be an indication * to the event receiver that o information was provided and * that they need to request the current size if they need it */ if (cur_size > UINT_MAX) { se.sigev_value.sival_int = UINT_MAX; } else { se.sigev_value.sival_int = (_Uint32t)cur_size; } } r = apm_deliver_event(®_event->evt_dest, &se); if (r == EOK) reg_event->undeliverable_count = 0; else if (r == ESRCH) ++reg_event->undeliverable_count; if ((reg_event->undeliverable_count > ORPHAN_RETRY_COUNT) || (!(evt->flags & evtflags_REARM))) { /* remove the event from the list */ deactivate_event(evlist, (part_evt_t *)reg_event); } else { reg_event->evt_data.size = cur_size; } } } reg_event = get_next_event(evlist, reg_event, &eld_p); } }