Skip to content

Commit

Permalink
Add fallback signal capability.
Browse files Browse the repository at this point in the history
  • Loading branch information
tmadden committed Jul 16, 2018
1 parent ae50994 commit 68a4f4d
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 0 deletions.
57 changes: 57 additions & 0 deletions src/alia/signals/adaptors.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,63 @@ is_writable(Wrapped const& wrapped)
return writability_signal<Wrapped>(wrapped);
}

// add_fallback(primary, fallback), where :primary and :fallback are both
// signals, yields another signal whose value is that of :primary if it's ready
// and that of :fallback otherwise.
// All writes go directly to :primary.
template<class Primary, class Fallback>
struct fallback_signal
: signal<typename Primary::value_type, typename Primary::direction_tag>
{
fallback_signal()
{
}
fallback_signal(Primary primary, Fallback fallback)
: primary_(primary), fallback_(fallback)
{
}
bool
is_readable() const
{
return primary_.is_readable() || fallback_.is_readable();
}
typename Primary::value_type const&
read() const
{
return primary_.is_readable() ? primary_.read() : fallback_.read();
}
id_interface const&
value_id() const
{
id_ = combine_ids(
make_id(primary_.is_readable()),
primary_.is_readable() ? ref(primary_.value_id())
: ref(fallback_.value_id()));
return id_;
}
bool
is_writable() const
{
return primary_.is_writable();
}
void
write(typename Primary::value_type const& value) const
{
primary_.write(value);
}

private:
mutable id_pair<simple_id<bool>, id_ref> id_;
Primary primary_;
Fallback fallback_;
};
template<class Primary, class Fallback>
fallback_signal<Primary, Fallback>
add_fallback(Primary const& primary, Fallback const& fallback)
{
return fallback_signal<Primary, Fallback>(primary, fallback);
}

} // namespace alia

#endif
88 changes: 88 additions & 0 deletions unit_tests/signals/adaptors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,91 @@ TEST_CASE("is_writable", "[signals]")
REQUIRE(read_signal(s) == true);
}
}

TEST_CASE("add_fallback", "[signals]")
{
using namespace alia;

int p = 1;
int f = 0;
auto make_fallback = [&](bool primary_readable,
bool primary_writable,
bool fallback_readable) {
return add_fallback(
lambda_bidirectional(
[=]() { return primary_readable; },
[=]() { return p; },
[=]() { return primary_writable; },
[&p](int x) { p = x; }),
lambda_bidirectional(
[=]() { return fallback_readable; },
[=]() { return f; },
always_writable,
[&f](int x) { f = x; }));
};

{
typedef decltype(make_fallback(true, true, true)) signal_t;
REQUIRE(signal_can_read<signal_t>::value);
REQUIRE(signal_can_write<signal_t>::value);
}

{
typedef decltype(add_fallback(value(0), value(1))) signal_t;
REQUIRE(signal_can_read<signal_t>::value);
REQUIRE(!signal_can_write<signal_t>::value);
}

{
p = 1;
auto s = make_fallback(true, true, true);
REQUIRE(signal_is_readable(s));
REQUIRE(read_signal(s) == 1);
REQUIRE(signal_is_writable(s));
write_signal(s, 2);
REQUIRE(p == 2);
REQUIRE(f == 0);
}

{
p = 1;
auto s = make_fallback(false, true, true);
REQUIRE(signal_is_readable(s));
REQUIRE(read_signal(s) == 0);
REQUIRE(signal_is_writable(s));
write_signal(s, 2);
REQUIRE(p == 2);
REQUIRE(f == 0);
}

{
p = 1;
auto s = make_fallback(false, true, false);
REQUIRE(!signal_is_readable(s));
REQUIRE(signal_is_writable(s));
write_signal(s, 2);
REQUIRE(p == 2);
REQUIRE(f == 0);
}

{
p = 1;
auto s = make_fallback(true, false, false);
REQUIRE(signal_is_readable(s));
REQUIRE(read_signal(s) == 1);
REQUIRE(!signal_is_writable(s));
}

{
// Check that the overall signal produces a different value ID when
// using the primary vs the fallback, even when the two component
// signals have the same value ID.
p = 0;
auto s = make_fallback(true, false, false);
auto t = make_fallback(false, false, true);
REQUIRE(signal_is_readable(s));
REQUIRE(signal_is_readable(t));
REQUIRE(read_signal(s) == read_signal(t));
REQUIRE(s.value_id() != t.value_id());
}
}

0 comments on commit 68a4f4d

Please sign in to comment.