/*
- * Copyright 2017 Facebook, Inc.
+ * Copyright 2013-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#pragma once
-#include <folly/Traits.h>
-
+#include <cassert>
+#include <cerrno>
#include <cstddef>
#include <cstdlib>
#include <exception>
#include <limits>
#include <memory>
#include <stdexcept>
+#include <type_traits>
#include <utility>
+#include <folly/Traits.h>
+#include <folly/functional/Invoke.h>
+#include <folly/portability/Config.h>
+#include <folly/portability/Malloc.h>
+
namespace folly {
+#if _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 || \
+ (defined(__ANDROID__) && (__ANDROID_API__ > 15)) || \
+ (defined(__APPLE__) && \
+ (__MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_6 || \
+ __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_3_0))
+
+inline void* aligned_malloc(size_t size, size_t align) {
+ // use posix_memalign, but mimic the behaviour of memalign
+ void* ptr = nullptr;
+ int rc = posix_memalign(&ptr, align, size);
+ return rc == 0 ? (errno = 0, ptr) : (errno = rc, nullptr);
+}
+
+inline void aligned_free(void* aligned_ptr) {
+ free(aligned_ptr);
+}
+
+#elif defined(_WIN32)
+
+inline void* aligned_malloc(size_t size, size_t align) {
+ return _aligned_malloc(size, align);
+}
+
+inline void aligned_free(void* aligned_ptr) {
+ _aligned_free(aligned_ptr);
+}
+
+#else
+
+inline void* aligned_malloc(size_t size, size_t align) {
+ return memalign(align, size);
+}
+
+inline void aligned_free(void* aligned_ptr) {
+ free(aligned_ptr);
+}
+
+#endif
+
/**
* For exception safety and consistency with make_shared. Erase me when
* we have std::make_unique().
#else
-template<typename T, typename... Args>
+template <typename T, typename... Args>
typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique(Args&&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
// Allows 'make_unique<T[]>(10)'. (N3690 s20.9.1.4 p3-4)
-template<typename T>
+template <typename T>
typename std::enable_if<std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique(const size_t n) {
return std::unique_ptr<T>(new typename std::remove_extent<T>::type[n]());
}
// Disallows 'make_unique<T[10]>()'. (N3690 s20.9.1.4 p5)
-template<typename T, typename... Args>
+template <typename T, typename... Args>
typename std::enable_if<
std::extent<T>::value != 0, std::unique_ptr<T>>::type
make_unique(Args&&...) = delete;
return std::weak_ptr<T>(ptr);
}
-using SysBufferDeleter = static_function_deleter<void, ::free>;
+struct SysBufferDeleter {
+ void operator()(void* p) const {
+ ::free(p);
+ }
+};
+
using SysBufferUniquePtr = std::unique_ptr<void, SysBufferDeleter>;
inline SysBufferUniquePtr allocate_sys_buffer(size_t size) {
return SysBufferUniquePtr(::malloc(size));
public:
void* allocate(size_t size) {
void* p = ::malloc(size);
- if (!p) throw std::bad_alloc();
+ if (!p) {
+ throw std::bad_alloc();
+ }
return p;
}
void deallocate(void* p) {
{
typedef typename std::remove_reference<Allocator>::type allocator_type;
-public:
+ public:
typedef typename Allocator::pointer pointer;
allocator_delete() = default;
}
void operator()(pointer p) const {
- if (!p) return;
+ if (!p) {
+ return;
+ }
const_cast<allocator_delete*>(this)->destroy(p);
const_cast<allocator_delete*>(this)->deallocate(p, 1);
}
};
-template <typename T, typename Allocator>
-class is_simple_allocator {
- FOLLY_CREATE_HAS_MEMBER_FN_TRAITS(has_destroy, destroy);
+namespace detail {
- typedef typename std::remove_const<
- typename std::remove_reference<Allocator>::type
- >::type allocator;
- typedef typename std::remove_reference<T>::type value_type;
- typedef value_type* pointer;
+FOLLY_CREATE_MEMBER_INVOKE_TRAITS(destroy_invoke_traits, destroy);
-public:
- constexpr static bool value = !has_destroy<allocator, void(pointer)>::value
- && !has_destroy<allocator, void(void*)>::value;
-};
+} // namespace detail
+
+template <typename Allocator, typename Value>
+using is_simple_allocator =
+ Negation<detail::destroy_invoke_traits::is_invocable<Allocator, Value*>>;
template <typename T, typename Allocator>
struct as_stl_allocator {
typedef typename std::conditional<
- is_simple_allocator<T, Allocator>::value,
+ is_simple_allocator<
+ typename std::remove_reference<Allocator>::type,
+ typename std::remove_reference<T>::type
+ >::value,
folly::StlAllocator<
typename std::remove_reference<Allocator>::type,
typename std::remove_reference<T>::type
template <typename T, typename Allocator>
typename std::enable_if<
- is_simple_allocator<T, Allocator>::value,
+ is_simple_allocator<
+ typename std::remove_reference<Allocator>::type,
+ typename std::remove_reference<T>::type
+ >::value,
folly::StlAllocator<
typename std::remove_reference<Allocator>::type,
typename std::remove_reference<T>::type
template <typename T, typename Allocator>
typename std::enable_if<
- !is_simple_allocator<T, Allocator>::value,
+ !is_simple_allocator<
+ typename std::remove_reference<Allocator>::type,
+ typename std::remove_reference<T>::type
+ >::value,
typename std::remove_reference<Allocator>::type
>::type make_stl_allocator(Allocator&& allocator) {
return std::move(allocator);
typedef std::unique_ptr<T,
folly::allocator_delete<
typename std::conditional<
- is_simple_allocator<T, Allocator>::value,
+ is_simple_allocator<
+ typename std::remove_reference<Allocator>::type,
+ typename std::remove_reference<T>::type
+ >::value,
folly::StlAllocator<typename std::remove_reference<Allocator>::type, T>,
typename std::remove_reference<Allocator>::type
>::type
*/
template <typename T>
class enable_shared_from_this : public std::enable_shared_from_this<T> {
-public:
+ public:
constexpr enable_shared_from_this() noexcept = default;
std::weak_ptr<T> weak_from_this() noexcept {
return weak_from_this_<T>(this);
}
-private:
+ private:
// Uses SFINAE to detect and call
// std::enable_shared_from_this<T>::weak_from_this() if available. Falls
// back to std::enable_shared_from_this<T>::shared_from_this() otherwise.
#endif
-} // namespace folly
+} // namespace folly