Add properties to channels and duplicate support
This commit is contained in:
		
							parent
							
								
									0944f84ac9
								
							
						
					
					
						commit
						9cc563d0dd
					
				| @ -37,7 +37,7 @@ set_dirty(struct chan *chan) | ||||
| { | ||||
| 	if (chan->is_dirty) { | ||||
| 		/* Already dirty and allowed, no need to do anything */ | ||||
| 		if (chan->allow_dirty_write) | ||||
| 		if (chan->prop[CHAN_DIRTY_WRITE]) | ||||
| 			return 0; | ||||
| 
 | ||||
| 		err("channel %s already dirty\n", chan->name); | ||||
| @ -61,8 +61,8 @@ static int | ||||
| check_duplicates(struct chan *chan, struct value *v) | ||||
| { | ||||
| 	/* If duplicates are allowed just skip the check */ | ||||
| 	//if (chan->oflags & CHAN_DUP)
 | ||||
| 	//	return 0;
 | ||||
| 	if (chan->prop[CHAN_DUPLICATES]) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	if (value_is_equal(&chan->last_value, v)) { | ||||
| 		err("check_duplicates %s: same value as last_value\n", | ||||
| @ -82,7 +82,7 @@ chan_set(struct chan *chan, struct value value) | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (chan->is_dirty && !chan->allow_dirty_write) { | ||||
| 	if (chan->is_dirty && !chan->prop[CHAN_DIRTY_WRITE]) { | ||||
| 		err("chan_set %s: cannot modify dirty channel\n", | ||||
| 				chan->name); | ||||
| 		return -1; | ||||
| @ -122,7 +122,7 @@ chan_push(struct chan *chan, struct value value) | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (chan->is_dirty && !chan->allow_dirty_write) { | ||||
| 	if (chan->is_dirty && !chan->prop[CHAN_DIRTY_WRITE]) { | ||||
| 		err("chan_push %s: cannot modify dirty channel\n", | ||||
| 				chan->name); | ||||
| 		return -1; | ||||
| @ -167,7 +167,7 @@ chan_pop(struct chan *chan, struct value evalue) | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (chan->is_dirty && !chan->allow_dirty_write) { | ||||
| 	if (chan->is_dirty && !chan->prop[CHAN_DIRTY_WRITE]) { | ||||
| 		err("chan_pop %s: cannot modify dirty channel\n", | ||||
| 				chan->name); | ||||
| 		return -1; | ||||
| @ -198,33 +198,25 @@ chan_pop(struct chan *chan, struct value evalue) | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| static void | ||||
| get_value(struct chan *chan, struct value *value) | ||||
| { | ||||
| 	if (chan->type == CHAN_SINGLE) { | ||||
| 		 *value = chan->data.value; | ||||
| 		 return 0; | ||||
| 	} else { | ||||
| 		struct chan_stack *stack = &chan->data.stack; | ||||
| 		if (stack->n > 0) | ||||
| 			*value = stack->values[stack->n - 1]; | ||||
| 		else | ||||
| 			*value = value_null(); | ||||
| 	} | ||||
| 
 | ||||
| 	struct chan_stack *stack = &chan->data.stack; | ||||
| 	if (stack->n <= 0) { | ||||
| 		err("get_value %s: channel stack empty\n", chan->name); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	*value = stack->values[stack->n - 1]; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /** Reads the current value of a channel */ | ||||
| int | ||||
| chan_read(struct chan *chan, struct value *value) | ||||
| { | ||||
| 	if (get_value(chan, value) != 0) { | ||||
| 		err("chan_read %s: get_value failed\n", chan->name); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	get_value(chan, value); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| @ -238,13 +230,21 @@ chan_flush(struct chan *chan) | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	get_value(chan, &chan->last_value); | ||||
| 
 | ||||
| 	chan->is_dirty = 0; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| chan_dirty_write(struct chan *chan, int allow) | ||||
| chan_prop_set(struct chan *chan, enum chan_prop prop, int value) | ||||
| { | ||||
| 	chan->allow_dirty_write = allow; | ||||
| 	chan->prop[prop] = value; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| chan_prop_get(struct chan *chan, enum chan_prop prop) | ||||
| { | ||||
| 	return chan->prop[prop]; | ||||
| } | ||||
|  | ||||
| @ -16,6 +16,12 @@ enum chan_type { | ||||
| 	CHAN_MAXTYPE, | ||||
| }; | ||||
| 
 | ||||
| enum chan_prop { | ||||
| 	CHAN_DIRTY_WRITE = 0, | ||||
| 	CHAN_DUPLICATES, | ||||
| 	CHAN_MAXPROP, | ||||
| }; | ||||
| 
 | ||||
| struct chan_stack { | ||||
| 	int n; | ||||
| 	struct value values[MAX_CHAN_STACK]; | ||||
| @ -35,8 +41,7 @@ struct chan { | ||||
| 	enum chan_type type; | ||||
| 	union chan_data data; | ||||
| 	int is_dirty; | ||||
| 	int allow_dirty_write; | ||||
| 	struct value err_value; | ||||
| 	int prop[CHAN_MAXPROP]; | ||||
| 	struct value last_value; | ||||
| 	chan_cb_t dirty_cb; | ||||
| 	void *dirty_arg; | ||||
| @ -53,7 +58,9 @@ int chan_pop(struct chan *chan, struct value expected); | ||||
| int chan_read(struct chan *chan, struct value *value); | ||||
| enum chan_type chan_get_type(struct chan *chan); | ||||
| int chan_flush(struct chan *chan); | ||||
| void chan_dirty_write(struct chan *chan, int allow); | ||||
| 
 | ||||
| void chan_prop_set(struct chan *chan, enum chan_prop prop, int value); | ||||
| int chan_prop_get(struct chan *chan, enum chan_prop prop); | ||||
| 
 | ||||
| /* Called when it becomes dirty */ | ||||
| void chan_set_dirty_cb(struct chan *chan, chan_cb_t func, void *arg); | ||||
|  | ||||
| @ -140,9 +140,9 @@ mux_init(struct mux *mux, | ||||
| 	} | ||||
| 
 | ||||
| 	/* The output channel must accept multiple writes in the same
 | ||||
| 	 * propagation phase, as we may write to the input and select | ||||
| 	 * channel at the same time. */ | ||||
| 	chan_dirty_write(output, 1); | ||||
| 	 * propagation phase while the channel is dirty, as we may write to the | ||||
| 	 * input and select channel at the same time. */ | ||||
| 	chan_prop_set(output, CHAN_DIRTY_WRITE, 1); | ||||
| 
 | ||||
| 	memset(mux, 0, sizeof(struct mux_input)); | ||||
| 	mux->select = select; | ||||
|  | ||||
| @ -18,7 +18,7 @@ test_dirty(void) | ||||
| 	if (chan_flush(&chan) != 0) | ||||
| 		die("chan_flush failed\n"); | ||||
| 
 | ||||
| 	chan_dirty_write(&chan, 1); | ||||
| 	chan_prop_set(&chan, CHAN_DIRTY_WRITE, 1); | ||||
| 
 | ||||
| 	if (chan_set(&chan, value_int64(3)) != 0) | ||||
| 		die("chan_set failed\n"); | ||||
| @ -71,6 +71,30 @@ test_single(void) | ||||
| 		die("chan_read returned unexpected value\n"); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| test_duplicate(void) | ||||
| { | ||||
| 	struct chan chan; | ||||
| 	chan_init(&chan, CHAN_SINGLE, "testchan"); | ||||
| 
 | ||||
| 	if (chan_set(&chan, value_int64(1)) != 0) | ||||
| 		die("chan_set failed\n"); | ||||
| 
 | ||||
| 	if (chan_flush(&chan) != 0) | ||||
| 		die("chan_flush failed\n"); | ||||
| 
 | ||||
| 	/* Attempt to write the same value again */ | ||||
| 	if (chan_set(&chan, value_int64(1)) == 0) | ||||
| 		die("chan_set didn't fail\n"); | ||||
| 
 | ||||
| 	/* Now enable duplicates */ | ||||
| 	chan_prop_set(&chan, CHAN_DUPLICATES, 1); | ||||
| 
 | ||||
| 	/* Then it should allow writting the same value */ | ||||
| 	if (chan_set(&chan, value_int64(1)) != 0) | ||||
| 		die("chan_set failed\n"); | ||||
| } | ||||
| 
 | ||||
| //static void
 | ||||
| //test_stack(void)
 | ||||
| //{
 | ||||
| @ -132,6 +156,7 @@ int main(void) | ||||
| { | ||||
| 	test_single(); | ||||
| 	test_dirty(); | ||||
| 	test_duplicate(); | ||||
| 	//test_stack();
 | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user