Skip to content

Commit

Permalink
Make excpetions optional depending on build-time feature checks.
Browse files Browse the repository at this point in the history
Replaces all try/catch/throw keyword usage with a set of macros that are
appropriately defined in config.hpp based on the status of the
`cxx_exceptions` compiler feature.

Reported in issue arximboldi#160.
  • Loading branch information
chuim committed Sep 29, 2020
1 parent 2076aff commit 9172b7a
Show file tree
Hide file tree
Showing 16 changed files with 348 additions and 308 deletions.
22 changes: 22 additions & 0 deletions immer/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,28 @@
#endif
#endif

#ifdef __has_feature
#if !__has_feature(cxx_exceptions)
#define IMMER_NO_EXCEPTIONS
#endif
#endif

#ifdef IMMER_NO_EXCEPTIONS
#define IMMER_TRY if (true)
#define IMMER_CATCH(expr) else
#define IMMER_THROW(expr) \
do { \
assert(! #expr); \
std::terminate(); \
} while(false)
#define IMMER_RETHROW
#else
#define IMMER_TRY try
#define IMMER_CATCH(expr) catch (expr)
#define IMMER_THROW(expr) throw expr
#define IMMER_RETHROW throw
#endif

#ifndef IMMER_NODISCARD
#define IMMER_NODISCARD
#endif
Expand Down
23 changes: 13 additions & 10 deletions immer/detail/arrays/no_capacity.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
#include <immer/algorithm.hpp>
#include <immer/detail/arrays/node.hpp>

#include <cassert>
#include <exception>

namespace immer {
namespace detail {
namespace arrays {
Expand Down Expand Up @@ -142,7 +145,7 @@ struct no_capacity
const T& get_check(std::size_t index) const
{
if (index >= size)
throw std::out_of_range{"out of range"};
IMMER_THROW(std::out_of_range{"out of range"});
return data()[index];
}

Expand All @@ -156,38 +159,38 @@ struct no_capacity
no_capacity push_back(T value) const
{
auto p = node_t::copy_n(size + 1, ptr, size);
try {
IMMER_TRY {
new (p->data() + size) T{std::move(value)};
return {p, size + 1};
} catch (...) {
} IMMER_CATCH (...) {
node_t::delete_n(p, size, size + 1);
throw;
IMMER_RETHROW;
}
}

no_capacity assoc(std::size_t idx, T value) const
{
auto p = node_t::copy_n(size, ptr, size);
try {
IMMER_TRY {
p->data()[idx] = std::move(value);
return {p, size};
} catch (...) {
} IMMER_CATCH (...) {
node_t::delete_n(p, size, size);
throw;
IMMER_RETHROW;
}
}

template <typename Fn>
no_capacity update(std::size_t idx, Fn&& op) const
{
auto p = node_t::copy_n(size, ptr, size);
try {
IMMER_TRY {
auto& elem = p->data()[idx];
elem = std::forward<Fn>(op)(std::move(elem));
return {p, size};
} catch (...) {
} IMMER_CATCH (...) {
node_t::delete_n(p, size, size);
throw;
IMMER_RETHROW;
}
}

Expand Down
12 changes: 6 additions & 6 deletions immer/detail/arrays/node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,12 @@ struct node
static node_t* fill_n(size_t n, T v)
{
auto p = make_n(n);
try {
IMMER_TRY {
std::uninitialized_fill_n(p->data(), n, v);
return p;
} catch (...) {
} IMMER_CATCH (...) {
heap::deallocate(sizeof_n(n), p);
throw;
IMMER_RETHROW;
}
}

Expand All @@ -94,12 +94,12 @@ struct node
static node_t* copy_n(size_t n, Iter first, Sent last)
{
auto p = make_n(n);
try {
IMMER_TRY {
uninitialized_copy(first, last, p->data());
return p;
} catch (...) {
} IMMER_CATCH (...) {
heap::deallocate(sizeof_n(n), p);
throw;
IMMER_RETHROW;
}
}

Expand Down
41 changes: 22 additions & 19 deletions immer/detail/arrays/with_capacity.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@

#include <immer/detail/arrays/no_capacity.hpp>

#include <cassert>
#include <exception>

namespace immer {
namespace detail {
namespace arrays {
Expand Down Expand Up @@ -159,7 +162,7 @@ struct with_capacity
const T& get_check(std::size_t index) const
{
if (index >= size)
throw std::out_of_range{"out of range"};
IMMER_THROW(std::out_of_range{"out of range"});
return data()[index];
}

Expand Down Expand Up @@ -190,12 +193,12 @@ struct with_capacity
{
auto cap = recommend_up(size + 1, capacity);
auto p = node_t::copy_n(cap, ptr, size);
try {
IMMER_TRY {
new (p->data() + size) T{std::move(value)};
return {p, size + 1, cap};
} catch (...) {
} IMMER_CATCH (...) {
node_t::delete_n(p, size, cap);
throw;
IMMER_RETHROW;
}
}

Expand All @@ -207,25 +210,25 @@ struct with_capacity
} else {
auto cap = recommend_up(size + 1, capacity);
auto p = node_t::copy_e(e, cap, ptr, size);
try {
IMMER_TRY {
new (p->data() + size) T{std::move(value)};
*this = {p, size + 1, cap};
} catch (...) {
} IMMER_CATCH (...) {
node_t::delete_n(p, size, cap);
throw;
IMMER_RETHROW;
}
}
}

with_capacity assoc(std::size_t idx, T value) const
{
auto p = node_t::copy_n(capacity, ptr, size);
try {
IMMER_TRY {
p->data()[idx] = std::move(value);
return {p, size, capacity};
} catch (...) {
} IMMER_CATCH (...) {
node_t::delete_n(p, size, capacity);
throw;
IMMER_RETHROW;
}
}

Expand All @@ -235,12 +238,12 @@ struct with_capacity
data()[idx] = std::move(value);
} else {
auto p = node_t::copy_n(capacity, ptr, size);
try {
IMMER_TRY {
p->data()[idx] = std::move(value);
*this = {p, size, capacity};
} catch (...) {
} IMMER_CATCH (...) {
node_t::delete_n(p, size, capacity);
throw;
IMMER_RETHROW;
}
}
}
Expand All @@ -249,13 +252,13 @@ struct with_capacity
with_capacity update(std::size_t idx, Fn&& op) const
{
auto p = node_t::copy_n(capacity, ptr, size);
try {
IMMER_TRY {
auto& elem = p->data()[idx];
elem = std::forward<Fn>(op)(std::move(elem));
return {p, size, capacity};
} catch (...) {
} IMMER_CATCH (...) {
node_t::delete_n(p, size, capacity);
throw;
IMMER_RETHROW;
}
}

Expand All @@ -267,13 +270,13 @@ struct with_capacity
elem = std::forward<Fn>(op)(std::move(elem));
} else {
auto p = node_t::copy_e(e, capacity, ptr, size);
try {
IMMER_TRY {
auto& elem = p->data()[idx];
elem = std::forward<Fn>(op)(std::move(elem));
*this = {p, size, capacity};
} catch (...) {
} IMMER_CATCH (...) {
node_t::delete_n(p, size, capacity);
throw;
IMMER_RETHROW;
}
}
}
Expand Down
30 changes: 15 additions & 15 deletions immer/detail/hamts/champ.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,13 +167,13 @@ struct champ
assert(node->children()[offset]);
auto result = do_add(
node->children()[offset], std::move(v), hash, shift + B);
try {
IMMER_TRY {
result.first =
node_t::copy_inner_replace(node, offset, result.first);
return result;
} catch (...) {
} IMMER_CATCH (...) {
node_t::delete_deep_shift(result.first, shift + B);
throw;
IMMER_RETHROW;
}
} else if (node->datamap() & bit) {
auto offset = node->data_count(bit);
Expand All @@ -185,13 +185,13 @@ struct champ
else {
auto child = node_t::make_merged(
shift + B, std::move(v), hash, *val, Hash{}(*val));
try {
IMMER_TRY {
return {node_t::copy_inner_replace_merged(
node, bit, offset, child),
true};
} catch (...) {
} IMMER_CATCH (...) {
node_t::delete_deep_shift(child, shift + B);
throw;
IMMER_RETHROW;
}
}
} else {
Expand Down Expand Up @@ -246,13 +246,13 @@ struct champ
std::forward<Fn>(fn),
hash,
shift + B);
try {
IMMER_TRY {
result.first =
node_t::copy_inner_replace(node, offset, result.first);
return result;
} catch (...) {
} IMMER_CATCH (...) {
node_t::delete_deep_shift(result.first, shift + B);
throw;
IMMER_RETHROW;
}
} else if (node->datamap() & bit) {
auto offset = node->data_count(bit);
Expand All @@ -273,13 +273,13 @@ struct champ
hash,
*val,
Hash{}(*val));
try {
IMMER_TRY {
return {node_t::copy_inner_replace_merged(
node, bit, offset, child),
true};
} catch (...) {
} IMMER_CATCH (...) {
node_t::delete_deep_shift(child, shift + B);
throw;
IMMER_RETHROW;
}
}
} else {
Expand Down Expand Up @@ -372,12 +372,12 @@ struct champ
: node_t::copy_inner_replace_inline(
node, bit, offset, *result.data.singleton);
case sub_result::tree:
try {
IMMER_TRY {
return node_t::copy_inner_replace(
node, offset, result.data.tree);
} catch (...) {
} IMMER_CATCH (...) {
node_t::delete_deep_shift(result.data.tree, shift + B);
throw;
IMMER_RETHROW;
}
}
} else if (node->datamap() & bit) {
Expand Down
Loading

0 comments on commit 9172b7a

Please sign in to comment.