Add MoveOnly and Pinned (#4526)
This commit is contained in:
committed by
Stanislav Erokhin
parent
98b2f3feec
commit
0dfc99ab1a
@@ -38,11 +38,12 @@
|
||||
#include "Exceptions.h"
|
||||
#include "ExecFormat.h"
|
||||
#include "Memory.h"
|
||||
#include "Mutex.hpp"
|
||||
#include "Natives.h"
|
||||
#include "KString.h"
|
||||
#include "SourceInfo.h"
|
||||
#include "Types.h"
|
||||
#include "Utils.h"
|
||||
#include "Utils.hpp"
|
||||
#include "ObjCExceptions.h"
|
||||
|
||||
namespace {
|
||||
@@ -279,7 +280,8 @@ RUNTIME_NORETURN void TerminateWithUnhandledException(KRef throwable) {
|
||||
#if KONAN_HAS_CXX11_EXCEPTION_FUNCTIONS
|
||||
|
||||
namespace {
|
||||
class TerminateHandler {
|
||||
// Copy, move and assign would be safe, but not much useful, so let's delete all (rule of 5)
|
||||
class TerminateHandler : private kotlin::Pinned {
|
||||
|
||||
// In fact, it's safe to call my_handler directly from outside: it will do the job and then invoke original handler,
|
||||
// even if it has not been initialized yet. So one may want to make it public and/or not the class member
|
||||
@@ -313,11 +315,6 @@ class TerminateHandler {
|
||||
return singleton;
|
||||
}
|
||||
|
||||
// Copy, move and assign would be safe, but not much useful, so let's delete all (rule of 5)
|
||||
TerminateHandler(const TerminateHandler&) = delete;
|
||||
TerminateHandler(TerminateHandler&&) = delete;
|
||||
TerminateHandler& operator=(const TerminateHandler&) = delete;
|
||||
TerminateHandler& operator=(TerminateHandler&&) = delete;
|
||||
// Dtor might be in use to restore original handler. However, consequent install
|
||||
// will not reconstruct handler anyway, so let's keep dtor deleted to avoid confusion.
|
||||
~TerminateHandler() = delete;
|
||||
|
||||
+7
-4
@@ -14,8 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef RUNTIME_MUTEX_H
|
||||
#define RUNTIME_MUTEX_H
|
||||
|
||||
#include <cstdint>
|
||||
#include "KAssert.h"
|
||||
#include "Utils.hpp"
|
||||
|
||||
class SimpleMutex {
|
||||
private:
|
||||
@@ -37,7 +41,7 @@ class SimpleMutex {
|
||||
|
||||
// TODO: use std::lock_guard instead?
|
||||
template <class Mutex>
|
||||
class LockGuard {
|
||||
class LockGuard : private kotlin::Pinned {
|
||||
public:
|
||||
explicit LockGuard(Mutex& mutex_) : mutex(mutex_) {
|
||||
mutex.lock();
|
||||
@@ -49,7 +53,6 @@ class LockGuard {
|
||||
|
||||
private:
|
||||
Mutex& mutex;
|
||||
|
||||
LockGuard(const LockGuard&) = delete;
|
||||
LockGuard& operator=(const LockGuard&) = delete;
|
||||
};
|
||||
|
||||
#endif // RUNTIME_MUTEX_H
|
||||
@@ -39,7 +39,7 @@
|
||||
#import "ObjCExportPrivate.h"
|
||||
#import "ObjCMMAPI.h"
|
||||
#import "Runtime.h"
|
||||
#import "Utils.h"
|
||||
#import "Mutex.hpp"
|
||||
#import "Exceptions.h"
|
||||
|
||||
struct ObjCToKotlinMethodAdapter {
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#import "ObjCExport.h"
|
||||
#import "Porting.h"
|
||||
#import "Runtime.h"
|
||||
#import "Utils.h"
|
||||
#import "Mutex.hpp"
|
||||
|
||||
#import "ObjCExportErrors.h"
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#include "ObjCExportPrivate.h"
|
||||
#include "ObjCMMAPI.h"
|
||||
#include "Types.h"
|
||||
#include "Utils.h"
|
||||
#include "Mutex.hpp"
|
||||
|
||||
// Replaced in ObjCExportCodeGenerator.
|
||||
__attribute__((weak)) const char* Kotlin_ObjCInterop_uniquePrefix = nullptr;
|
||||
|
||||
@@ -7,22 +7,18 @@
|
||||
#define RUNTIME_OBJCMMAPI_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#if KONAN_OBJC_INTEROP
|
||||
|
||||
extern "C" ALWAYS_INLINE void Kotlin_ObjCExport_releaseAssociatedObject(void* associatedObject);
|
||||
|
||||
namespace konan {
|
||||
class AutoreleasePool {
|
||||
class AutoreleasePool : private kotlin::Pinned {
|
||||
public:
|
||||
AutoreleasePool();
|
||||
~AutoreleasePool();
|
||||
|
||||
AutoreleasePool(const AutoreleasePool&) = delete;
|
||||
AutoreleasePool(AutoreleasePool&&) = delete;
|
||||
AutoreleasePool& operator=(const AutoreleasePool&) = delete;
|
||||
AutoreleasePool& operator=(AutoreleasePool&&) = delete;
|
||||
|
||||
private:
|
||||
void* handle;
|
||||
};
|
||||
|
||||
@@ -10,9 +10,10 @@
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "Types.h"
|
||||
#include "Utils.hpp"
|
||||
|
||||
template <class F>
|
||||
class ScopedStrictMockFunction {
|
||||
class ScopedStrictMockFunction : private kotlin::MoveOnly {
|
||||
public:
|
||||
using Mock = testing::StrictMock<testing::MockFunction<F>>;
|
||||
|
||||
@@ -24,9 +25,6 @@ public:
|
||||
*globalMockLocation_ = mock_.get();
|
||||
}
|
||||
|
||||
ScopedStrictMockFunction(const ScopedStrictMockFunction&) = delete;
|
||||
ScopedStrictMockFunction& operator=(const ScopedStrictMockFunction&) = delete;
|
||||
|
||||
ScopedStrictMockFunction(ScopedStrictMockFunction&& rhs) : globalMockLocation_(rhs.globalMockLocation_), mock_(std::move(rhs.mock_)) {
|
||||
rhs.globalMockLocation_ = nullptr;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.
|
||||
*/
|
||||
|
||||
#ifndef RUNTIME_UTILS_H
|
||||
#define RUNTIME_UTILS_H
|
||||
|
||||
namespace kotlin {
|
||||
|
||||
// A helper for implementing classes with disabled copy constructor and copy assignment.
|
||||
// Usage:
|
||||
// class A: private MoveOnly {
|
||||
// ...
|
||||
// };
|
||||
// Prefer private inheritance to discourage casting instances of `A` to instances
|
||||
// of `MoveOnly`.
|
||||
class MoveOnly {
|
||||
// Hide constructors, assignments and destructor, to discourage operating on an instance of `MoveOnly`.
|
||||
protected:
|
||||
MoveOnly() noexcept = default;
|
||||
MoveOnly(const MoveOnly&) = delete;
|
||||
MoveOnly(MoveOnly&&) noexcept = default;
|
||||
|
||||
MoveOnly& operator=(const MoveOnly&) = delete;
|
||||
MoveOnly& operator=(MoveOnly&&) noexcept = default;
|
||||
|
||||
// Not virtual by design. Since this class hides this destructor, no one can destroy an
|
||||
// instance of `MoveOnly` directly, so this destructor is never called in a virtual manner.
|
||||
~MoveOnly() = default;
|
||||
};
|
||||
|
||||
// A helper for implementing classes with disabled copy and move constructors, and copy and move assignments.
|
||||
// Usage:
|
||||
// class A: private Pinned {
|
||||
// ...
|
||||
// };
|
||||
// Prefer private inheritance to discourage casting instances of `A` to instances
|
||||
// of `Pinned`.
|
||||
class Pinned {
|
||||
// Hide constructors, assignments and destructor, to discourage operating on an instance of `Pinned`.
|
||||
protected:
|
||||
Pinned() noexcept = default;
|
||||
Pinned(const Pinned&) = delete;
|
||||
Pinned(Pinned&&) = delete;
|
||||
|
||||
Pinned& operator=(const Pinned&) = delete;
|
||||
Pinned& operator=(Pinned&&) = delete;
|
||||
|
||||
// Not virtual by design. Since this class hides this destructor, no one can destroy an
|
||||
// instance of `Pinned` directly, so this destructor is never called in a virtual manner.
|
||||
~Pinned() = default;
|
||||
};
|
||||
|
||||
} // namespace kotlin
|
||||
|
||||
#endif // RUNTIME_UTILS_H
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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 "Utils.hpp"
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// TODO: use std variants when we move to C++17
|
||||
template <typename T>
|
||||
constexpr bool is_nothrow_default_constructible_v = std::is_nothrow_default_constructible<T>::value;
|
||||
template <typename T>
|
||||
constexpr bool is_nothrow_destructible_v = std::is_nothrow_destructible<T>::value;
|
||||
template <typename T>
|
||||
constexpr bool is_copy_constructible_v = std::is_copy_constructible<T>::value;
|
||||
template <typename T>
|
||||
constexpr bool is_copy_assignable_v = std::is_copy_assignable<T>::value;
|
||||
template <typename T>
|
||||
constexpr bool is_move_constructible_v = std::is_move_constructible<T>::value;
|
||||
template <typename T>
|
||||
constexpr bool is_move_assignable_v = std::is_move_assignable<T>::value;
|
||||
template <typename T>
|
||||
constexpr bool is_nothrow_move_constructible_v = std::is_nothrow_move_constructible<T>::value;
|
||||
template <typename T>
|
||||
constexpr bool is_nothrow_move_assignable_v = std::is_nothrow_move_assignable<T>::value;
|
||||
|
||||
struct A {
|
||||
int field;
|
||||
};
|
||||
|
||||
class MoveOnlyImpl : private kotlin::MoveOnly {
|
||||
public:
|
||||
A a;
|
||||
};
|
||||
|
||||
class PinnedImpl : private kotlin::Pinned {
|
||||
public:
|
||||
A a;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(UtilsTest, MoveOnlyImpl) {
|
||||
static_assert(is_nothrow_default_constructible_v<MoveOnlyImpl>, "Must be nothrow default constructible");
|
||||
static_assert(is_nothrow_destructible_v<MoveOnlyImpl>, "Must be nothrow destructible");
|
||||
static_assert(!is_copy_constructible_v<MoveOnlyImpl>, "Must not be copy constructible");
|
||||
static_assert(!is_copy_assignable_v<MoveOnlyImpl>, "Must not be copy assignable");
|
||||
static_assert(is_nothrow_move_constructible_v<MoveOnlyImpl>, "Must be nothrow move constructible");
|
||||
static_assert(is_nothrow_move_assignable_v<MoveOnlyImpl>, "Must be nothrow move assignable");
|
||||
static_assert(sizeof(MoveOnlyImpl) == sizeof(A), "Must not increase size");
|
||||
}
|
||||
|
||||
TEST(UtilsTest, PinnedImpl) {
|
||||
static_assert(is_nothrow_default_constructible_v<PinnedImpl>, "Must be nothrow default constructible");
|
||||
static_assert(is_nothrow_destructible_v<PinnedImpl>, "Must be nothrow destructible");
|
||||
static_assert(!is_copy_constructible_v<PinnedImpl>, "Must not be copy constructible");
|
||||
static_assert(!is_copy_assignable_v<PinnedImpl>, "Must not be copy assignable");
|
||||
static_assert(!is_move_constructible_v<PinnedImpl>, "Must not be move constructible");
|
||||
static_assert(!is_move_assignable_v<PinnedImpl>, "Must not be move assignable");
|
||||
static_assert(sizeof(PinnedImpl) == sizeof(A), "Must not increase size");
|
||||
}
|
||||
Reference in New Issue
Block a user