[K/N] Add kotlin::ManuallyScoped<T> ^KT-56233

kotlin::ManuallyScoped<T> is a wrapper over T that pins T in place
and has a trivial constructor and destructor. Creation and destruction
of T must be carried out manually by construct and destroy methods.
This commit is contained in:
Alexander Shabalin
2023-03-31 17:13:32 +02:00
committed by Space Team
parent 6a0e6b11bd
commit aad6d2c8f8
2 changed files with 108 additions and 0 deletions
@@ -0,0 +1,68 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
#include "ManuallyScoped.hpp"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
using namespace kotlin;
using ::testing::_;
namespace {
struct NonTrivialCtor {
int x = 123;
};
static_assert(!std::is_trivially_constructible_v<NonTrivialCtor>);
static_assert(std::is_trivially_destructible_v<NonTrivialCtor>);
static_assert(std::is_trivially_constructible_v<ManuallyScoped<NonTrivialCtor>>);
static_assert(std::is_trivially_destructible_v<ManuallyScoped<NonTrivialCtor>>);
class NonTrivialDtor : private Pinned {
public:
explicit NonTrivialDtor(std::function<void(NonTrivialDtor*)> dtorHook) : dtorHook_(std::move(dtorHook)) {}
~NonTrivialDtor() { dtorHook_(this); }
private:
std::function<void(NonTrivialDtor*)> dtorHook_;
};
static_assert(!std::is_trivially_constructible_v<NonTrivialDtor>);
static_assert(!std::is_trivially_destructible_v<NonTrivialDtor>);
static_assert(std::is_trivially_constructible_v<ManuallyScoped<NonTrivialDtor>>);
static_assert(std::is_trivially_destructible_v<ManuallyScoped<NonTrivialDtor>>);
} // namespace
class ManuallyScopedTest : public testing::Test {
public:
testing::MockFunction<void(NonTrivialDtor*)>& dtorHook() noexcept { return dtorHook_; }
private:
testing::StrictMock<testing::MockFunction<void(NonTrivialDtor*)>> dtorHook_;
};
TEST_F(ManuallyScopedTest, NonTrivialCtor) {
ManuallyScoped<NonTrivialCtor> instance;
instance.construct();
EXPECT_THAT(instance->x, 123);
}
TEST_F(ManuallyScopedTest, NonTrivialDtor) {
ManuallyScoped<NonTrivialDtor> instance;
instance.construct(dtorHook().AsStdFunction());
EXPECT_CALL(dtorHook(), Call(&*instance));
instance.destroy();
}
TEST_F(ManuallyScopedTest, NonTrivialDtorLeak) {
ManuallyScoped<NonTrivialDtor> instance;
instance.construct(dtorHook().AsStdFunction());
EXPECT_CALL(dtorHook(), Call(_)).Times(0);
}