Merge pull request #341 from ethereum/cpp

cpp: Extend API to allow moving evmc::vm objects
This commit is contained in:
Paweł Bylica 2019-07-03 19:44:34 +02:00 committed by GitHub
commit f6d3f97e13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 89 additions and 2 deletions

View File

@ -10,6 +10,8 @@
new `evmc_load_and_configure()` function.
- Added: [[#327](https://github.com/ethereum/evmc/pull/327)]
Full support for 32-bit architectures has been added.
- Added: [[#341](https://github.com/ethereum/evmc/pull/341)]
Support for moving `evmc::vm` objects in C++ API.
- Changed: [[#293](https://github.com/ethereum/evmc/pull/293)]
In C++ API `evmc::result::raw()` renamed to `evmc::result::release_raw()`.
- Changed: [[#311](https://github.com/ethereum/evmc/pull/311)]

View File

@ -80,11 +80,32 @@ public:
class vm
{
public:
vm() noexcept = default;
/// Converting constructor from evmc_instance.
explicit vm(evmc_instance* instance) noexcept : m_instance{instance} {}
/// Destructor responsible for automatically destroying the VM instance.
~vm() noexcept { m_instance->destroy(m_instance); }
~vm() noexcept
{
if (m_instance)
m_instance->destroy(m_instance);
}
vm(const vm&) = delete;
vm& operator=(const vm&) = delete;
/// Move constructor.
vm(vm&& other) noexcept : m_instance{other.m_instance} { other.m_instance = nullptr; }
/// Move assignment operator.
vm& operator=(vm&& other) noexcept
{
this->~vm();
m_instance = other.m_instance;
other.m_instance = nullptr;
return *this;
}
/// The constructor that captures a VM instance and configures the instance
/// with provided list of options.
@ -96,6 +117,9 @@ public:
set_option(option.first, option.second);
}
/// Checks if contains a valid pointer to the VM instance.
explicit operator bool() const noexcept { return m_instance != nullptr; }
/// Checks whenever the VM instance is ABI compatible with the current EVMC API.
bool is_abi_compatible() const noexcept { return m_instance->abi_version == EVMC_ABI_VERSION; }
@ -128,7 +152,7 @@ public:
}
private:
evmc_instance* const m_instance = nullptr;
evmc_instance* m_instance = nullptr;
};
/// The EVMC Host interface

View File

@ -70,6 +70,67 @@ TEST(cpp, vm_set_option)
EXPECT_EQ(vm.set_option("1", "2"), EVMC_SET_OPTION_INVALID_NAME);
}
TEST(cpp, vm_null)
{
evmc::vm vm;
EXPECT_FALSE(vm);
EXPECT_TRUE(!vm);
}
TEST(cpp, vm_move)
{
static int destroy_counter = 0;
const auto template_instance =
evmc_instance{EVMC_ABI_VERSION, "", "", [](evmc_instance*) { ++destroy_counter; },
nullptr, nullptr, nullptr, nullptr};
EXPECT_EQ(destroy_counter, 0);
{
auto v1 = template_instance;
auto v2 = template_instance;
auto vm1 = evmc::vm{&v1};
EXPECT_TRUE(vm1);
vm1 = evmc::vm{&v2};
EXPECT_TRUE(vm1);
}
EXPECT_EQ(destroy_counter, 2);
{
auto v1 = template_instance;
auto vm1 = evmc::vm{&v1};
EXPECT_TRUE(vm1);
vm1 = evmc::vm{};
EXPECT_FALSE(vm1);
}
EXPECT_EQ(destroy_counter, 3);
{
auto v1 = template_instance;
auto vm1 = evmc::vm{&v1};
EXPECT_TRUE(vm1);
auto vm2 = std::move(vm1);
EXPECT_TRUE(vm2);
EXPECT_FALSE(vm1); // NOLINT
auto vm3 = std::move(vm2);
EXPECT_TRUE(vm3);
EXPECT_FALSE(vm2); // NOLINT
EXPECT_FALSE(vm1);
}
EXPECT_EQ(destroy_counter, 4);
{
// Moving to itself will destroy the VM and reset the evmc::vm.
auto v1 = template_instance;
auto vm1 = evmc::vm{&v1};
auto& vm1_ref = vm1;
vm1 = std::move(vm1_ref);
EXPECT_EQ(destroy_counter, 5); // Already destroyed.
EXPECT_FALSE(vm1); // Null.
}
EXPECT_EQ(destroy_counter, 5);
}
TEST(cpp, host)
{
// Use example host to execute all methods from the C++ host wrapper.