123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549 |
- // -*- C++ -*-
- //===------------------------ functional ----------------------------------===//
- //
- // The LLVM Compiler Infrastructure
- //
- // This file is dual licensed under the MIT and the University of Illinois Open
- // Source Licenses. See LICENSE.TXT for details.
- //
- //===----------------------------------------------------------------------===//
- // STL common functionality
- //
- // Some aspects of STL are core language concepts that should be used from all C++ code, regardless
- // of whether exceptions are enabled in the component. Common library code that expects to be used
- // from exception-free components want these concepts, but including STL headers directly introduces
- // friction as it requires components not using STL to declare their STL version. Doing so creates
- // ambiguity around whether STL use is safe in a particular component and implicitly brings in
- // a long list of headers (including <new>) which can create further ambiguity around throwing new
- // support (some routines pulled in may expect it). Secondarily, pulling in these headers also has
- // the potential to create naming conflicts or other implied dependencies.
- //
- // To promote the use of these core language concepts outside of STL-based binaries, this file is
- // selectively pulling those concepts *directly* from corresponding STL headers. The corresponding
- // "std::" namespace STL functions and types should be preferred over these in code that is bound to
- // STL. The implementation and naming of all functions are taken directly from STL, instead using
- // "wistd" (Windows Implementation std) as the namespace.
- //
- // Routines in this namespace should always be considered a reflection of the *current* STL implementation
- // of those routines. Updates from STL should be taken, but no "bugs" should be fixed here.
- //
- // New, exception-based code should not use this namespace, but instead should prefer the std:: implementation.
- // Only code that is not exception-based and libraries that expect to be utilized across both exception
- // and non-exception based code should utilize this functionality.
- #ifndef _WISTD_FUNCTIONAL_H_
- #define _WISTD_FUNCTIONAL_H_
- // DO NOT add *any* additional includes to this file -- there should be no dependencies from its usage
- #include "wistd_memory.h"
- #include <intrin.h> // For __fastfail
- #include <new.h> // For placement new
- #if !defined(__WI_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
- #pragma GCC system_header
- #endif
- #pragma warning(push)
- #pragma warning(disable: 4324)
- #pragma warning(disable: 4800)
- /// @cond
- namespace wistd // ("Windows Implementation" std)
- {
- // wistd::function
- //
- // All of the code below is in direct support of wistd::function. This class is identical to std::function
- // with the following exceptions:
- //
- // 1) It never allocates and is safe to use from exception-free code (custom allocators are not supported)
- // 2) It's slightly bigger on the stack (64 bytes, rather than 24 for 32bit)
- // 3) There is an explicit static-assert if a lambda becomes too large to hold in the internal buffer (rather than an allocation)
- template <class _Ret>
- struct __invoke_void_return_wrapper
- {
- #ifndef __WI_LIBCPP_CXX03_LANG
- template <class ..._Args>
- static _Ret __call(_Args&&... __args) {
- return __invoke(wistd::forward<_Args>(__args)...);
- }
- #else
- template <class _Fn>
- static _Ret __call(_Fn __f) {
- return __invoke(__f);
- }
- template <class _Fn, class _A0>
- static _Ret __call(_Fn __f, _A0& __a0) {
- return __invoke(__f, __a0);
- }
- template <class _Fn, class _A0, class _A1>
- static _Ret __call(_Fn __f, _A0& __a0, _A1& __a1) {
- return __invoke(__f, __a0, __a1);
- }
- template <class _Fn, class _A0, class _A1, class _A2>
- static _Ret __call(_Fn __f, _A0& __a0, _A1& __a1, _A2& __a2){
- return __invoke(__f, __a0, __a1, __a2);
- }
- #endif
- };
- template <>
- struct __invoke_void_return_wrapper<void>
- {
- #ifndef __WI_LIBCPP_CXX03_LANG
- template <class ..._Args>
- static void __call(_Args&&... __args) {
- (void)__invoke(wistd::forward<_Args>(__args)...);
- }
- #else
- template <class _Fn>
- static void __call(_Fn __f) {
- __invoke(__f);
- }
- template <class _Fn, class _A0>
- static void __call(_Fn __f, _A0& __a0) {
- __invoke(__f, __a0);
- }
- template <class _Fn, class _A0, class _A1>
- static void __call(_Fn __f, _A0& __a0, _A1& __a1) {
- __invoke(__f, __a0, __a1);
- }
- template <class _Fn, class _A0, class _A1, class _A2>
- static void __call(_Fn __f, _A0& __a0, _A1& __a1, _A2& __a2) {
- __invoke(__f, __a0, __a1, __a2);
- }
- #endif
- };
- ////////////////////////////////////////////////////////////////////////////////
- // FUNCTION
- //==============================================================================
- // bad_function_call
- __WI_LIBCPP_NORETURN inline __WI_LIBCPP_INLINE_VISIBILITY
- void __throw_bad_function_call()
- {
- __fastfail(7); // FAST_FAIL_FATAL_APP_EXIT
- }
- template<class _Fp> class __WI_LIBCPP_TEMPLATE_VIS function; // undefined
- namespace __function
- {
- template<class _Rp>
- struct __maybe_derive_from_unary_function
- {
- };
- template<class _Rp, class _A1>
- struct __maybe_derive_from_unary_function<_Rp(_A1)>
- : public unary_function<_A1, _Rp>
- {
- };
- template<class _Rp>
- struct __maybe_derive_from_binary_function
- {
- };
- template<class _Rp, class _A1, class _A2>
- struct __maybe_derive_from_binary_function<_Rp(_A1, _A2)>
- : public binary_function<_A1, _A2, _Rp>
- {
- };
- template <class _Fp>
- __WI_LIBCPP_INLINE_VISIBILITY
- bool __not_null(_Fp const&) { return true; }
- template <class _Fp>
- __WI_LIBCPP_INLINE_VISIBILITY
- bool __not_null(_Fp* __ptr) { return __ptr; }
- template <class _Ret, class _Class>
- __WI_LIBCPP_INLINE_VISIBILITY
- bool __not_null(_Ret _Class::*__ptr) { return __ptr; }
- template <class _Fp>
- __WI_LIBCPP_INLINE_VISIBILITY
- bool __not_null(function<_Fp> const& __f) { return !!__f; }
- } // namespace __function
- #ifndef __WI_LIBCPP_CXX03_LANG
- namespace __function {
- template<class _Fp> class __base;
- template<class _Rp, class ..._ArgTypes>
- class __base<_Rp(_ArgTypes...)>
- {
- __base(const __base&);
- __base& operator=(const __base&);
- public:
- __WI_LIBCPP_INLINE_VISIBILITY __base() {}
- __WI_LIBCPP_INLINE_VISIBILITY virtual ~__base() {}
- virtual void __clone(__base*) const = 0;
- virtual void __move(__base*) = 0;
- virtual void destroy() WI_NOEXCEPT = 0;
- virtual _Rp operator()(_ArgTypes&& ...) = 0;
- };
- template<class _FD, class _FB> class __func;
- template<class _Fp, class _Rp, class ..._ArgTypes>
- class __func<_Fp, _Rp(_ArgTypes...)>
- : public __base<_Rp(_ArgTypes...)>
- {
- _Fp __f_;
- public:
- __WI_LIBCPP_INLINE_VISIBILITY
- explicit __func(_Fp&& __f)
- : __f_(wistd::move(__f)) {}
- __WI_LIBCPP_INLINE_VISIBILITY
- explicit __func(const _Fp& __f)
- : __f_(__f) {}
- virtual void __clone(__base<_Rp(_ArgTypes...)>*) const;
- virtual void __move(__base<_Rp(_ArgTypes...)>*);
- virtual void destroy() WI_NOEXCEPT;
- virtual _Rp operator()(_ArgTypes&& ... __arg);
- };
- template<class _Fp, class _Rp, class ..._ArgTypes>
- void
- __func<_Fp, _Rp(_ArgTypes...)>::__clone(__base<_Rp(_ArgTypes...)>* __p) const
- {
- ::new (__p) __func(__f_);
- }
- template<class _Fp, class _Rp, class ..._ArgTypes>
- void
- __func<_Fp, _Rp(_ArgTypes...)>::__move(__base<_Rp(_ArgTypes...)>* __p)
- {
- ::new (__p) __func(wistd::move(__f_));
- }
- template<class _Fp, class _Rp, class ..._ArgTypes>
- void
- __func<_Fp, _Rp(_ArgTypes...)>::destroy() WI_NOEXCEPT
- {
- __f_.~_Fp();
- }
- template<class _Fp, class _Rp, class ..._ArgTypes>
- _Rp
- __func<_Fp, _Rp(_ArgTypes...)>::operator()(_ArgTypes&& ... __arg)
- {
- typedef __invoke_void_return_wrapper<_Rp> _Invoker;
- return _Invoker::__call(__f_, wistd::forward<_ArgTypes>(__arg)...);
- }
- // 'wistd::function' is most similar to 'inplace_function' in that it _only_ permits holding function objects
- // that can fit within its internal buffer. Therefore, we expand this size to accommodate space for at least 12
- // pointers (__base vtable takes an additional one).
- constexpr const size_t __buffer_size = 13 * sizeof(void*);
- } // __function
- // NOTE: The extra 'alignas' here is to work around the x86 compiler bug mentioned in
- // https://github.com/microsoft/STL/issues/1533 to force alignment on the stack
- template<class _Rp, class ..._ArgTypes>
- class __WI_LIBCPP_TEMPLATE_VIS __WI_ALIGNAS(typename aligned_storage<__function::__buffer_size>::type)
- function<_Rp(_ArgTypes...)>
- : public __function::__maybe_derive_from_unary_function<_Rp(_ArgTypes...)>,
- public __function::__maybe_derive_from_binary_function<_Rp(_ArgTypes...)>
- {
- using __base = __function::__base<_Rp(_ArgTypes...)>;
- __WI_LIBCPP_SUPPRESS_NONINIT_ANALYSIS
- typename aligned_storage<__function::__buffer_size>::type __buf_;
- __base* __f_;
- __WI_LIBCPP_NO_CFI static __base *__as_base(void *p) {
- return static_cast<__base*>(p);
- }
- template <class _Fp, bool>
- struct __callable_imp
- {
- static const bool value = is_same<void, _Rp>::value ||
- is_convertible<typename __invoke_of<_Fp&, _ArgTypes...>::type,
- _Rp>::value;
- };
- template <class _Fp>
- struct __callable_imp<_Fp, false>
- {
- static constexpr bool value = false;
- };
- template <class _Fp>
- struct __callable
- {
- static const bool value = __callable_imp<_Fp, __lazy_and<
- integral_constant<bool, !is_same<__uncvref_t<_Fp>, function>::value>,
- __invokable<_Fp&, _ArgTypes...>
- >::value>::value;
- };
- template <class _Fp>
- using _EnableIfCallable = typename enable_if<__callable<_Fp>::value>::type;
- public:
- using result_type = _Rp;
- // construct/copy/destroy:
- __WI_LIBCPP_INLINE_VISIBILITY __WI_LIBCPP_SUPPRESS_NONINIT_ANALYSIS
- function() WI_NOEXCEPT : __f_(0) {}
- __WI_LIBCPP_INLINE_VISIBILITY
- function(nullptr_t) WI_NOEXCEPT : __f_(0) {}
- function(const function&);
- function(function&&);
- template<class _Fp, class = _EnableIfCallable<_Fp>>
- function(_Fp);
- function& operator=(const function&);
- function& operator=(function&&);
- function& operator=(nullptr_t) WI_NOEXCEPT;
- template<class _Fp, class = _EnableIfCallable<_Fp>>
- function& operator=(_Fp&&);
- ~function();
- // function modifiers:
- void swap(function&);
- // function capacity:
- __WI_LIBCPP_INLINE_VISIBILITY
- __WI_LIBCPP_EXPLICIT operator bool() const WI_NOEXCEPT {return __f_;}
- // deleted overloads close possible hole in the type system
- template<class _R2, class... _ArgTypes2>
- bool operator==(const function<_R2(_ArgTypes2...)>&) const = delete;
- template<class _R2, class... _ArgTypes2>
- bool operator!=(const function<_R2(_ArgTypes2...)>&) const = delete;
- public:
- // function invocation:
- _Rp operator()(_ArgTypes...) const;
- // NOTE: type_info is very compiler specific, and on top of that, we're operating in a namespace other than
- // 'std' so all functions requiring RTTI have been removed
- };
- template<class _Rp, class ..._ArgTypes>
- __WI_LIBCPP_SUPPRESS_NONINIT_ANALYSIS
- function<_Rp(_ArgTypes...)>::function(const function& __f)
- {
- if (__f.__f_ == nullptr)
- __f_ = 0;
- else
- {
- __f_ = __as_base(&__buf_);
- __f.__f_->__clone(__f_);
- }
- }
- template<class _Rp, class ..._ArgTypes>
- __WI_LIBCPP_SUPPRESS_NONINIT_ANALYSIS __WI_LIBCPP_SUPPRESS_NOEXCEPT_ANALYSIS
- function<_Rp(_ArgTypes...)>::function(function&& __f)
- {
- if (__f.__f_ == nullptr)
- __f_ = 0;
- else
- {
- __f_ = __as_base(&__buf_);
- __f.__f_->__move(__f_);
- __f.__f_->destroy();
- __f.__f_ = 0;
- }
- }
- template<class _Rp, class ..._ArgTypes>
- template <class _Fp, class>
- __WI_LIBCPP_SUPPRESS_NONINIT_ANALYSIS
- function<_Rp(_ArgTypes...)>::function(_Fp __f)
- : __f_(nullptr)
- {
- if (__function::__not_null(__f))
- {
- typedef __function::__func<_Fp, _Rp(_ArgTypes...)> _FF;
- static_assert(sizeof(_FF) <= sizeof(__buf_),
- "The sizeof(wistd::function) has grown too large for the reserved buffer (12 pointers). Refactor to reduce size of the capture.");
- __f_ = ::new(static_cast<void*>(&__buf_)) _FF(wistd::move(__f));
- }
- }
- template<class _Rp, class ..._ArgTypes>
- function<_Rp(_ArgTypes...)>&
- function<_Rp(_ArgTypes...)>::operator=(const function& __f)
- {
- *this = nullptr;
- if (__f.__f_)
- {
- __f_ = __as_base(&__buf_);
- __f.__f_->__clone(__f_);
- }
- return *this;
- }
- template<class _Rp, class ..._ArgTypes>
- function<_Rp(_ArgTypes...)>&
- function<_Rp(_ArgTypes...)>::operator=(function&& __f)
- {
- *this = nullptr;
- if (__f.__f_)
- {
- __f_ = __as_base(&__buf_);
- __f.__f_->__move(__f_);
- __f.__f_->destroy();
- __f.__f_ = 0;
- }
- return *this;
- }
- template<class _Rp, class ..._ArgTypes>
- function<_Rp(_ArgTypes...)>&
- function<_Rp(_ArgTypes...)>::operator=(nullptr_t) WI_NOEXCEPT
- {
- __base* __t = __f_;
- __f_ = 0;
- if (__t)
- __t->destroy();
- return *this;
- }
- template<class _Rp, class ..._ArgTypes>
- template <class _Fp, class>
- function<_Rp(_ArgTypes...)>&
- function<_Rp(_ArgTypes...)>::operator=(_Fp&& __f)
- {
- *this = nullptr;
- if (__function::__not_null(__f))
- {
- typedef __function::__func<typename decay<_Fp>::type, _Rp(_ArgTypes...)> _FF;
- static_assert(sizeof(_FF) <= sizeof(__buf_),
- "The sizeof(wistd::function) has grown too large for the reserved buffer (12 pointers). Refactor to reduce size of the capture.");
- __f_ = ::new(static_cast<void*>(&__buf_)) _FF(wistd::move(__f));
- }
- return *this;
- }
- template<class _Rp, class ..._ArgTypes>
- function<_Rp(_ArgTypes...)>::~function()
- {
- if (__f_)
- __f_->destroy();
- }
- template<class _Rp, class ..._ArgTypes>
- void
- function<_Rp(_ArgTypes...)>::swap(function& __f)
- {
- if (wistd::addressof(__f) == this)
- return;
- if (__f_ && __f.__f_)
- {
- typename aligned_storage<sizeof(__buf_)>::type __tempbuf;
- __base* __t = __as_base(&__tempbuf);
- __f_->__move(__t);
- __f_->destroy();
- __f_ = 0;
- __f.__f_->__move(__as_base(&__buf_));
- __f.__f_->destroy();
- __f.__f_ = 0;
- __f_ = __as_base(&__buf_);
- __t->__move(__as_base(&__f.__buf_));
- __t->destroy();
- __f.__f_ = __as_base(&__f.__buf_);
- }
- else if (__f_)
- {
- __f_->__move(__as_base(&__f.__buf_));
- __f_->destroy();
- __f_ = 0;
- __f.__f_ = __as_base(&__f.__buf_);
- }
- else if (__f.__f_)
- {
- __f.__f_->__move(__as_base(&__buf_));
- __f.__f_->destroy();
- __f.__f_ = 0;
- __f_ = __as_base(&__buf_);
- }
- }
- template<class _Rp, class ..._ArgTypes>
- _Rp
- function<_Rp(_ArgTypes...)>::operator()(_ArgTypes... __arg) const
- {
- if (__f_ == nullptr)
- __throw_bad_function_call();
- return (*__f_)(wistd::forward<_ArgTypes>(__arg)...);
- }
- template <class _Rp, class... _ArgTypes>
- inline __WI_LIBCPP_INLINE_VISIBILITY
- bool
- operator==(const function<_Rp(_ArgTypes...)>& __f, nullptr_t) WI_NOEXCEPT {return !__f;}
- template <class _Rp, class... _ArgTypes>
- inline __WI_LIBCPP_INLINE_VISIBILITY
- bool
- operator==(nullptr_t, const function<_Rp(_ArgTypes...)>& __f) WI_NOEXCEPT {return !__f;}
- template <class _Rp, class... _ArgTypes>
- inline __WI_LIBCPP_INLINE_VISIBILITY
- bool
- operator!=(const function<_Rp(_ArgTypes...)>& __f, nullptr_t) WI_NOEXCEPT {return (bool)__f;}
- template <class _Rp, class... _ArgTypes>
- inline __WI_LIBCPP_INLINE_VISIBILITY
- bool
- operator!=(nullptr_t, const function<_Rp(_ArgTypes...)>& __f) WI_NOEXCEPT {return (bool)__f;}
- // Provide both 'swap_wil' and 'swap' since we now have two ADL scenarios that we need to work
- template <class _Rp, class... _ArgTypes>
- inline __WI_LIBCPP_INLINE_VISIBILITY
- void
- swap(function<_Rp(_ArgTypes...)>& __x, function<_Rp(_ArgTypes...)>& __y)
- {return __x.swap(__y);}
- template <class _Rp, class... _ArgTypes>
- inline __WI_LIBCPP_INLINE_VISIBILITY
- void
- swap_wil(function<_Rp(_ArgTypes...)>& __x, function<_Rp(_ArgTypes...)>& __y)
- {return __x.swap(__y);}
- // std::invoke
- template <class _Fn, class ..._Args>
- typename __invoke_of<_Fn, _Args...>::type
- invoke(_Fn&& __f, _Args&&... __args)
- __WI_NOEXCEPT_((__nothrow_invokable<_Fn, _Args...>::value))
- {
- return wistd::__invoke(wistd::forward<_Fn>(__f), wistd::forward<_Args>(__args)...);
- }
- #else // __WI_LIBCPP_CXX03_LANG
- #error wistd::function and wistd::invoke not implemented for pre-C++11
- #endif
- }
- /// @endcond
- #pragma warning(pop)
- #endif // _WISTD_FUNCTIONAL_H_
|