[DEV] fork on etk::Function

This commit is contained in:
Edouard DUPIN 2017-09-02 23:20:24 +02:00
parent 4abbcad222
commit 69b8f326d4
5 changed files with 94 additions and 52 deletions

View File

@ -5,12 +5,14 @@
*/ */
#include <etk/types.hpp> #include <etk/types.hpp>
//#include <ememory/UniquePtr.hpp>
#pragma once #pragma once
namespace etk { namespace etk {
template <typename ETK_TYPE_FUNCTION> template <typename ETK_TYPE_FUNCTION>
class Function; class Function;
template <typename ETK_TYPE_FUNCTION_RETURN, typename... ETK_TYPE_FUNCTION_ARGS> template <typename ETK_TYPE_FUNCTION_RETURN, typename... ETK_TYPE_FUNCTION_ARGS>
class Function<ETK_TYPE_FUNCTION_RETURN(ETK_TYPE_FUNCTION_ARGS...)> { class Function<ETK_TYPE_FUNCTION_RETURN(ETK_TYPE_FUNCTION_ARGS...)> {
// function pointer types for the type-erasure behaviors // function pointer types for the type-erasure behaviors
@ -18,24 +20,23 @@ namespace etk {
typedef ETK_TYPE_FUNCTION_RETURN (*invoke_fn_t)(char*, ETK_TYPE_FUNCTION_ARGS&&...); typedef ETK_TYPE_FUNCTION_RETURN (*invoke_fn_t)(char*, ETK_TYPE_FUNCTION_ARGS&&...);
typedef void (*construct_fn_t)(char*, char*); typedef void (*construct_fn_t)(char*, char*);
typedef void (*destroy_fn_t)(char*); typedef void (*destroy_fn_t)(char*);
// type-aware generic functions for invoking // type-aware generic functions for invoking
// the specialization of these functions won't be capable with // the specialization of these functions won't be capable with
// the above function pointer types, so we need some cast // the above function pointer types, so we need some cast
template <typename ETK_TYPE_FUNCTION_FUNCTOR> template <typename ETK_TYPE_FUNCTION_FUNCTOR>
static ETK_TYPE_FUNCTION_RETURN invoke_fn(ETK_TYPE_FUNCTION_FUNCTOR* _functor, static ETK_TYPE_FUNCTION_RETURN invoke_fn(ETK_TYPE_FUNCTION_FUNCTOR* _functor,
ETK_TYPE_FUNCTION_ARGS&&... _args) { ETK_TYPE_FUNCTION_ARGS&&... _args) {
return (*_functor)(std::forward<ETK_TYPE_FUNCTION_ARGS>(_args)...); return (*_functor)(etk::forward<ETK_TYPE_FUNCTION_ARGS>(_args)...);
} }
template <typename ETK_TYPE_FUNCTION_FUNCTOR> template <typename ETK_TYPE_FUNCTION_FUNCTOR>
static void construct_fn(ETK_TYPE_FUNCTION_FUNCTOR* _constructDestination, static void construct_fn(ETK_TYPE_FUNCTION_FUNCTOR* _constructDestination,
ETK_TYPE_FUNCTION_FUNCTOR* _constructSource) { ETK_TYPE_FUNCTION_FUNCTOR* _constructSource) {
// the functor type must be copy-constructible // the functor type must be copy-constructible
new (_constructDestination) Functor(*_constructSource); new (_constructDestination) Function(*_constructSource);
} }
template <typename ETK_TYPE_FUNCTION_FUNCTOR> template <typename ETK_TYPE_FUNCTION_FUNCTOR>
static void destroy_fn(ETK_TYPE_FUNCTION_FUNCTOR* _functor) { static void destroy_fn(ETK_TYPE_FUNCTION_FUNCTOR* _functor) {
_functor->~Functor(); _functor->~Function();
} }
// These pointers are storing behaviors. // These pointers are storing behaviors.
invoke_fn_t invoke_f; invoke_fn_t invoke_f;
@ -43,10 +44,10 @@ namespace etk {
destroy_fn_t destroy_f; destroy_fn_t destroy_f;
// Erase the type of any functor and store it into a char* // Erase the type of any functor and store it into a char*
// so the storage size should be obtained as well // so the storage size should be obtained as well
std::unique_ptr<char[]> m_dataPointer; char* m_dataPointer;
size_t m_dataSize; size_t m_dataSize;
public: public:
function() Function()
: invoke_f(nullptr) : invoke_f(nullptr)
, construct_f(nullptr) , construct_f(nullptr)
, destroy_f(nullptr) , destroy_f(nullptr)
@ -56,42 +57,45 @@ namespace etk {
// construct from any functor type // construct from any functor type
template <typename ETK_TYPE_FUNCTION_FUNCTOR> template <typename ETK_TYPE_FUNCTION_FUNCTOR>
Function(ETK_TYPE_FUNCTION_FUNCTOR _funtor) Function(ETK_TYPE_FUNCTION_FUNCTOR _functor):
// specialize functions and erase their type info by casting // specialize functions and erase their type info by casting
: invoke_f(reinterpret_cast<invoke_fn_t>(invoke_fn<ETK_TYPE_FUNCTION_FUNCTOR>)) invoke_f(reinterpret_cast<invoke_fn_t>(invoke_fn<ETK_TYPE_FUNCTION_FUNCTOR>)),
, construct_f(reinterpret_cast<construct_fn_t>(construct_fn<ETK_TYPE_FUNCTION_FUNCTOR>)) construct_f(reinterpret_cast<construct_fn_t>(construct_fn<ETK_TYPE_FUNCTION_FUNCTOR>)),
, destroy_f(reinterpret_cast<destroy_fn_t>(destroy_fn<ETK_TYPE_FUNCTION_FUNCTOR>)) destroy_f(reinterpret_cast<destroy_fn_t>(destroy_fn<ETK_TYPE_FUNCTION_FUNCTOR>)),
, m_dataPointer(new char[sizeof(ETK_TYPE_FUNCTION_FUNCTOR)]) m_dataPointer(new char[sizeof(ETK_TYPE_FUNCTION_FUNCTOR)]),
, m_dataSize(sizeof(ETK_TYPE_FUNCTION_FUNCTOR)) m_dataSize(sizeof(ETK_TYPE_FUNCTION_FUNCTOR)) {
{
// copy the functor to internal storage // copy the functor to internal storage
this->construct_f(this->m_dataPointer.get(), reinterpret_cast<char*>(&_functor)); construct_f(m_dataPointer, reinterpret_cast<char*>(&_functor));
} }
// copy constructor // copy constructor
Function(Function const& rhs): Function(Function const& _obj):
invoke_f(rhs.invoke_f), invoke_f(_obj.invoke_f),
construct_f(rhs.construct_f) construct_f(_obj.construct_f),
destroy_f(rhs.destroy_f), destroy_f(_obj.destroy_f),
dataSize(rhs.dataSize) { m_dataSize(_obj.m_dataSize) {
if (this->invoke_f) { if (invoke_f) {
// when the source is not a null function, copy its internal functor // when the source is not a null function, copy its internal functor
this->m_dataPointer.reset(new char[this->m_dataSize]); delete(m_dataPointer);
this->construct_f(this->m_dataPointer.get(), rhs.m_dataPointer.get()); m_dataPointer = new char[m_dataSize];
construct_f(m_dataPointer, _obj.m_dataPointer);
} }
} }
~Function() { ~Function() {
if (m_dataPointer != nullptr) { if (m_dataPointer != nullptr) {
this->destroy_f(this->m_dataPointer.get()); destroy_f(m_dataPointer);
delete m_dataPointer;
} }
} }
// other constructors, from nullptr, from function pointers // other constructors, from nullptr, from function pointers
ETK_TYPE_FUNCTION_RETURN operator()(ETK_TYPE_FUNCTION_ARGS&&... _args) { ETK_TYPE_FUNCTION_RETURN operator()(ETK_TYPE_FUNCTION_ARGS&&... _args) {
return this->invoke_f(this->m_dataPointer.get(), return invoke_f(m_dataPointer,
std::forward<ETK_TYPE_FUNCTION_ARGS>(_args)...); etk::forward<ETK_TYPE_FUNCTION_ARGS>(_args)...);
}
bool operator!= (nullptr_t) const {
return m_dataPointer != nullptr;
}
bool operator== (nullptr_t) const {
return m_dataPointer == nullptr;
} }
}; };
} }

View File

@ -8,25 +8,62 @@
namespace etk { namespace etk {
template<class ETK_MOVE_TYPE> template<class ETK_MOVE_TYPE>
struct _Remove_reference { struct RemoveReference {
// remove reference // remove reference
typedef ETK_MOVE_TYPE m_type; typedef ETK_MOVE_TYPE m_type;
}; };
template<class ETK_MOVE_TYPE> template<class ETK_MOVE_TYPE>
struct _Remove_reference<ETK_MOVE_TYPE&> { struct RemoveReference<ETK_MOVE_TYPE&> {
// remove reference // remove reference
typedef ETK_MOVE_TYPE m_type; typedef ETK_MOVE_TYPE m_type;
}; };
template<class ETK_MOVE_TYPE> template<class ETK_MOVE_TYPE>
struct _Remove_reference<ETK_MOVE_TYPE&&> { struct RemoveReference<ETK_MOVE_TYPE&&> {
// remove rvalue reference // remove rvalue reference
typedef ETK_MOVE_TYPE m_type; typedef ETK_MOVE_TYPE m_type;
}; };
template<class ETK_MOVE_TYPE> inline template<class ETK_MOVE_TYPE> inline
typename etk::_Remove_reference<ETK_MOVE_TYPE>::m_type&& move(ETK_MOVE_TYPE&& _obj) { typename etk::RemoveReference<ETK_MOVE_TYPE>::m_type&& move(ETK_MOVE_TYPE&& _obj) {
// forward _Arg as movable // forward _Arg as movable
return ((typename etk::_Remove_reference<ETK_MOVE_TYPE>::m_type&&)_obj); return ((typename etk::RemoveReference<ETK_MOVE_TYPE>::m_type&&)_obj);
}
template<typename ETK_SWAP_TYPE>
inline void swap(ETK_SWAP_TYPE& _obj1, ETK_SWAP_TYPE& _obj2) {
ETK_SWAP_TYPE tmp = etk::move(_obj1);
_obj1 = etk::move(_obj2);
_obj2 = etk::move(tmp);
}
template<class ETK_TYPE, ETK_TYPE v>
struct integralConstant {
static constexpr ETK_TYPE value = v;
typedef ETK_TYPE typeValue;
// using injected-class-name
typedef integralConstant type;
constexpr operator typeValue() const noexcept {
return value;
}
constexpr typeValue operator()() const noexcept {
return value;
}
};
typedef etk::integralConstant<bool, true> typeTrue;
typedef etk::integralConstant<bool, false> typeFalse;
template<class ETK_TYPE>
struct isLeftValueReference : etk::typeFalse {};
template<class ETK_TYPE>
struct isLeftValueReference<ETK_TYPE&> : etk::typeTrue {};
template <class ETK_FORWARD_TYPE>
inline ETK_FORWARD_TYPE&& forward(typename etk::RemoveReference<ETK_FORWARD_TYPE>::m_type& _obj) noexcept {
return static_cast<ETK_FORWARD_TYPE&&>(_obj);
}
template <class ETK_FORWARD_TYPE>
inline ETK_FORWARD_TYPE&& forward(typename etk::RemoveReference<ETK_FORWARD_TYPE>::m_type&& _obj) noexcept {
static_assert(!etk::isLeftValueReference<ETK_FORWARD_TYPE>::type, "Can not forward an rvalue as an lvalue.");
return static_cast<ETK_FORWARD_TYPE&&>(_obj);
} }
} }

View File

@ -4,15 +4,18 @@
* @license MPL v2.0 (see license file) * @license MPL v2.0 (see license file)
*/ */
#pragma once #pragma once
#include <cstdlib> extern "C" {
#include <cstdio> #include <stdlib.h>
#include <stdarg.h> #include <stdio.h>
#include <cstring> #include <stdarg.h>
#include <cassert> #include <string.h>
// defien type : uintXX_t and intXX_t #include <assert.h>
#define __STDC_LIMIT_MACROS // defien type : uintXX_t and intXX_t
// note in android include the macro of min max are overwitten #define __STDC_LIMIT_MACROS
#include <cstdint> // note in android include the macro of min max are overwitten
#include <stdint.h>
#include <stddef.h>
}
// in case of android error ... // in case of android error ...
#ifdef __TARGET_OS__Android #ifdef __TARGET_OS__Android
#if __ANDROID_BOARD_ID__ <= 20 #if __ANDROID_BOARD_ID__ <= 20
@ -42,7 +45,9 @@
#endif #endif
#ifndef _WIN32 #ifndef _WIN32
#include <cmath> extern "C" {
#include <math.h>
}
#ifndef _MATH_H_MATHDEF #ifndef _MATH_H_MATHDEF
//! @brief Generate a basic type for floating point unit selection (not finished) //! @brief Generate a basic type for floating point unit selection (not finished)
using float_t = float; using float_t = float;

View File

@ -8,11 +8,6 @@
#include <etk/types.hpp> #include <etk/types.hpp>
#include <etk/String.hpp> #include <etk/String.hpp>
#include <etk/Vector.hpp> #include <etk/Vector.hpp>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <chrono>
#include <etk/stdTools.hpp> #include <etk/stdTools.hpp>
namespace etk { namespace etk {

View File

@ -33,6 +33,7 @@ def configure(target, my_module):
'etk/utf8.cpp', 'etk/utf8.cpp',
'etk/stdTools.cpp', 'etk/stdTools.cpp',
'etk/Stream.cpp', 'etk/Stream.cpp',
'etk/Function.cpp',
]) ])
my_module.add_header_file([ my_module.add_header_file([
@ -47,6 +48,7 @@ def configure(target, my_module):
'etk/Pair.hpp', 'etk/Pair.hpp',
'etk/Map.hpp', 'etk/Map.hpp',
'etk/move.hpp', 'etk/move.hpp',
'etk/Function.hpp',
]) ])
# build in C++ mode # build in C++ mode
@ -56,7 +58,6 @@ def configure(target, my_module):
'c', 'c',
'm', 'm',
"pthread", "pthread",
"cxx",
]) ])
if "Android" in target.get_type(): if "Android" in target.get_type():