Add properties to channels and duplicate support

This commit is contained in:
Rodrigo Arias 2023-01-11 11:58:23 +01:00 committed by Rodrigo Arias Mallo
parent 0944f84ac9
commit 9cc563d0dd
4 changed files with 63 additions and 31 deletions

View File

@ -37,7 +37,7 @@ set_dirty(struct chan *chan)
{ {
if (chan->is_dirty) { if (chan->is_dirty) {
/* Already dirty and allowed, no need to do anything */ /* Already dirty and allowed, no need to do anything */
if (chan->allow_dirty_write) if (chan->prop[CHAN_DIRTY_WRITE])
return 0; return 0;
err("channel %s already dirty\n", chan->name); err("channel %s already dirty\n", chan->name);
@ -61,8 +61,8 @@ static int
check_duplicates(struct chan *chan, struct value *v) check_duplicates(struct chan *chan, struct value *v)
{ {
/* If duplicates are allowed just skip the check */ /* If duplicates are allowed just skip the check */
//if (chan->oflags & CHAN_DUP) if (chan->prop[CHAN_DUPLICATES])
// return 0; return 0;
if (value_is_equal(&chan->last_value, v)) { if (value_is_equal(&chan->last_value, v)) {
err("check_duplicates %s: same value as last_value\n", err("check_duplicates %s: same value as last_value\n",
@ -82,7 +82,7 @@ chan_set(struct chan *chan, struct value value)
return -1; 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", err("chan_set %s: cannot modify dirty channel\n",
chan->name); chan->name);
return -1; return -1;
@ -122,7 +122,7 @@ chan_push(struct chan *chan, struct value value)
return -1; 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", err("chan_push %s: cannot modify dirty channel\n",
chan->name); chan->name);
return -1; return -1;
@ -167,7 +167,7 @@ chan_pop(struct chan *chan, struct value evalue)
return -1; 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", err("chan_pop %s: cannot modify dirty channel\n",
chan->name); chan->name);
return -1; return -1;
@ -198,33 +198,25 @@ chan_pop(struct chan *chan, struct value evalue)
return 0; return 0;
} }
static int static void
get_value(struct chan *chan, struct value *value) get_value(struct chan *chan, struct value *value)
{ {
if (chan->type == CHAN_SINGLE) { if (chan->type == CHAN_SINGLE) {
*value = chan->data.value; *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 */ /** Reads the current value of a channel */
int int
chan_read(struct chan *chan, struct value *value) chan_read(struct chan *chan, struct value *value)
{ {
if (get_value(chan, value) != 0) { get_value(chan, value);
err("chan_read %s: get_value failed\n", chan->name);
return -1;
}
return 0; return 0;
} }
@ -238,13 +230,21 @@ chan_flush(struct chan *chan)
return -1; return -1;
} }
get_value(chan, &chan->last_value);
chan->is_dirty = 0; chan->is_dirty = 0;
return 0; return 0;
} }
void 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];
} }

View File

@ -16,6 +16,12 @@ enum chan_type {
CHAN_MAXTYPE, CHAN_MAXTYPE,
}; };
enum chan_prop {
CHAN_DIRTY_WRITE = 0,
CHAN_DUPLICATES,
CHAN_MAXPROP,
};
struct chan_stack { struct chan_stack {
int n; int n;
struct value values[MAX_CHAN_STACK]; struct value values[MAX_CHAN_STACK];
@ -35,8 +41,7 @@ struct chan {
enum chan_type type; enum chan_type type;
union chan_data data; union chan_data data;
int is_dirty; int is_dirty;
int allow_dirty_write; int prop[CHAN_MAXPROP];
struct value err_value;
struct value last_value; struct value last_value;
chan_cb_t dirty_cb; chan_cb_t dirty_cb;
void *dirty_arg; 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); int chan_read(struct chan *chan, struct value *value);
enum chan_type chan_get_type(struct chan *chan); enum chan_type chan_get_type(struct chan *chan);
int chan_flush(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 */ /* Called when it becomes dirty */
void chan_set_dirty_cb(struct chan *chan, chan_cb_t func, void *arg); void chan_set_dirty_cb(struct chan *chan, chan_cb_t func, void *arg);

View File

@ -140,9 +140,9 @@ mux_init(struct mux *mux,
} }
/* The output channel must accept multiple writes in the same /* The output channel must accept multiple writes in the same
* propagation phase, as we may write to the input and select * propagation phase while the channel is dirty, as we may write to the
* channel at the same time. */ * input and select channel at the same time. */
chan_dirty_write(output, 1); chan_prop_set(output, CHAN_DIRTY_WRITE, 1);
memset(mux, 0, sizeof(struct mux_input)); memset(mux, 0, sizeof(struct mux_input));
mux->select = select; mux->select = select;

View File

@ -18,7 +18,7 @@ test_dirty(void)
if (chan_flush(&chan) != 0) if (chan_flush(&chan) != 0)
die("chan_flush failed\n"); 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) if (chan_set(&chan, value_int64(3)) != 0)
die("chan_set failed\n"); die("chan_set failed\n");
@ -71,6 +71,30 @@ test_single(void)
die("chan_read returned unexpected value\n"); 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 //static void
//test_stack(void) //test_stack(void)
//{ //{
@ -132,6 +156,7 @@ int main(void)
{ {
test_single(); test_single();
test_dirty(); test_dirty();
test_duplicate();
//test_stack(); //test_stack();
return 0; return 0;
} }