Skip to content

Commit

Permalink
Get rid of keyed data.
Browse files Browse the repository at this point in the history
  • Loading branch information
tmadden committed Oct 10, 2020
1 parent c8240f5 commit 62f1905
Show file tree
Hide file tree
Showing 4 changed files with 2 additions and 301 deletions.
167 changes: 0 additions & 167 deletions src/alia/flow/data_graph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -525,173 +525,6 @@ get_cached_data(Context& ctx)
return *data;
}

// get_keyed_data(ctx, key, &signal) is a utility for retrieving cached data
// from a data graph.
// It stores not only the data but also a key that identifies the data.
// The key is presented at each retrieval, and if it changes, the associated
// data is invalidated and must be recomputed.

// The return value is true iff the data needs to be recomputed.

template<class Data>
struct keyed_data
{
captured_id key;
bool is_valid;
Data value;
keyed_data() : is_valid(false)
{
}
};

template<class Data>
bool
is_valid(keyed_data<Data> const& data)
{
return data.is_valid;
}

template<class Data>
void
invalidate(keyed_data<Data>& data)
{
data.is_valid = false;
data.key.clear();
}

template<class Data>
void
mark_valid(keyed_data<Data>& data)
{
data.is_valid = true;
}

template<class Data>
bool
refresh_keyed_data(keyed_data<Data>& data, id_interface const& key)
{
if (!data.key.matches(key))
{
data.is_valid = false;
data.key.capture(key);
return true;
}
return false;
}

template<class Data>
void
set(keyed_data<Data>& data, Data value)
{
data.value = std::move(value);
mark_valid(data);
}

template<class Data>
Data const&
get(keyed_data<Data> const& data)
{
assert(is_valid(data));
return data.value;
}

template<class Data>
struct keyed_data_signal
: signal<keyed_data_signal<Data>, Data, readable_duplex_signal>
{
keyed_data_signal()
{
}
keyed_data_signal(keyed_data<Data>* data) : data_(data)
{
}
bool
has_value() const
{
return data_->is_valid;
}
Data const&
read() const
{
return data_->value;
}
id_interface const&
value_id() const
{
return data_->key.is_initialized() ? data_->key.get() : null_id;
}
bool
ready_to_write() const
{
return true;
}
void
write(Data value) const
{
alia::set(*data_, std::move(value));
}
Data
movable_value() const
{
Data movable = std::move(data_->value);
return movable;
}

private:
keyed_data<Data>* data_;
};

template<class Data>
keyed_data_signal<Data>
make_signal(keyed_data<Data>* data)
{
return keyed_data_signal<Data>(data);
}

template<class Context, class Data>
bool
get_keyed_data(
Context ctx, id_interface const& key, keyed_data_signal<Data>* signal)
{
keyed_data<Data>* ptr;
get_cached_data(ctx, &ptr);
refresh_keyed_data(*ptr, key);
*signal = make_signal(ptr);
return !is_valid(*ptr);
};

// This is another form of get_keyed_data where there's no signal to guard
// access to the retrieved data. Thus, it's up to the caller to track whether
// or not the data is properly initialized.

template<class Data>
struct raw_keyed_data
{
captured_id key;
Data data;
};

template<class Context, class Data>
bool
get_keyed_data(Context ctx, id_interface const& key, Data** data)
{
raw_keyed_data<Data>* ptr;
bool is_new = false;
if (get_cached_data(ctx, &ptr))
{
ptr->key.capture(key);
is_new = true;
}
else if (!ptr->key.matches(key))
{
ptr->key.capture(key);
ptr->data = Data();
is_new = true;
}
*data = &ptr->data;
return is_new;
};

// scoped_data_traversal can be used to manage a traversal of a graph.
// begin(graph, traversal) will initialize traversal to act as a traversal of
// graph.
Expand Down
22 changes: 2 additions & 20 deletions src/alia/signals/text.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,28 +92,10 @@ ALIA_DECLARE_STRING_CONVERSIONS(std::string)

// as_text(ctx, x) creates a text-based interface to the signal x.
template<class Readable>
void
update_text_conversion(keyed_data<std::string>* data, Readable x)
{
if (signal_has_value(x))
{
refresh_keyed_data(*data, x.value_id());
if (!is_valid(*data))
set(*data, to_string(read_signal(x)));
}
else
{
invalidate(*data);
}
}
template<class Readable>
keyed_data_signal<std::string>
auto
as_text(context ctx, Readable x)
{
keyed_data<std::string>* data;
get_cached_data(ctx, &data);
update_text_conversion(data, x);
return keyed_data_signal<std::string>(data);
return apply(ctx, ALIA_LAMBDIFY(to_string), x);
}

// as_duplex_text(ctx, x) is similar to as_text but it's duplex.
Expand Down
95 changes: 0 additions & 95 deletions unit_tests/flow/data_graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -495,101 +495,6 @@ TEST_CASE("scoped_cache_clearing_disabler", "[data_graph]")
"destructing int;");
}

TEST_CASE("keyed_data", "[data_graph]")
{
keyed_data<int> i;
REQUIRE(!is_valid(i));

set(i, 2);
REQUIRE(is_valid(i));
REQUIRE(get(i) == 2);

invalidate(i);
REQUIRE(!is_valid(i));

mark_valid(i);
REQUIRE(is_valid(i));
REQUIRE(get(i) == 2);

refresh_keyed_data(i, make_id(0));
REQUIRE(!is_valid(i));

set(i, 1);
REQUIRE(is_valid(i));
REQUIRE(get(i) == 1);

refresh_keyed_data(i, make_id(0));
REQUIRE(is_valid(i));

refresh_keyed_data(i, make_id(1));
REQUIRE(!is_valid(i));
}

TEST_CASE("signal-based get_keyed_data", "[data_graph]")
{
clear_log();
{
data_graph graph;
auto make_controller = [](int i) {
return [=](context ctx) {
do_keyed_int(ctx, i);
do_keyed_int(ctx, 0);
};
};
do_traversal(graph, make_controller(1));
check_log(
"initializing keyed int: 1;"
"initializing keyed int: 0;");
do_traversal(graph, make_controller(1));
check_log(
"visiting keyed int: 1;"
"visiting keyed int: 0;");
do_traversal(graph, make_controller(2));
check_log(
"initializing keyed int: 2;"
"visiting keyed int: 0;");
do_traversal(graph, make_controller(2));
check_log(
"visiting keyed int: 2;"
"visiting keyed int: 0;");
}
check_log(
"destructing int;"
"destructing int;");
}

TEST_CASE("low-level get_keyed_data", "[data_graph]")
{
clear_log();
{
data_graph graph;
auto make_controller = [](int i) {
return [=](context ctx) {
int_object* x;
if (get_keyed_data(ctx, make_id(i), &x))
{
x->n = i;
the_log << "initializing keyed int: " << i << ";";
}
else
{
REQUIRE(x->n == i);
the_log << "visiting keyed int: " << i << ";";
}
};
};
do_traversal(graph, make_controller(1));
check_log("initializing keyed int: 1;");
do_traversal(graph, make_controller(1));
check_log("visiting keyed int: 1;");
do_traversal(graph, make_controller(2));
check_log("initializing keyed int: 2;");
do_traversal(graph, make_controller(2));
check_log("visiting keyed int: 2;");
}
check_log("destructing int;");
}

namespace {

struct verbose_int_object
Expand Down
19 changes: 0 additions & 19 deletions unit_tests/flow/testing.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,25 +98,6 @@ do_cached_int(Context& ctx, int n)
}
}

template<class Context>
void
do_keyed_int(Context& ctx, int n)
{
keyed_data_signal<int_object> obj;
if (get_keyed_data(ctx, make_id(n), &obj))
{
REQUIRE(!obj.has_value());
write_signal(obj, int_object(n * 2));
the_log << "initializing keyed int: " << n << ";";
}
else
{
REQUIRE(read_signal(obj).n == n * 2);
REQUIRE(obj.value_id() == make_id(n));
the_log << "visiting keyed int: " << n << ";";
}
}

template<class Controller>
void
do_traversal(
Expand Down

0 comments on commit 62f1905

Please sign in to comment.