Przeglądaj źródła

Invoke implemented.

main
offa 7 lat temu
rodzic
commit
2dbe0ca826
2 zmienionych plików z 86 dodań i 12 usunięć
  1. +15
    -2
      include/unique_resource.h
  2. +71
    -10
      test/UniqueResourceTest.cpp

+ 15
- 2
include/unique_resource.h Wyświetl plik

{ {
try try
{ {
m_deleter();
m_deleter(m_resource);
} }
catch( ... ) { /* Empty */ } catch( ... ) { /* Empty */ }
} }
} }




void invoke(const invoke_it strategy = invoke_it::once) noexcept
{
if( m_execute_on_destruction == true )
{
try
{
m_deleter(m_resource);
}
catch( ... ) { /* Empty */ }
}
m_execute_on_destruction = ( strategy == invoke_it::again );
}

const Ressource& release() noexcept const Ressource& release() noexcept
{ {
m_execute_on_destruction = false; m_execute_on_destruction = false;


unique_resource_t& operator=(unique_resource_t&& other) noexcept unique_resource_t& operator=(unique_resource_t&& other) noexcept
{ {
m_deleter();
m_deleter(m_resource);
m_resource = std::move(other.m_resource); m_resource = std::move(other.m_resource);
m_deleter = std::move(other.m_deleter); m_deleter = std::move(other.m_deleter);
m_execute_on_destruction = other.m_execute_on_destruction; m_execute_on_destruction = other.m_execute_on_destruction;

+ 71
- 10
test/UniqueResourceTest.cpp Wyświetl plik

std::size_t calls{0}; std::size_t calls{0};


{ {
auto guard = sr::unique_resource(Handle{3}, [&calls] { ++calls; });
auto guard = sr::unique_resource(Handle{3}, [&calls](auto) { ++calls; });
static_cast<void>(guard); static_cast<void>(guard);
} }


std::size_t calls{0}; std::size_t calls{0};


{ {
auto guard = sr::unique_resource(Handle{3}, [&calls] { ++calls; });
auto guard = sr::unique_resource(Handle{3}, [&calls](auto) { ++calls; });
guard.release(); guard.release();
} }




TEST_CASE("release returns reference to resource", "[UniqueResource]") TEST_CASE("release returns reference to resource", "[UniqueResource]")
{ {
auto guard = sr::unique_resource(Handle{3}, [] { });
auto guard = sr::unique_resource(Handle{3}, [](auto) { });
const auto result = guard.release(); const auto result = guard.release();


REQUIRE(3 == result); REQUIRE(3 == result);
std::size_t calls{0}; std::size_t calls{0};


{ {
auto movedFrom = sr::unique_resource(Handle{3}, [&calls] { ++calls; });
auto movedFrom = sr::unique_resource(Handle{3}, [&calls](auto) { ++calls; });
auto guard = std::move(movedFrom); auto guard = std::move(movedFrom);
static_cast<void>(guard); static_cast<void>(guard);
} }
std::size_t calls{0}; std::size_t calls{0};


{ {
auto movedFrom = sr::unique_resource(Handle{3}, [&calls] { ++calls; });
auto movedFrom = sr::unique_resource(Handle{3}, [&calls](auto) { ++calls; });
auto guard = std::move(movedFrom); auto guard = std::move(movedFrom);
static_cast<void>(guard); static_cast<void>(guard);
} }
std::size_t calls{0}; std::size_t calls{0};


{ {
auto movedFrom = sr::unique_resource(Handle{3}, [&calls] { ++calls; });
auto movedFrom = sr::unique_resource(Handle{3}, [&calls](auto) { ++calls; });
movedFrom.release(); movedFrom.release();
auto guard = std::move(movedFrom); auto guard = std::move(movedFrom);
static_cast<void>(guard); static_cast<void>(guard);
TEST_CASE("move assignment releases moved-from object", "[UniqueResource]") TEST_CASE("move assignment releases moved-from object", "[UniqueResource]")
{ {
std::size_t calls{0}; std::size_t calls{0};
std::function<void()> del = [&calls] { ++calls; };
std::function<void(Handle)> del = [&calls](auto) { ++calls; };


{ {
auto movedFrom = sr::unique_resource(Handle{3}, del); auto movedFrom = sr::unique_resource(Handle{3}, del);
TEST_CASE("move assignment transfers state", "[UniqueResource]") TEST_CASE("move assignment transfers state", "[UniqueResource]")
{ {
std::size_t calls{0}; std::size_t calls{0};
std::function<void()> del = [&calls] { ++calls; };
std::function<void(Handle)> del = [&calls](auto) { ++calls; };


{ {
auto movedFrom = sr::unique_resource(Handle{3}, del); auto movedFrom = sr::unique_resource(Handle{3}, del);
TEST_CASE("move assignment transfers state if released", "[UniqueResource]") TEST_CASE("move assignment transfers state if released", "[UniqueResource]")
{ {
std::size_t calls{0}; std::size_t calls{0};
std::function<void()> del = [&calls] { ++calls; };
std::function<void(Handle)> del = [&calls](auto) { ++calls; };


{ {
auto movedFrom = sr::unique_resource(Handle{3}, del); auto movedFrom = sr::unique_resource(Handle{3}, del);
TEST_CASE("no exception propagation from deleter", "[UniqueResource]") TEST_CASE("no exception propagation from deleter", "[UniqueResource]")
{ {
REQUIRE_NOTHROW([] { REQUIRE_NOTHROW([] {
auto guard = sr::unique_resource(Handle{3}, [] { throw "Don't propagate this!"; });
auto guard = sr::unique_resource(Handle{3}, [](auto) { throw "Don't propagate this!"; });
static_cast<void>(guard); static_cast<void>(guard);
}()); }());
} }


TEST_CASE("invoke executes deleter on resource", "[UniqueResource]")
{
std::size_t calls{0};

{
auto guard = sr::unique_resource(Handle{3}, [&calls](auto h)
{
REQUIRE(h == 3);
++calls;
});
guard.invoke();
}

REQUIRE(calls == 1);
}

TEST_CASE("invoke executes only multiple times if again strategy", "[UniqueResource]")
{
std::size_t calls{0};

{
auto guard = sr::unique_resource(Handle{3}, [&calls](auto h) { if( h == 3 ) { ++calls;} });
guard.invoke(sr::invoke_it::again);
guard.invoke(sr::invoke_it::again);
}

REQUIRE(calls == 3);
}

TEST_CASE("invoke does nothing if released", "[UniqueResource]")
{
std::size_t calls{0};

{
auto guard = sr::unique_resource(Handle{3}, [&calls](auto) { ++calls; });
guard.release();
guard.invoke(sr::invoke_it::once);
}

REQUIRE(calls == 0);
}

TEST_CASE("invoke executes after release if again strategy", "[UniqueResource]")
{
std::size_t calls{0};

{
auto guard = sr::unique_resource(Handle{3}, [&calls](auto) { ++calls; });
guard.release();
guard.invoke(sr::invoke_it::again);
}

REQUIRE(calls == 1);
}

TEST_CASE("invoke does not propagate exception", "[UniqueResource]")
{
auto guard = sr::unique_resource(Handle{3}, [](auto) { throw "Don't propagate this!"; });
REQUIRE_NOTHROW(guard.invoke());
}


Ładowanie…
Anuluj
Zapisz