summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorMikhail Pozdnyakov <mikhail.pozdnyakov@mapbox.com>2019-02-07 12:13:19 +0200
committerMikhail Pozdnyakov <mikhail.pozdnyakov@mapbox.com>2019-02-28 17:45:21 +0200
commit810999fadf41576204752113f33336a69603de4a (patch)
treec228c311bf62d62af0710cc0a0a0ca7f7ebae813 /include
parent96ec18376fb91fd857d96ecdb07db14d8a5cf4fd (diff)
downloadqtlocation-mapboxgl-810999fadf41576204752113f33336a69603de4a.tar.gz
[core] Simplify util::peer
Remove custom vtable, base implementation on `std::unique_ptr`.
Diffstat (limited to 'include')
-rw-r--r--include/mbgl/util/peer.hpp97
1 files changed, 9 insertions, 88 deletions
diff --git a/include/mbgl/util/peer.hpp b/include/mbgl/util/peer.hpp
index a4abea0e88..d56526b80d 100644
--- a/include/mbgl/util/peer.hpp
+++ b/include/mbgl/util/peer.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include <memory>
#include <type_traits>
#include <utility>
@@ -8,102 +9,22 @@ namespace util {
class peer {
public:
- peer() = default;
- peer(const peer&) = delete;
-
- peer(peer&& other)
- : vtable(other.vtable)
- {
- if (vtable) {
- vtable->move(other.storage, storage);
- }
- other.vtable = nullptr;
- }
+ peer() noexcept : storage(nullptr, noop_deleter) {}
template <class T>
- peer(T&& value) {
- using _Vt = std::decay_t<T>;
- vtable = get_vtable<_Vt>();
- new (&storage) _Vt(std::forward<T>(value));
- }
-
- ~peer() {
- reset();
- }
-
- peer& operator=(peer&& rhs) {
- peer(std::move(rhs)).swap(*this);
- return *this;
- }
-
- void reset() {
- if (vtable) {
- vtable->destroy(storage);
- vtable = nullptr;
- }
- }
+ peer(T&& value) noexcept : storage(new std::decay_t<T>(std::forward<T>(value)), cast_deleter<std::decay_t<T>>) {}
- void swap(peer& rhs) {
- if (this == &rhs) {
- return;
- } else {
- peer tmp(std::move(rhs));
- rhs.vtable = vtable;
- if (rhs.vtable) {
- rhs.vtable->move(storage, rhs.storage);
- }
- vtable = tmp.vtable;
- if (vtable) {
- vtable->move(tmp.storage, storage);
- }
- }
- }
-
- bool has_value() const {
- return vtable != nullptr;
- }
-
- template <class T>
- T& get() {
- return reinterpret_cast<T&>(storage);
- }
+ bool has_value() const noexcept { return static_cast<bool>(storage); }
template <class T>
- T&& take() {
- reset();
- return std::move(get<T>());
- }
+ T& get() noexcept { return *reinterpret_cast<T*>(storage.get()); }
private:
- using storage_t = std::aligned_storage_t<2*sizeof(void*), alignof(void*)>;
-
- struct vtable {
- virtual ~vtable() = default;
- virtual void move(storage_t&, storage_t&) = 0;
- virtual void destroy(storage_t&) = 0;
- };
-
- template <class T>
- struct vtable_impl : public vtable {
- static_assert(sizeof(T) <= sizeof(storage_t), "peer object is too big");
-
- void move(storage_t& src, storage_t& dst) override {
- new (&dst) T(std::move(reinterpret_cast<T&>(src)));
- destroy(src);
- }
-
- void destroy(storage_t& s) override {
- reinterpret_cast<T&>(s).~T();
- }
- };
-
- template <class T>
- static vtable* get_vtable() {
- static vtable_impl<T> vtable;
- return &vtable;
- }
+ template <typename T>
+ static void cast_deleter(void* ptr) noexcept { delete reinterpret_cast<T*>(ptr); }
+ static void noop_deleter(void*) noexcept {}
- vtable* vtable = nullptr;
+ using storage_t = std::unique_ptr<void, void(*)(void*)>;
storage_t storage;
};