destructors are not possible currently. use a gc if you need them.

thread
Brett 2024-08-11 20:21:53 -04:00
parent e9954f5065
commit 4735c6c21b
5 changed files with 70 additions and 41 deletions

View File

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.25)
project(blt-gp VERSION 0.0.135)
project(blt-gp VERSION 0.0.136)
include(CTest)

View File

@ -101,8 +101,17 @@ namespace blt::gp
allocator.from<detail::remove_cv_ref<Args>>(getByteOffset<indices>())...);
}
template<typename context = void, typename... NoCtxArgs>
void call_destructors_without_first(stack_allocator& read_allocator)
{
if constexpr (sizeof...(NoCtxArgs) > 0)
{
read_allocator.call_destructors<detail::remove_cv_ref<NoCtxArgs>...>();
}
}
template<typename Func, typename... ExtraArgs>
Return operator()(Func&& func, stack_allocator& read_allocator, ExtraArgs&& ... args)
Return operator()(bool, Func&& func, stack_allocator& read_allocator, ExtraArgs&& ... args)
{
constexpr auto seq = std::make_integer_sequence<blt::u64, sizeof...(Args)>();
#if BLT_DEBUG_LEVEL > 0
@ -110,7 +119,10 @@ namespace blt::gp
{
#endif
Return ret = exec_sequence_to_indices(std::forward<Func>(func), read_allocator, seq, std::forward<ExtraArgs>(args)...);
read_allocator.call_destructors<detail::remove_cv_ref<Args>...>();
/*if (has_context)
call_destructors_without_first<Args...>(read_allocator);
else
read_allocator.call_destructors<detail::remove_cv_ref<Args>...>();*/
read_allocator.pop_bytes((stack_allocator::aligned_size<detail::remove_cv_ref<Args>>() + ...));
return ret;
#if BLT_DEBUG_LEVEL > 0
@ -153,7 +165,7 @@ namespace blt::gp
return func();
} else
{
return call_with<Return, Args...>()(func, read_allocator);
return call_with<Return, Args...>()(false, func, read_allocator);
}
}
@ -170,7 +182,7 @@ namespace blt::gp
return func(ctx_ref);
} else
{
return call_without_first<Return, Args...>()(func, read_allocator, ctx_ref);
return call_without_first<Return, Args...>()(true, func, read_allocator, ctx_ref);
}
}
@ -214,16 +226,24 @@ namespace blt::gp
};
template<typename Lambda>
operation_t(Lambda) -> operation_t<Lambda, decltype(&Lambda::operator())>;
operation_t(Lambda)
->
operation_t<Lambda, decltype(&Lambda::operator())>;
template<typename Return, typename... Args>
operation_t(Return(*)(Args...)) -> operation_t<Return(*)(Args...), Return(Args...)>;
operation_t(Return(*)
(Args...)) ->
operation_t<Return(*)(Args...), Return(Args...)>;
template<typename Lambda>
operation_t(Lambda, std::optional<std::string_view>) -> operation_t<Lambda, decltype(&Lambda::operator())>;
operation_t(Lambda, std::optional<std::string_view>
) ->
operation_t<Lambda, decltype(&Lambda::operator())>;
template<typename Return, typename... Args>
operation_t(Return(*)(Args...), std::optional<std::string_view>) -> operation_t<Return(*)(Args...), Return(Args...)>;
operation_t(Return(*)
(Args...), std::optional<std::string_view>) ->
operation_t<Return(*)(Args...), Return(Args...)>;
}
#endif //BLT_GP_OPERATIONS_H

View File

@ -205,14 +205,15 @@ namespace blt::gp
* @param value universal reference to the object to push
*/
template<typename T>
void push(T&& value)
void push(const T& value)
{
using NO_REF_T = std::remove_cv_t<std::remove_reference_t<T>>;
static_assert(std::is_trivially_copyable_v<NO_REF_T> && "Type must be bitwise copyable!");
static_assert(alignof(NO_REF_T) <= MAX_ALIGNMENT && "Type must not be greater than the max alignment!");
auto ptr = allocate_bytes<NO_REF_T>();
head->metadata.offset = static_cast<blt::u8*>(ptr) + aligned_size<NO_REF_T>();
new(ptr) NO_REF_T(std::forward<T>(value));
//new(ptr) NO_REF_T(std::forward<T>(value));
std::memcpy(ptr, &value, sizeof(NO_REF_T));
}
template<typename T>
@ -233,7 +234,7 @@ namespace blt::gp
NO_REF_T t = *reinterpret_cast<NO_REF_T*>(head->metadata.offset - TYPE_SIZE);
// call destructor
if constexpr (detail::has_func_drop_v<T>)
reinterpret_cast<NO_REF_T*>(head->metadata.offset - TYPE_SIZE)->~NO_REF_T();
call_drop<NO_REF_T>(0);
// move offset back
head->metadata.offset -= TYPE_SIZE;
// moving back allows us to allocate with other data, if there is room.
@ -348,9 +349,9 @@ namespace blt::gp
template<typename... Args>
void call_destructors()
{
blt::size_t offset = 0;
((call_drop<Args>(offset), offset += stack_allocator::aligned_size<NO_REF_T<Args>>()), ...);
blt::size_t offset = (stack_allocator::aligned_size<NO_REF_T<Args>>() + ...) -
stack_allocator::aligned_size<NO_REF_T<typename blt::meta::arg_helper<Args...>::First>>();
((call_drop<Args>(offset), offset -= stack_allocator::aligned_size<NO_REF_T<Args>>()), ...);
}
[[nodiscard]] bool empty() const noexcept

@ -1 +1 @@
Subproject commit 4327b34c841fd6d8fb6509757d5cab2717d35457
Subproject commit 92300bc6a29927f5354d516df76ad40be7fca868

View File

@ -43,39 +43,46 @@
//static constexpr long SEED = 41912;
static const unsigned long SEED = std::random_device()();
inline std::atomic_uint64_t last_value = 0;
inline std::atomic_uint64_t constructions = 0;
inline std::atomic_uint64_t destructions = 0;
class move_float
{
public:
move_float(): f(new float())
{ constructions++; }
explicit move_float(float f): f(new float(f))
move_float(): f(new float()), assignment(++last_value)
{
constructions++;
// BLT_TRACE("Value Constructed");
BLT_TRACE("Value %ld Default Constructed", assignment);
}
explicit move_float(float f): f(new float(f)), assignment(++last_value)
{
constructions++;
BLT_TRACE("Value %ld Constructed", assignment);
}
explicit operator float() const
{
BLT_TRACE("Using value %ld", assignment);
return *f;
}
float get() const
[[nodiscard]] float get() const
{
BLT_TRACE("Using value %ld", assignment);
return *f;
}
float operator*() const
{
BLT_TRACE("Using value %ld", assignment);
return *f;
}
void drop() // NOLINT
{
//BLT_TRACE("Drop Called");
BLT_TRACE("Drop Called On %ld", assignment);
delete f;
f = nullptr;
destructions++;
@ -83,6 +90,7 @@ class move_float
private:
float* f = nullptr;
blt::size_t assignment;
};
static_assert(std::is_trivially_copyable_v<move_float>);
@ -90,7 +98,7 @@ static_assert(std::is_trivially_copyable_v<move_float>);
struct context
{
move_float x, y;
float x, y;
};
std::array<context, 200> fitness_cases;
@ -104,32 +112,32 @@ blt::gp::prog_config_t config = blt::gp::prog_config_t()
.set_reproduction_chance(0)
.set_max_generations(1)
.set_pop_size(1)
.set_thread_count(0);
.set_thread_count(1);
blt::gp::type_provider type_system;
blt::gp::gp_program program{type_system, SEED, config};
blt::gp::operation_t add([](const move_float& a, const move_float& b) { return move_float(*a + *b); }, "add");
blt::gp::operation_t sub([](const move_float& a, const move_float& b) { return move_float(*a - *b); }, "sub");
blt::gp::operation_t mul([](const move_float& a, const move_float& b) { return move_float(*a * *b); }, "mul");
blt::gp::operation_t pro_div([](const move_float& a, const move_float& b) { return move_float(*b == 0.0f ? 1.0f : *a / *b); }, "div");
blt::gp::operation_t op_sin([](const move_float& a) { return move_float(std::sin(*a)); }, "sin");
blt::gp::operation_t op_cos([](const move_float& a) { return move_float(std::cos(*a)); }, "cos");
blt::gp::operation_t op_exp([](const move_float& a) { return move_float(std::exp(*a)); }, "exp");
blt::gp::operation_t op_log([](const move_float& a) { return move_float(*a == 0.0f ? 0.0f : std::log(*a)); }, "log");
blt::gp::operation_t add([](const move_float& a, const move_float& b) { return move_float(*a + *b); }, "add"); // 0
blt::gp::operation_t sub([](const move_float& a, const move_float& b) { return move_float(*a - *b); }, "sub"); // 1
blt::gp::operation_t mul([](const move_float& a, const move_float& b) { return move_float(*a * *b); }, "mul"); // 2
blt::gp::operation_t pro_div([](const move_float& a, const move_float& b) { return move_float(*b == 0.0f ? 1.0f : *a / *b); }, "div"); // 3
blt::gp::operation_t op_sin([](const move_float& a) { return move_float(std::sin(*a)); }, "sin"); // 4
blt::gp::operation_t op_cos([](const move_float& a) { return move_float(std::cos(*a)); }, "cos"); // 5
blt::gp::operation_t op_exp([](const move_float& a) { return move_float(std::exp(*a)); }, "exp"); // 6
blt::gp::operation_t op_log([](const move_float& a) { return move_float(*a == 0.0f ? 0.0f : std::log(*a)); }, "log"); // 7
blt::gp::operation_t lit([]() {
blt::gp::operation_t lit([]() { // 8
return move_float(program.get_random().get_float(-320.0f, 320.0f));
}, "lit");
blt::gp::operation_t op_x([](const context& context) {
return context.x;
blt::gp::operation_t op_x([](const context& context) { // 9
return move_float(context.x);
}, "x");
constexpr auto fitness_function = [](blt::gp::tree_t& current_tree, blt::gp::fitness_t& fitness, blt::size_t) {
constexpr double value_cutoff = 1.e15;
for (auto& fitness_case : fitness_cases)
{
auto diff = std::abs(*fitness_case.y - *current_tree.get_evaluation_value<move_float>(&fitness_case));
auto diff = std::abs(fitness_case.y - *current_tree.get_evaluation_value<move_float>(&fitness_case));
if (diff < value_cutoff)
{
fitness.raw_fitness += diff;
@ -159,7 +167,7 @@ int main()
constexpr float half_range = range / 2.0;
auto x = program.get_random().get_float(-half_range, half_range);
auto y = example_function(x);
fitness_case = {move_float(x), move_float(y)};
fitness_case = {x, y};
}
BLT_DEBUG("Setup Types and Operators");