Add multiple callback types in the patchbay
This commit is contained in:
parent
ecc07012c0
commit
e240937e58
@ -6,6 +6,11 @@
|
||||
#include "uthash.h"
|
||||
#include "utlist.h"
|
||||
|
||||
static char *propname[BAY_CB_MAX] = {
|
||||
[BAY_CB_DIRTY] = "dirty",
|
||||
[BAY_CB_EMIT] = "emit"
|
||||
};
|
||||
|
||||
/* Called from the channel when it becomes dirty */
|
||||
static int
|
||||
cb_chan_is_dirty(struct chan *chan, void *arg)
|
||||
@ -14,6 +19,12 @@ cb_chan_is_dirty(struct chan *chan, void *arg)
|
||||
struct bay_chan *bchan = arg;
|
||||
struct bay *bay = bchan->bay;
|
||||
|
||||
if (bay->state != BAY_READY && bay->state != BAY_PROPAGATING) {
|
||||
err("cannot add dirty channel %s in current bay state\n",
|
||||
chan->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (bchan->is_dirty) {
|
||||
err("channel %s already on dirty list\n", chan->name);
|
||||
return -1;
|
||||
@ -94,7 +105,8 @@ bay_remove(struct bay *bay, struct chan *chan)
|
||||
}
|
||||
|
||||
int
|
||||
bay_add_cb(struct bay *bay, struct chan *chan, bay_cb_func_t func, void *arg)
|
||||
bay_add_cb(struct bay *bay, enum bay_cb_type type,
|
||||
struct chan *chan, bay_cb_func_t func, void *arg)
|
||||
{
|
||||
if (func == NULL) {
|
||||
err("bay_add_cb: func is NULL\n");
|
||||
@ -117,8 +129,8 @@ bay_add_cb(struct bay *bay, struct chan *chan, bay_cb_func_t func, void *arg)
|
||||
cb->func = func;
|
||||
cb->arg = arg;
|
||||
|
||||
DL_APPEND(bchan->cb, cb);
|
||||
bchan->ncallbacks++;
|
||||
DL_APPEND(bchan->cb[type], cb);
|
||||
bchan->ncallbacks[type]++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -130,13 +142,14 @@ bay_init(struct bay *bay)
|
||||
}
|
||||
|
||||
static int
|
||||
propagate_chan(struct bay_chan *bchan)
|
||||
propagate_chan(struct bay_chan *bchan, enum bay_cb_type type)
|
||||
{
|
||||
dbg("- propagating dirty channel %s\n", bchan->chan->name);
|
||||
dbg("- propagating channel '%s' phase %s\n",
|
||||
bchan->chan->name, propname[type]);
|
||||
|
||||
struct bay_cb *cur = NULL;
|
||||
struct bay_cb *tmp = NULL;
|
||||
DL_FOREACH_SAFE(bchan->cb, cur, tmp) {
|
||||
DL_FOREACH_SAFE(bchan->cb[type], cur, tmp) {
|
||||
if (cur->func(bchan->chan, cur->arg) != 0) {
|
||||
err("propagate_chan: callback failed\n");
|
||||
return -1;
|
||||
@ -149,20 +162,31 @@ propagate_chan(struct bay_chan *bchan)
|
||||
int
|
||||
bay_propagate(struct bay *bay)
|
||||
{
|
||||
dbg("-- propagating channels begins\n");
|
||||
struct bay_chan *cur = NULL;
|
||||
struct bay_chan *tmp = NULL;
|
||||
struct bay_chan *cur, *tmp;
|
||||
bay->state = BAY_PROPAGATING;
|
||||
DL_FOREACH_SAFE(bay->dirty, cur, tmp) {
|
||||
/* May add more dirty channels */
|
||||
if (propagate_chan(cur) != 0) {
|
||||
if (propagate_chan(cur, BAY_CB_DIRTY) != 0) {
|
||||
err("bay_propagate: propagate_chan failed\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Flush channels after running all the dirty callbacks, so we
|
||||
* capture any potential double write when running the
|
||||
* callbacks */
|
||||
/* Once the dirty callbacks have been propagated,
|
||||
* begin the emit stage */
|
||||
bay->state = BAY_EMITTING;
|
||||
DL_FOREACH_SAFE(bay->dirty, cur, tmp) {
|
||||
/* May add more dirty channels */
|
||||
if (propagate_chan(cur, BAY_CB_EMIT) != 0) {
|
||||
err("bay_propagate: propagate_chan failed\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Flush channels after running all the dirty and emit
|
||||
* callbacks, so we capture any potential double write when
|
||||
* running the callbacks */
|
||||
bay->state = BAY_FLUSHING;
|
||||
DL_FOREACH_SAFE(bay->dirty, cur, tmp) {
|
||||
if (chan_flush(cur->chan) != 0) {
|
||||
err("bay_propagate: chan_flush failed\n");
|
||||
@ -172,19 +196,7 @@ bay_propagate(struct bay *bay)
|
||||
}
|
||||
|
||||
bay->dirty = NULL;
|
||||
|
||||
dbg("-- propagating channels ends\n");
|
||||
bay->state = BAY_READY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//int
|
||||
//bay_emit(struct bay *bay)
|
||||
//{
|
||||
// for (chan in dirty channels) {
|
||||
// /* May add more dirty channels */
|
||||
// emit_chan(chan);
|
||||
// }
|
||||
//
|
||||
// return 0;
|
||||
//}
|
||||
|
@ -10,6 +10,12 @@ struct bay;
|
||||
struct bay_cb;
|
||||
struct bay_chan;
|
||||
|
||||
enum bay_cb_type {
|
||||
BAY_CB_DIRTY = 0,
|
||||
BAY_CB_EMIT,
|
||||
BAY_CB_MAX,
|
||||
};
|
||||
|
||||
typedef int (*bay_cb_func_t)(struct chan *chan, void *ptr);
|
||||
|
||||
struct bay_cb {
|
||||
@ -25,8 +31,8 @@ struct bay_cb {
|
||||
|
||||
struct bay_chan {
|
||||
struct chan *chan;
|
||||
int ncallbacks;
|
||||
struct bay_cb *cb;
|
||||
int ncallbacks[BAY_CB_MAX];
|
||||
struct bay_cb *cb[BAY_CB_MAX];
|
||||
struct bay *bay;
|
||||
int is_dirty;
|
||||
|
||||
@ -39,12 +45,11 @@ struct bay_chan {
|
||||
};
|
||||
|
||||
enum bay_state {
|
||||
BAY_CONFIG = 1,
|
||||
BAY_UKNOWN = 0,
|
||||
BAY_READY,
|
||||
BAY_PROPAGATING,
|
||||
BAY_PROPAGATED,
|
||||
BAY_EMITTING,
|
||||
BAY_EMITTED
|
||||
BAY_FLUSHING
|
||||
};
|
||||
|
||||
struct bay {
|
||||
@ -53,11 +58,11 @@ struct bay {
|
||||
struct bay_chan *dirty;
|
||||
};
|
||||
|
||||
void bay_init(struct bay *bay);
|
||||
int bay_register(struct bay *bay, struct chan *chan);
|
||||
int bay_remove(struct bay *bay, struct chan *chan);
|
||||
struct chan *bay_find(struct bay *bay, const char *name);
|
||||
int bay_add_cb(struct bay *bay, struct chan *chan, bay_cb_func_t func, void *arg);
|
||||
void bay_init(struct bay *bay);
|
||||
int bay_add_cb(struct bay *bay, enum bay_cb_type type, struct chan *chan, bay_cb_func_t func, void *arg);
|
||||
int bay_propagate(struct bay *bay);
|
||||
|
||||
#endif /* BAY_H */
|
||||
|
@ -173,7 +173,7 @@ mux_init(struct mux *mux,
|
||||
mux->select_func = select_func;
|
||||
mux->bay = bay;
|
||||
|
||||
if (bay_add_cb(bay, select, cb_select, mux) != 0) {
|
||||
if (bay_add_cb(bay, BAY_CB_DIRTY, select, cb_select, mux) != 0) {
|
||||
err("mux_init: bay_add_cb failed\n");
|
||||
return -1;
|
||||
}
|
||||
@ -222,7 +222,7 @@ mux_add_input(struct mux *mux, struct value key, struct chan *chan)
|
||||
|
||||
HASH_ADD_KEYPTR(hh, mux->input, &input->key, sizeof(input->key), input);
|
||||
|
||||
if (bay_add_cb(mux->bay, chan, cb_input, mux) != 0) {
|
||||
if (bay_add_cb(mux->bay, BAY_CB_DIRTY, chan, cb_input, mux) != 0) {
|
||||
err("mux_add_input: bay_add_cb failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
@ -17,15 +17,6 @@ typedef int (* mux_select_func_t)(struct mux *mux,
|
||||
struct value value,
|
||||
struct mux_input **input);
|
||||
|
||||
/* MUX logic:
|
||||
*
|
||||
* select input output
|
||||
* ---------------------------
|
||||
* null - null
|
||||
* input x x
|
||||
*
|
||||
*/
|
||||
|
||||
struct mux {
|
||||
struct bay *bay;
|
||||
int64_t ninputs;
|
||||
|
@ -27,6 +27,8 @@
|
||||
/* Poison assert */
|
||||
#pragma GCC poison assert
|
||||
|
||||
#define USE_RET __attribute__((warn_unused_result))
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
#endif /* COMMON_H */
|
||||
|
@ -62,7 +62,7 @@ test_callback(struct bay *bay)
|
||||
die("bay_register failed\n");
|
||||
|
||||
int64_t data = 0;
|
||||
if (bay_add_cb(bay, &chan, callback, &data) != 0)
|
||||
if (bay_add_cb(bay, BAY_CB_DIRTY, &chan, callback, &data) != 0)
|
||||
die("bay_add_cb failed\n");
|
||||
|
||||
if (data != 0)
|
||||
|
Loading…
Reference in New Issue
Block a user