// Matrix Construct // // Copyright (C) Matrix Construct Developers, Authors & Contributors // Copyright (C) 2016-2018 Jason Volk // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice is present in all copies. The // full license for this software is available in the LICENSE file. #pragma once #define HAVE_IRCD_BUFFER_UNIQUE_BUFFER_H /// Like unique_ptr, this template holds ownership of an allocated buffer /// template struct ircd::buffer::unique_buffer :buffer { buffer release(); unique_buffer(const size_t &size); unique_buffer(std::unique_ptr &&, const size_t &size); explicit unique_buffer(const buffer &); unique_buffer(); unique_buffer(unique_buffer &&) noexcept; unique_buffer(const unique_buffer &) = delete; unique_buffer &operator=(unique_buffer &&) noexcept; unique_buffer &operator=(const unique_buffer &) = delete; ~unique_buffer() noexcept; }; template ircd::buffer::unique_buffer::unique_buffer() :buffer { nullptr, nullptr } {} template ircd::buffer::unique_buffer::unique_buffer(const buffer &src) :buffer{[&src]() -> buffer { std::unique_ptr ret { new __attribute__((aligned(16))) char[size(src)] }; const mutable_buffer dst { ret.get(), size(src) }; copy(dst, src); return dst; }()} { } template ircd::buffer::unique_buffer::unique_buffer(const size_t &size) :unique_buffer { std::unique_ptr { //TODO: Can't use a template parameter to the attribute even though // it's known at compile time. Hardcoding this until fixed with better // aligned dynamic memory. //new __attribute__((aligned(alignment))) char[size] new __attribute__((aligned(16))) char[size] }, size } { // Alignment can only be 16 bytes for now assert(alignment == 16); } template ircd::buffer::unique_buffer::unique_buffer(std::unique_ptr &&b, const size_t &size) :buffer { typename buffer::iterator(b.release()), size } {} template ircd::buffer::unique_buffer::unique_buffer(unique_buffer &&other) noexcept :buffer { std::move(static_cast(other)) } { get<0>(other) = nullptr; } template ircd::buffer::unique_buffer & ircd::buffer::unique_buffer::operator=(unique_buffer &&other) noexcept { this->~unique_buffer(); static_cast(*this) = std::move(static_cast(other)); get<0>(other) = nullptr; return *this; } template ircd::buffer::unique_buffer::~unique_buffer() noexcept { delete[] data(*this); } template buffer ircd::buffer::unique_buffer::release() { const buffer ret{static_cast(*this)}; static_cast(*this) = buffer{}; return ret; }