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) {
|
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];
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user