diff options
Diffstat (limited to 'third_party/immer/test/dada.hpp')
-rw-r--r-- | third_party/immer/test/dada.hpp | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/third_party/immer/test/dada.hpp b/third_party/immer/test/dada.hpp new file mode 100644 index 000000000000..1465bf7bf52d --- /dev/null +++ b/third_party/immer/test/dada.hpp @@ -0,0 +1,243 @@ +// +// immer: immutable data structures for C++ +// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente +// +// This software is distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt +// + +#pragma once + +#include <array> +#include <cstddef> +#include <utility> + +#include <immer/detail/hamts/bits.hpp> +#include <immer/detail/rbts/bits.hpp> + +namespace { + +template <typename Iterator> +struct rotator +{ + using value_type = typename std::iterator_traits<Iterator>::value_type; + + Iterator first; + Iterator last; + Iterator curr; + + void init(Iterator f, Iterator l) + { + first = f; + last = l; + curr = f; + } + + value_type next() + { + if (curr == last) + curr = first; + return *curr++; + } +}; + +template <typename Range> +struct range_rotator : rotator<typename Range::iterator> +{ + using base_t = rotator<typename Range::iterator>; + + Range range; + + range_rotator(Range r) + : range{std::move(r)} + { + base_t::init(range.begin(), range.end()); + } +}; + +template <typename Range> +auto make_rotator(Range r) -> range_rotator<Range> +{ + return {r}; +} + +inline auto magic_rotator() +{ + return make_rotator(std::array<unsigned, 15>{ + {7, 11, 2, 3, 5, 7, 11, 13, 17, 19, 23, 5, 29, 31, 37}}); +} + +struct dada_error +{}; + +struct dadaism; +static dadaism* g_dadaism = nullptr; + +struct dadaism +{ + using rotator_t = decltype(magic_rotator()); + + rotator_t magic = magic_rotator(); + + unsigned step = magic.next(); + unsigned count = 0; + unsigned happenings = 0; + unsigned last = 0; + bool toggle = false; + + struct scope + { + bool moved = false; + dadaism* save_ = g_dadaism; + scope(scope&& s) + { + save_ = s.save_; + s.moved = true; + } + scope(dadaism* self) { g_dadaism = self; } + ~scope() + { + if (!moved) + g_dadaism = save_; + } + }; + + static scope disable() { return {nullptr}; } + + scope next() + { + toggle = last == happenings; + last = happenings; + step = toggle ? step : magic.next(); + return {this}; + } + + void dada() + { + if (toggle && ++count % step == 0) { + ++happenings; + throw dada_error{}; + } + } +}; + +inline void dada() +{ + if (g_dadaism) + g_dadaism->dada(); +} + +inline bool soft_dada() +{ + try { + dada(); + return false; + } catch (dada_error) { + return true; + } +} + +template <typename Heap> +struct dadaist_heap : Heap +{ + template <typename... Tags> + static auto allocate(std::size_t s, Tags... tags) + { + dada(); + return Heap::allocate(s, tags...); + } +}; + +template <typename MP> +struct dadaist_memory_policy : MP +{ + struct heap + { + using type = dadaist_heap<typename MP::heap::type>; + + template <std::size_t Size> + struct optimized + { + using base = typename MP::heap::template optimized<Size>::type; + using type = dadaist_heap<base>; + }; + }; +}; + +struct tristan_tzara +{ + tristan_tzara() { dada(); } + tristan_tzara(const tristan_tzara&) { dada(); } + tristan_tzara(tristan_tzara&&) { dada(); } + tristan_tzara& operator=(const tristan_tzara&) + { + dada(); + return *this; + } + tristan_tzara& operator=(tristan_tzara&&) + { + dada(); + return *this; + } +}; + +template <typename T> +struct dadaist : tristan_tzara +{ + T value; + + dadaist() + : value{} + {} + dadaist(T v) + : value{std::move(v)} + {} + operator T() const { return value; } +}; + +template <typename T> +struct dadaist_wrapper; + +using rbits_t = immer::detail::rbts::bits_t; +using hbits_t = immer::detail::rbts::bits_t; + +template <template <class, class, rbits_t, rbits_t> class V, + typename T, + typename MP, + rbits_t B, + rbits_t BL> +struct dadaist_wrapper<V<T, MP, B, BL>> +{ + using type = V<dadaist<T>, dadaist_memory_policy<MP>, B, BL>; +}; + +template <template <class, class> class V, typename T, typename MP> +struct dadaist_wrapper<V<T, MP>> +{ + using type = V<dadaist<T>, dadaist_memory_policy<MP>>; +}; + +template <template <class, class, class, class, hbits_t> class V, + typename T, + typename E, + typename H, + typename MP, + hbits_t B> +struct dadaist_wrapper<V<T, H, E, MP, B>> +{ + using type = V<dadaist<T>, H, E, dadaist_memory_policy<MP>, B>; +}; + +template <template <class, class, class, class, class, hbits_t> class V, + typename K, + typename T, + typename E, + typename H, + typename MP, + hbits_t B> +struct dadaist_wrapper<V<K, T, H, E, MP, B>> +{ + using type = V<K, dadaist<T>, H, E, dadaist_memory_policy<MP>, B>; +}; + +} // anonymous namespace |