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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user