Skip to content

Commit

Permalink
Improve try/catch.
Browse files Browse the repository at this point in the history
  • Loading branch information
tmadden committed Sep 14, 2020
1 parent 0235763 commit be3eaa8
Show file tree
Hide file tree
Showing 5 changed files with 337 additions and 161 deletions.
57 changes: 57 additions & 0 deletions src/alia/flow/try_catch.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#include <alia/flow/try_catch.hpp>

#include <alia/system/internals.hpp>

namespace alia {

try_block::try_block(context ctx) : ctx_(ctx)
{
get_cached_data(ctx, &data_);
on_refresh(ctx, [&](auto ctx) {
auto refresh_counter = get<system_tag>(ctx).refresh_counter;
if (data_->last_refresh != refresh_counter)
{
data_->exception = nullptr;
data_->last_refresh = refresh_counter;
}
else if (data_->exception && data_->uncaught)
{
std::rethrow_exception(data_->exception);
}
});
uncaught_ = data_->exception ? true : false;
}

void
try_block::operator<<(function_view<void()> body)
{
ALIA_IF_(ctx_, !data_->exception)
{
try
{
body();
}
catch (alia::traversal_abortion&)
{
throw;
}
catch (...)
{
data_->exception = std::current_exception();
data_->uncaught = false;
mark_dirty_component(ctx_);
}
}
ALIA_END
}

try_block::~try_block()
{
if (uncaught_ && !std::uncaught_exception())
{
mark_dirty_component(ctx_);
data_->uncaught = true;
}
}

} // namespace alia
38 changes: 5 additions & 33 deletions src/alia/flow/try_catch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,45 +73,17 @@ struct try_block_data
{
counter_type last_refresh = 0;
std::exception_ptr exception;
bool uncaught = false;
};

struct try_block
{
try_block(alia::context ctx) : ctx_(ctx)
{
get_cached_data(ctx, &data_);
on_refresh(ctx, [&](auto ctx) {
auto refresh_counter = get<system_tag>(ctx).refresh_counter;
if (data_->last_refresh != refresh_counter)
{
data_->exception = nullptr;
data_->last_refresh = refresh_counter;
}
});
uncaught_ = data_->exception ? true : false;
}
try_block(context ctx);

void
operator<<(function_view<void()> body)
{
ALIA_IF_(ctx_, !data_->exception)
{
try
{
body();
}
catch (alia::traversal_abortion&)
{
throw;
}
catch (...)
{
data_->exception = std::current_exception();
mark_dirty_component(ctx_);
}
}
ALIA_END
}
operator<<(function_view<void()> body);

~try_block();

context ctx_;
try_block_data* data_;
Expand Down
128 changes: 0 additions & 128 deletions unit_tests/flow/object_trees.cpp
Original file line number Diff line number Diff line change
@@ -1,135 +1,7 @@
#include <alia/flow/object_trees.hpp>

#include <alia/flow/events.hpp>

#include <flow/testing.hpp>

namespace {

struct test_object
{
void
remove()
{
the_log << "removing " << name << "; ";

auto& siblings = this->parent->children;
siblings.erase(
std::remove(siblings.begin(), siblings.end(), this),
siblings.end());
}

void
relocate(test_object& new_parent, test_object* after, test_object* before)
{
the_log << "relocating " << name << " into " << new_parent.name;
if (after)
the_log << " after " << after->name;
the_log << "; ";

if (this->parent)
{
auto& siblings = this->parent->children;
siblings.erase(
std::remove(siblings.begin(), siblings.end(), this),
siblings.end());
}

this->parent = &new_parent;

auto& siblings = new_parent.children;
std::vector<test_object*>::iterator insertion_point;
if (after)
{
insertion_point = siblings.insert(
std::find(siblings.begin(), siblings.end(), after) + 1, this);
}
else
{
insertion_point = siblings.insert(siblings.begin(), this);
}

++insertion_point;
if (before)
{
REQUIRE(*insertion_point == before);
}
else
{
REQUIRE(insertion_point == siblings.end());
}
}

void
stream(std::ostream& out)
{
out << name << "(";
for (test_object* child : children)
{
child->stream(out);
out << ";";
}
out << ")";
}

std::string
to_string()
{
std::stringstream out;
this->stream(out);
return out.str();
}

std::string name;
test_object* parent = nullptr;
std::vector<test_object*> children;
};

ALIA_DEFINE_TAGGED_TYPE(tree_traversal_tag, tree_traversal<test_object>&)

typedef alia::extend_context_type_t<alia::context, tree_traversal_tag>
test_context;

void
do_object(test_context ctx, std::string name)
{
tree_node<test_object>* node;
if (get_cached_data(ctx, &node))
node->object.name = name;
if (is_refresh_event(ctx))
refresh_tree_node(get<tree_traversal_tag>(ctx), *node);
}

template<class Contents>
void
do_container(test_context ctx, std::string name, Contents contents)
{
scoped_tree_node<test_object> scoped;
tree_node<test_object>* node;
if (get_cached_data(ctx, &node))
node->object.name = name;
if (is_refresh_event(ctx))
scoped.begin(get<tree_traversal_tag>(ctx), *node);
contents(ctx);
}

template<class Contents>
void
do_piecewise_container(test_context ctx, std::string name, Contents contents)
{
tree_node<test_object>* node;
if (get_cached_data(ctx, &node))
node->object.name = name;
if (is_refresh_event(ctx))
refresh_tree_node(get<tree_traversal_tag>(ctx), *node);
scoped_tree_children<test_object> scoped;
if (is_refresh_event(ctx))
scoped.begin(get<tree_traversal_tag>(ctx), *node);
contents(ctx);
}

} // namespace

TEST_CASE("simple object tree", "[flow][object_trees]")
{
clear_log();
Expand Down
127 changes: 127 additions & 0 deletions unit_tests/flow/testing.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <alia/context/interface.hpp>
#include <alia/flow/data_graph.hpp>
#include <alia/flow/events.hpp>
#include <alia/flow/object_trees.hpp>
#include <alia/system/internals.hpp>

#include <sstream>
Expand All @@ -30,6 +31,8 @@ clear_log();
void
check_log(std::string const& expected_contents);

namespace {

struct int_object
{
int_object() : n(-1)
Expand Down Expand Up @@ -138,4 +141,128 @@ do_traversal(
controller(ctx);
}

struct test_object
{
void
remove()
{
the_log << "removing " << name << "; ";

auto& siblings = this->parent->children;
siblings.erase(
std::remove(siblings.begin(), siblings.end(), this),
siblings.end());
}

void
relocate(test_object& new_parent, test_object* after, test_object* before)
{
the_log << "relocating " << name << " into " << new_parent.name;
if (after)
the_log << " after " << after->name;
the_log << "; ";

if (this->parent)
{
auto& siblings = this->parent->children;
siblings.erase(
std::remove(siblings.begin(), siblings.end(), this),
siblings.end());
}

this->parent = &new_parent;

auto& siblings = new_parent.children;
std::vector<test_object*>::iterator insertion_point;
if (after)
{
insertion_point = siblings.insert(
std::find(siblings.begin(), siblings.end(), after) + 1, this);
}
else
{
insertion_point = siblings.insert(siblings.begin(), this);
}

++insertion_point;
if (before)
{
REQUIRE(*insertion_point == before);
}
else
{
REQUIRE(insertion_point == siblings.end());
}
}

void
stream(std::ostream& out)
{
out << name << "(";
for (test_object* child : children)
{
child->stream(out);
out << ";";
}
out << ")";
}

std::string
to_string()
{
std::stringstream out;
this->stream(out);
return out.str();
}

std::string name;
test_object* parent = nullptr;
std::vector<test_object*> children;
};

ALIA_DEFINE_TAGGED_TYPE(tree_traversal_tag, tree_traversal<test_object>&)

typedef alia::extend_context_type_t<alia::context, tree_traversal_tag>
test_context;

void
do_object(test_context ctx, std::string name)
{
tree_node<test_object>* node;
if (get_cached_data(ctx, &node))
node->object.name = name;
if (is_refresh_event(ctx))
refresh_tree_node(get<tree_traversal_tag>(ctx), *node);
}

template<class Contents>
void
do_container(test_context ctx, std::string name, Contents contents)
{
scoped_tree_node<test_object> scoped;
tree_node<test_object>* node;
if (get_cached_data(ctx, &node))
node->object.name = name;
if (is_refresh_event(ctx))
scoped.begin(get<tree_traversal_tag>(ctx), *node);
contents(ctx);
}

template<class Contents>
void
do_piecewise_container(test_context ctx, std::string name, Contents contents)
{
tree_node<test_object>* node;
if (get_cached_data(ctx, &node))
node->object.name = name;
if (is_refresh_event(ctx))
refresh_tree_node(get<tree_traversal_tag>(ctx), *node);
scoped_tree_children<test_object> scoped;
if (is_refresh_event(ctx))
scoped.begin(get<tree_traversal_tag>(ctx), *node);
contents(ctx);
}

} // namespace

#endif

0 comments on commit be3eaa8

Please sign in to comment.