From: Andre Noll Date: Mon, 31 Mar 2008 22:23:58 +0000 (+0200) Subject: filter: Switch from linked lists to arrays. X-Git-Tag: v0.3.2~40 X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=commitdiff_plain;h=d32eb7a5cf569ee842d91f3f830a8562fa0ae12d;hp=6f0e4a5138f17d0a150f648fd09fe867c080660a filter: Switch from linked lists to arrays. The number of filters is known and never changes, so it's easier to use arrays. --- diff --git a/audiod.c b/audiod.c index e33f7383..a76ee1fd 100644 --- a/audiod.c +++ b/audiod.c @@ -41,9 +41,9 @@ struct audio_format_info { void *receiver_conf; /** the number of filters that should be activated for this audio format */ unsigned int num_filters; - /** pointer to the array of filters to be activated */ - struct filter **filters; - /** pointer to the array of filter configurations */ + /** Array of filter numbers to be activated. */ + unsigned *filter_nums; + /** Pointer to the array of filter configurations. */ void **filter_conf; /** the number of filters that should be activated for this audio format */ unsigned int num_writers; @@ -268,6 +268,7 @@ static void open_filters(int slot_num) { struct slot_info *s = &slot[slot_num]; struct audio_format_info *a = &afi[s->format]; + struct filter_node *fn; int nf = a->num_filters; int i; @@ -276,26 +277,27 @@ static void open_filters(int slot_num) return; PARA_INFO_LOG("opening %s filters\n", audio_formats[s->format]); s->fc = para_calloc(sizeof(struct filter_chain)); - INIT_LIST_HEAD(&s->fc->filters); + s->fc->filter_nodes = para_malloc(nf * sizeof(struct filter_chain)); s->fc->inbuf = s->receiver_node->buf; s->fc->in_loaded = &s->receiver_node->loaded; s->fc->input_error = &s->receiver_node->task.error; s->fc->task.pre_select = filter_pre_select; + s->fc->task.post_select = NULL; s->fc->task.error = 0; + s->fc->num_filters = nf; s->receiver_node->output_error = &s->fc->task.error; sprintf(s->fc->task.status, "filter chain"); - for (i = 0; i < nf; i++) { - struct filter_node *fn = para_calloc(sizeof(struct filter_node)); + FOR_EACH_FILTER_NODE(fn, s->fc, i) { + struct filter *f = filters + a->filter_nums[i]; + fn->filter_num = a->filter_nums[i]; fn->conf = a->filter_conf[i]; fn->fc = s->fc; - fn->filter = a->filters[i]; + fn->loaded = 0; INIT_LIST_HEAD(&fn->callbacks); - list_add_tail(&fn->node, &s->fc->filters); - fn->filter->open(fn); + f->open(fn); PARA_NOTICE_LOG("%s filter %d/%d (%s) started in slot %d\n", - audio_formats[s->format], i + 1, nf, - fn->filter->name, slot_num); + audio_formats[s->format], i + 1, nf, f->name, slot_num); s->fc->outbuf = fn->buf; s->fc->out_loaded = &fn->loaded; } @@ -336,7 +338,7 @@ static void open_writers(int slot_num) return; } s->wstime = *now; - activate_inactive_grab_clients(slot_num, s->format, &s->fc->filters); + activate_inactive_grab_clients(slot_num, s->format, s->fc); } #if 0 @@ -651,10 +653,10 @@ static int add_filter(int format, char *cmdline) filter_num = check_filter_arg(cmdline, &a->filter_conf[nf]); if (filter_num < 0) return filter_num; - a->filters[nf] = &filters[filter_num]; + a->filter_nums[nf] = filter_num; a->num_filters++; PARA_INFO_LOG("%s filter %d: %s\n", audio_formats[format], nf + 1, - a->filters[nf]->name); + filters[filter_num].name); return filter_num; } @@ -786,7 +788,7 @@ static int init_filters(void) PARA_INFO_LOG("maximal number of filters: %d\n", nf); FOR_EACH_AUDIO_FORMAT(i) { afi[i].filter_conf = para_malloc(nf * sizeof(void *)); - afi[i].filters = para_malloc(nf * sizeof(struct filter *)); + afi[i].filter_nums = para_malloc(nf * sizeof(unsigned)); } if (!conf.no_default_filters_given) return init_default_filters(); diff --git a/audiod_command.c b/audiod_command.c index 875e4551..0428bea1 100644 --- a/audiod_command.c +++ b/audiod_command.c @@ -294,9 +294,10 @@ static struct filter_node *find_filter_node(int slot_num, int format, int filter continue; /* success */ j = 1; - list_for_each_entry(fn, &s->fc->filters, node) + FOR_EACH_FILTER_NODE(fn, s->fc, j) { if (filternum <= 0 || j++ == filternum) break; + } return fn; } return NULL; diff --git a/filter.c b/filter.c index 68c97b45..81d5df1a 100644 --- a/filter.c +++ b/filter.c @@ -41,11 +41,13 @@ INIT_STDERR_LOGGING(conf.loglevel_arg); static void open_filters(void) { + int i; struct filter_node *fn; - list_for_each_entry(fn, &fc->filters, node) { - fn->filter->open(fn); - PARA_INFO_LOG("opened %s filter\n", fn->filter->name); + FOR_EACH_FILTER_NODE(fn, fc, i) { + struct filter *f = filters + fn->filter_num; + f->open(fn); + PARA_INFO_LOG("opened %s filter\n", f->name); fc->outbuf = fn->buf; fc->out_loaded = &fn->loaded; } @@ -53,11 +55,13 @@ static void open_filters(void) static int init_filter_chain(void) { - int i, filter_num; + int i, ret; struct filter_node *fn; - INIT_LIST_HEAD(&fc->filters); - + if (!conf.filter_given) + return -E_NO_FILTERS; + fc->num_filters = conf.filter_given; + fc->filter_nodes = para_malloc(fc->num_filters * sizeof(struct filter_node)); fc->inbuf = sit->buf; fc->in_loaded = &sit->loaded; fc->input_error = &sit->task.error; @@ -66,22 +70,17 @@ static int init_filter_chain(void) fc->task.pre_select = filter_pre_select; sprintf(fc->task.status, "filter chain"); - for (i = 0; i < conf.filter_given; i++) { + FOR_EACH_FILTER_NODE(fn, fc, i) { char *fa = conf.filter_arg[i]; - fn = para_calloc(sizeof(struct filter_node)); - filter_num = check_filter_arg(fa, &fn->conf); - if (filter_num < 0) { - free(fn); - return filter_num; - } + fn = fc->filter_nodes + i; + ret = check_filter_arg(fa, &fn->conf); + if (ret < 0) + return ret; + fn->filter_num = ret; fn->fc = fc; INIT_LIST_HEAD(&fn->callbacks); - fn->filter = &filters[filter_num]; - PARA_DEBUG_LOG("adding %s to filter chain\n", fn->filter->name); - list_add_tail(&fn->node, &fc->filters); + PARA_DEBUG_LOG("filter #%d: %s\n", i, filters[fn->filter_num].name); } - if (list_empty(&fc->filters)) - return -E_NO_FILTERS; open_filters(); return 1; } diff --git a/filter.h b/filter.h index 5cb7aaf8..1b916eec 100644 --- a/filter.h +++ b/filter.h @@ -6,8 +6,35 @@ /** \file filter.h Filter-related structures and exported symbols from filter_chain.c. */ + +/** + * Describes one running instance of a filter. +*/ +struct filter_node { + /** The number in the array of available filters. */ + unsigned filter_num; + /** The filter chain this filter node belongs to. */ + struct filter_chain *fc; + /** + * Each filter may store any filter-specific information about the particular + * instance of the filter here. + */ + void *private_data; + /** The output buffer. */ + char *buf; + /** The size of the output buffer. */ + size_t bufsize; + /** The number of bytes currently loaded in \a buf. */ + size_t loaded; + /** The list of registered callbacks. */ + struct list_head callbacks; + /** A pointer to the configuration of this instance. */ + void *conf; +}; + /** Describes one running instance of a chain of filters */ struct filter_chain { + unsigned int num_filters; /** * The number of channels of the current stream. * @@ -21,7 +48,7 @@ struct filter_chain { */ unsigned int samplerate; /** The list containing all filter nodes in this filter chain. */ - struct list_head filters; + struct filter_node *filter_nodes; /** * The input buffer of the filter chain. * @@ -48,37 +75,9 @@ struct filter_chain { struct task task; }; -/** - * Describes one running instance of a filter. -*/ -struct filter_node { - /** A pointer to the corresponding filter struct. */ - struct filter *filter; - /** The filter chain this filter node belongs to. */ - struct filter_chain *fc; - /** - * The position of the filter in the corresponding filter chain. - * - * All filters that make up the filter chains are organized in a doubly - * linked list. - */ - struct list_head node; - /** - * Each filter may store any filter-specific information about the particular - * instance of the filter here. - */ - void *private_data; - /** The output buffer. */ - char *buf; - /** The size of the output buffer. */ - size_t bufsize; - /** The number of bytes currently loaded in \a buf. */ - size_t loaded; - /** The list of registered callbacks. */ - struct list_head callbacks; - /** A pointer to the configuration of this instance. */ - void *conf; -}; +#define FOR_EACH_FILTER_NODE(fn, fc, i) for (i = 0; i < (fc)->num_filters \ + && (fn = (fc)->filter_nodes + i); i++) + /** * Used to manage grab clients. @@ -130,11 +129,6 @@ struct filter_callback { }; -void close_filters(struct filter_chain *fc); -void filter_init(struct filter *all_filters); -int check_filter_arg(char *filter_arg, void **conf); -void filter_pre_select(__a_unused struct sched *s, struct task *t); - /** * The structure associated with a paraslash filter. * @@ -206,6 +200,11 @@ struct filter { void *(*parse_config)(int argc, char **argv); }; +void close_filters(struct filter_chain *fc); +void filter_init(struct filter *all_filters); +int check_filter_arg(char *filter_arg, void **conf); +void filter_pre_select(__a_unused struct sched *s, struct task *t); + static inline void write_int16_host_endian(char *buf, int val) { diff --git a/filter_chain.c b/filter_chain.c index 97553929..798d58e0 100644 --- a/filter_chain.c +++ b/filter_chain.c @@ -62,7 +62,7 @@ static void close_callbacks(struct filter_node *fn) list_for_each_entry_safe(fcb, tmp, &fn->callbacks, node) { PARA_INFO_LOG("closing %s filter callback\n", - fn->filter->name); + filters[fn->filter_num].name); close_filter_callback(fcb); } } @@ -113,7 +113,7 @@ void filter_pre_select(__a_unused struct sched *s, struct task *t) struct filter_node *fn; char *ib; size_t *loaded; - int conv, conv_total = 0; + int i, conv, conv_total = 0; if (fc->output_error && *fc->output_error < 0) { t->error = *fc->output_error; @@ -123,12 +123,13 @@ again: ib = fc->inbuf; loaded = fc->in_loaded; conv = 0; - list_for_each_entry(fn, &fc->filters, node) { + FOR_EACH_FILTER_NODE(fn, fc, i) { + struct filter *f = filters + fn->filter_num; if (*loaded && fn->loaded < fn->bufsize) { size_t size, old_fn_loaded = fn->loaded; // PARA_DEBUG_LOG("fc %p loaded: %zd, calling %s convert\n", // fc, *loaded, fn->filter->name); - t->error = fn->filter->convert(ib, *loaded, fn); + t->error = f->convert(ib, *loaded, fn); if (t->error < 0) return; size = t->error; @@ -176,18 +177,19 @@ again: */ void close_filters(struct filter_chain *fc) { - struct filter_node *fn, *tmp; + struct filter_node *fn; + int i; if (!fc) return; PARA_NOTICE_LOG("closing filter chain %p\n", fc); - list_for_each_entry_safe(fn, tmp, &fc->filters, node) { + FOR_EACH_FILTER_NODE(fn, fc, i) { + struct filter *f = filters + fn->filter_num; close_callbacks(fn); - PARA_INFO_LOG("closing %s filter\n", fn->filter->name); - fn->filter->close(fn); - list_del(&fn->node); - free(fn); + PARA_INFO_LOG("closing %s filter\n", f->name); + f->close(fn); } + free(fc->filter_nodes); } /* diff --git a/grab_client.c b/grab_client.c index a3db5c68..e348ea2b 100644 --- a/grab_client.c +++ b/grab_client.c @@ -176,7 +176,7 @@ void activate_grab_client(struct grab_client *gc, struct filter_node *fn) * activate_grab_client. */ void activate_inactive_grab_clients(int slot_num, int audio_format_num, - struct list_head *filter_list) + struct filter_chain *fc) { struct grab_client *gc, *tmp; int i; @@ -193,12 +193,10 @@ void activate_inactive_grab_clients(int slot_num, int audio_format_num, num_filters(gc->audio_format_num) < gc->conf->filter_num_arg) continue; - i = 1; - list_for_each_entry(fn, filter_list, node) { + FOR_EACH_FILTER_NODE(fn, fc, i) { if (gc->conf->filter_num_arg <= 0 - || i == gc->conf->filter_num_arg) + || i == gc->conf->filter_num_arg + 1) break; - i++; } activate_grab_client(gc, fn); } diff --git a/grab_client.h b/grab_client.h index 9550afbd..2832f093 100644 --- a/grab_client.h +++ b/grab_client.h @@ -43,6 +43,7 @@ struct grab_client { }; __malloc struct grab_client *grab_client_new(int fd, char *line, int *err); -void activate_inactive_grab_clients(int slot, int audio_format_num, struct list_head *filter_list); +void activate_inactive_grab_clients(int slot_num, int audio_format_num, + struct filter_chain *fc); void activate_grab_client(struct grab_client *gc, struct filter_node *fn); void init_grabbing(void);