// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab /* * Ceph - scalable distributed file system * * Copyright (C) 2020 Red Hat * * This is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software * Foundation. See file COPYING. * */ #pragma once #include namespace ceph { /// An allocator-aware 'Deleter' for std::unique_ptr. The /// allocator's traits must have a value_type of T. template class deallocator { using allocator_type = Alloc; using allocator_traits = std::allocator_traits; using pointer = typename allocator_traits::pointer; allocator_type alloc; public: explicit deallocator(const allocator_type& alloc) noexcept : alloc(alloc) {} void operator()(pointer p) { allocator_traits::destroy(alloc, p); allocator_traits::deallocate(alloc, p, 1); } }; /// deallocator alias that rebinds Alloc's value_type to T template using deallocator_t = deallocator ::template rebind_alloc>; /// std::unique_ptr alias that rebinds Alloc if necessary, and avoids repetition /// of the template parameter T. template using allocated_unique_ptr = std::unique_ptr>; /// Returns a std::unique_ptr whose memory is managed by the given allocator. template static auto allocate_unique(Alloc& alloc, Args&&... args) -> allocated_unique_ptr { static_assert(!std::is_array_v, "allocate_unique() does not support T[]"); using allocator_type = typename std::allocator_traits ::template rebind_alloc; using allocator_traits = std::allocator_traits; auto a = allocator_type{alloc}; auto p = allocator_traits::allocate(a, 1); try { allocator_traits::construct(a, p, std::forward(args)...); return {p, deallocator{a}}; } catch (...) { allocator_traits::deallocate(a, p, 1); throw; } } } // namespace ceph