Skip to content

Commit

Permalink
Add context content IDs.
Browse files Browse the repository at this point in the history
  • Loading branch information
tmadden committed Jun 16, 2020
1 parent c9bf179 commit eab9b5f
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 0 deletions.
42 changes: 42 additions & 0 deletions src/alia/context/interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,53 @@ make_context(
data_traversal& data,
timing_subsystem& timing)
{
storage->content_id = &unit_id;
return make_context(impl::make_empty_structural_collection(storage))
.add<system_tag>(sys)
.add<event_traversal_tag>(event)
.add<timing_tag>(timing)
.add<data_traversal_tag>(data);
}

struct scoped_context_content_id_data
{
captured_id id_from_above;
captured_id id_from_here;
unsigned id_to_present = 0;
};

void
scoped_context_content_id::begin(context ctx, id_interface const& id)
{
ctx_.reset(ctx);
parent_id_ = ctx.contents_.storage->content_id;

auto& data = get_cached_data<scoped_context_content_id_data>(ctx);

if (!data.id_from_above.matches(*parent_id_))
{
++data.id_to_present;
data.id_from_above.capture(*parent_id_);
}

if (!data.id_from_here.matches(id))
{
++data.id_to_present;
data.id_from_here.capture(id);
}

this_id_ = make_id(data.id_to_present);
ctx.contents_.storage->content_id = &this_id_;
}

void
scoped_context_content_id::end()
{
if (ctx_)
{
ctx_->contents_.storage->content_id = parent_id_;
ctx_.reset();
}
}

} // namespace alia
39 changes: 39 additions & 0 deletions src/alia/context/interface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ struct context_storage
impl::generic_tagged_storage<impl::any_ref> generic;

ALIA_IMPLEMENT_STORAGE_OBJECT_ACCESSORS(context_storage)

// an ID to track changes in the context contents
id_interface const* content_id = nullptr;
};

ALIA_ADD_DIRECT_TAGGED_DATA_ACCESS(context_storage, system_tag, sys)
Expand Down Expand Up @@ -196,6 +199,14 @@ get_data_traversal(Context ctx)
return ctx.template get<data_traversal_tag>();
}

inline id_interface const&
get_content_id(context ctx)
{
return *ctx.contents_.storage->content_id;
}

// optional_context is basically just std::optional for contexts.
// (alia supports C++14, which is why we don't use std::optional directly.)
template<class Context>
struct optional_context
{
Expand Down Expand Up @@ -252,6 +263,34 @@ struct optional_context
Context ctx_;
};

// scoped_context_content_id is used to fold another ID into the overall ID for
// a context's content.
struct scoped_context_content_id
{
scoped_context_content_id()
{
}
scoped_context_content_id(context ctx, id_interface const& id)
{
begin(ctx, id);
}
~scoped_context_content_id()
{
end();
}

void
begin(context ctx, id_interface const& id);

void
end();

private:
optional_context<dataless_context> ctx_;
simple_id<unsigned> this_id_;
id_interface const* parent_id_;
};

} // namespace alia

#endif
47 changes: 47 additions & 0 deletions unit_tests/context/interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

#include <testing.hpp>

#include "traversal.hpp"

using namespace alia;

struct other_traversal
Expand Down Expand Up @@ -54,6 +56,8 @@ TEST_CASE("context", "[context][interface]")

context ctx = make_context(&storage, sys, event, data, timing);

REQUIRE(get_content_id(ctx) == unit_id);

REQUIRE(ctx.has<data_traversal_tag>());
REQUIRE(&ctx.get<data_traversal_tag>() == &data);
dataless_context dataless = ctx.remove<data_traversal_tag>();
Expand Down Expand Up @@ -99,3 +103,46 @@ TEST_CASE("optional_context", "[context][interface]")
optional.reset();
REQUIRE(!optional);
}

TEST_CASE("make_context", "[context][interface]")
{
alia::system sys;
initialize_system(sys, [](context) {});

captured_id outer_id, inner_id;

auto make_controller = [&](int outer, int inner) {
return [&, outer, inner](context ctx) {
REQUIRE(get_content_id(ctx) == unit_id);
scoped_context_content_id outer_content(ctx, make_id(outer));
outer_id.capture(get_content_id(ctx));
{
scoped_context_content_id inner_content(ctx, make_id(inner));
inner_id.capture(get_content_id(ctx));
}
};
};

do_traversal(sys, make_controller(4, 1));
captured_id last_outer = outer_id;
captured_id last_inner = inner_id;

do_traversal(sys, make_controller(4, 2));
REQUIRE(last_outer == outer_id);
REQUIRE(last_inner != inner_id);
last_inner = inner_id;

do_traversal(sys, make_controller(4, 2));
REQUIRE(last_outer == outer_id);
REQUIRE(last_inner == inner_id);

do_traversal(sys, make_controller(7, 2));
REQUIRE(last_outer != outer_id);
last_outer = outer_id;
REQUIRE(last_inner != inner_id);
last_inner = inner_id;

do_traversal(sys, make_controller(7, 2));
REQUIRE(last_outer == outer_id);
REQUIRE(last_inner == inner_id);
}

0 comments on commit eab9b5f

Please sign in to comment.