[DEV] function
This commit is contained in:
parent
628146c380
commit
4abbcad222
137
etk/Function.hpp
137
etk/Function.hpp
@ -9,27 +9,120 @@
|
||||
#pragma once
|
||||
|
||||
namespace etk {
|
||||
/**
|
||||
* @brief Generic Thread interface (OS independent)
|
||||
*/
|
||||
template<class ETK_TYPE_FUNCTION>
|
||||
class Function {
|
||||
private:
|
||||
#ifdef __TARGET_OS__Windows
|
||||
|
||||
#else
|
||||
pthread_mutex_t m_thread;
|
||||
#endif
|
||||
uint32_t m_uid; //!< unique id of the thread
|
||||
etk::String m_name; //!< Name of the thread (do not get it on the system ==> more portable)
|
||||
etk::Function<void()> m_function; //!< Function to call every cycle of the thead running
|
||||
public:
|
||||
Thread(etk::Function<void()>&& _call, const std::string& _name);
|
||||
~Thread();
|
||||
void join();
|
||||
bool detach();
|
||||
void setName(const std::string& _name);
|
||||
const std::string& setName() const;
|
||||
uint32_t getIdentifier() const;
|
||||
template <typename ETK_TYPE_FUNCTION>
|
||||
class Function;
|
||||
template <typename ETK_TYPE_FUNCTION_RETURN, typename... ETK_TYPE_FUNCTION_ARGS>
|
||||
class Function<ETK_TYPE_FUNCTION_RETURN(ETK_TYPE_FUNCTION_ARGS...)> {
|
||||
// function pointer types for the type-erasure behaviors
|
||||
// all these char* parameters are actually casted from some functor type
|
||||
typedef ETK_TYPE_FUNCTION_RETURN (*invoke_fn_t)(char*, ETK_TYPE_FUNCTION_ARGS&&...);
|
||||
typedef void (*construct_fn_t)(char*, char*);
|
||||
typedef void (*destroy_fn_t)(char*);
|
||||
|
||||
// type-aware generic functions for invoking
|
||||
// the specialization of these functions won't be capable with
|
||||
// the above function pointer types, so we need some cast
|
||||
template <typename ETK_TYPE_FUNCTION_FUNCTOR>
|
||||
static ETK_TYPE_FUNCTION_RETURN invoke_fn(ETK_TYPE_FUNCTION_FUNCTOR* _functor,
|
||||
ETK_TYPE_FUNCTION_ARGS&&... _args) {
|
||||
return (*_functor)(std::forward<ETK_TYPE_FUNCTION_ARGS>(_args)...);
|
||||
}
|
||||
template <typename ETK_TYPE_FUNCTION_FUNCTOR>
|
||||
static void construct_fn(ETK_TYPE_FUNCTION_FUNCTOR* _constructDestination,
|
||||
ETK_TYPE_FUNCTION_FUNCTOR* _constructSource) {
|
||||
// the functor type must be copy-constructible
|
||||
new (_constructDestination) Functor(*_constructSource);
|
||||
}
|
||||
template <typename ETK_TYPE_FUNCTION_FUNCTOR>
|
||||
static void destroy_fn(ETK_TYPE_FUNCTION_FUNCTOR* _functor) {
|
||||
_functor->~Functor();
|
||||
}
|
||||
// These pointers are storing behaviors.
|
||||
invoke_fn_t invoke_f;
|
||||
construct_fn_t construct_f;
|
||||
destroy_fn_t destroy_f;
|
||||
// Erase the type of any functor and store it into a char*
|
||||
// so the storage size should be obtained as well
|
||||
std::unique_ptr<char[]> m_dataPointer;
|
||||
size_t m_dataSize;
|
||||
public:
|
||||
function()
|
||||
: invoke_f(nullptr)
|
||||
, construct_f(nullptr)
|
||||
, destroy_f(nullptr)
|
||||
, m_dataPointer(nullptr)
|
||||
, m_dataSize(0)
|
||||
{}
|
||||
|
||||
// construct from any functor type
|
||||
template <typename ETK_TYPE_FUNCTION_FUNCTOR>
|
||||
Function(ETK_TYPE_FUNCTION_FUNCTOR _funtor)
|
||||
// specialize functions and erase their type info by casting
|
||||
: 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>))
|
||||
, destroy_f(reinterpret_cast<destroy_fn_t>(destroy_fn<ETK_TYPE_FUNCTION_FUNCTOR>))
|
||||
, m_dataPointer(new char[sizeof(ETK_TYPE_FUNCTION_FUNCTOR)])
|
||||
, m_dataSize(sizeof(ETK_TYPE_FUNCTION_FUNCTOR))
|
||||
{
|
||||
// copy the functor to internal storage
|
||||
this->construct_f(this->m_dataPointer.get(), reinterpret_cast<char*>(&_functor));
|
||||
}
|
||||
|
||||
// copy constructor
|
||||
Function(Function const& rhs):
|
||||
invoke_f(rhs.invoke_f),
|
||||
construct_f(rhs.construct_f)
|
||||
destroy_f(rhs.destroy_f),
|
||||
dataSize(rhs.dataSize) {
|
||||
if (this->invoke_f) {
|
||||
// when the source is not a null function, copy its internal functor
|
||||
this->m_dataPointer.reset(new char[this->m_dataSize]);
|
||||
this->construct_f(this->m_dataPointer.get(), rhs.m_dataPointer.get());
|
||||
}
|
||||
}
|
||||
|
||||
~Function() {
|
||||
if (m_dataPointer != nullptr) {
|
||||
this->destroy_f(this->m_dataPointer.get());
|
||||
}
|
||||
}
|
||||
|
||||
// other constructors, from nullptr, from function pointers
|
||||
|
||||
ETK_TYPE_FUNCTION_RETURN operator()(ETK_TYPE_FUNCTION_ARGS&&... _args) {
|
||||
return this->invoke_f(this->m_dataPointer.get(),
|
||||
std::forward<ETK_TYPE_FUNCTION_ARGS>(_args)...);
|
||||
}
|
||||
};
|
||||
}
|
||||
/*
|
||||
// examples
|
||||
int main()
|
||||
{
|
||||
int i = 0;
|
||||
auto fn = [i](etk::String const& s) mutable
|
||||
{
|
||||
std::cout << ++i << ". " << s << std::endl;
|
||||
};
|
||||
fn("first"); // 1. first
|
||||
fn("second"); // 2. second
|
||||
|
||||
// construct from lambda
|
||||
::function<void(std::string const&)> f(fn);
|
||||
f("third"); // 3. third
|
||||
|
||||
// copy from another function
|
||||
::function<void(std::string const&)> g(f);
|
||||
f("forth - f"); // 4. forth - f
|
||||
g("forth - g"); // 4. forth - g
|
||||
|
||||
// capture and copy non-trivial types like std::string
|
||||
std::string x("xxxx");
|
||||
::function<void()> h([x]() { std::cout << x << std::endl; });
|
||||
h();
|
||||
|
||||
::function<void()> k(h);
|
||||
k();
|
||||
return 0;
|
||||
}
|
||||
*/
|
@ -324,7 +324,9 @@ const etk::String::Iterator etk::String::end() const {
|
||||
|
||||
void etk::String::resize(size_t _newSize, char _value) {
|
||||
size_t oldSize = m_data.size();
|
||||
m_data[m_data.size()-1] = _value;
|
||||
if (oldSize != 0) {
|
||||
m_data[m_data.size()-1] = _value;
|
||||
}
|
||||
m_data.resize(_newSize + 1, _value);
|
||||
// in all case ==> we have the last element that is '\0'
|
||||
m_data[_newSize] = '\0';
|
||||
|
@ -190,7 +190,6 @@ namespace etk {
|
||||
* @return the reference on the current Element
|
||||
*/
|
||||
ETK_VECTOR_TYPE* operator-> () const {
|
||||
//TK_CHECK_INOUT(m_current < m_vector->size());
|
||||
return &m_vector->get(m_current);
|
||||
}
|
||||
/**
|
||||
@ -198,7 +197,6 @@ namespace etk {
|
||||
* @return the reference on the current Element
|
||||
*/
|
||||
ETK_VECTOR_TYPE& operator* () const {
|
||||
//TK_CHECK_INOUT(m_current < m_vector->size());
|
||||
return m_vector->get(m_current);
|
||||
}
|
||||
private:
|
||||
@ -228,15 +226,13 @@ namespace etk {
|
||||
* @brief Re-copy constructor (copy all needed data)
|
||||
* @param[in] _obj Vector that might be copy
|
||||
*/
|
||||
Vector(const etk::Vector<ETK_VECTOR_TYPE>& _obj) {
|
||||
m_allocated = _obj.m_allocated;
|
||||
m_size = _obj.m_size;
|
||||
m_data = nullptr;
|
||||
//TK_DEBUG("USE Specific vector allocator ... Evb.m_size=" << Evb.m_size << " Evb.m_increment=" << Evb.m_increment);
|
||||
Vector(const etk::Vector<ETK_VECTOR_TYPE>& _obj):
|
||||
m_data(nullptr),
|
||||
m_size(_obj.m_size),
|
||||
m_allocated(_obj.m_allocated) {
|
||||
// allocate all same data
|
||||
m_data = new ETK_VECTOR_TYPE[m_allocated];
|
||||
if (m_data == nullptr) {
|
||||
//TK_CRITICAL("Vector : Error in data allocation ... might nor work correctly anymore");
|
||||
return;
|
||||
}
|
||||
// Copy all data ...
|
||||
@ -245,6 +241,12 @@ namespace etk {
|
||||
m_data[iii] = _obj.m_data[iii];
|
||||
}
|
||||
}
|
||||
Vector(const etk::Vector<ETK_VECTOR_TYPE>&& _obj):
|
||||
m_data(etk::move(_obj.m_data)),
|
||||
m_size(etk::move(_obj.m_size)),
|
||||
m_allocated(etk::move(_obj.m_allocated)) {
|
||||
|
||||
}
|
||||
/**
|
||||
* @brief Destructor of the current Class
|
||||
*/
|
||||
@ -280,7 +282,6 @@ namespace etk {
|
||||
* @return reference on the current re-copy vector
|
||||
*/
|
||||
Vector& operator=(const etk::Vector<ETK_VECTOR_TYPE> & _obj) {
|
||||
//TK_DEBUG("USE RECOPY vector ... Evb.m_size=" << Evb.m_size << " Evb.m_increment=" << Evb.m_increment);
|
||||
if (this != &_obj) {
|
||||
if (m_data != nullptr) {
|
||||
delete[] m_data;
|
||||
@ -292,12 +293,11 @@ namespace etk {
|
||||
// allocate all same data
|
||||
m_data = new ETK_VECTOR_TYPE[m_allocated];
|
||||
if (m_data == nullptr) {
|
||||
//TK_CRITICAL("Vector : Error in data allocation ... might nor work correctly anymore");
|
||||
return *this;
|
||||
}
|
||||
for(size_t iii=0; iii<m_allocated; iii++) {
|
||||
// copy operator ...
|
||||
m_data[iii] = _obj.m_data[iii];
|
||||
m_data[iii] = etk::move(_obj.m_data[iii]);
|
||||
}
|
||||
}
|
||||
// Return the current pointer
|
||||
|
@ -28,7 +28,8 @@ def configure(target, my_module):
|
||||
my_module.add_src_file([
|
||||
'test/main.cpp',
|
||||
'test/testColor.cpp',
|
||||
'test/testHash.cpp',
|
||||
'test/testMapUnordered.cpp',
|
||||
'test/testMap.cpp',
|
||||
'test/testMatrix3x3.cpp',
|
||||
'test/testRegExp.cpp',
|
||||
'test/testTransform.cpp',
|
||||
@ -37,7 +38,6 @@ def configure(target, my_module):
|
||||
'test/testFSNode.cpp',
|
||||
'test/testMatrix2x2.cpp',
|
||||
'test/testQuaternion.cpp',
|
||||
'test/testStdShared.cpp',
|
||||
'test/testVector2_f.cpp',
|
||||
'test/testString.cpp',
|
||||
])
|
||||
|
0
test/testFunction.cpp
Normal file
0
test/testFunction.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <etk/Map.hpp>
|
||||
#include <test-debug/debug.hpp>
|
||||
#define NAME "Map"
|
||||
|
||||
TEST(TestEtkMap, Creation) {
|
||||
etk::Map<uint32_t, etk::String> testData(0,true);
|
||||
EXPECT_EQ(testData.size(), 0);
|
||||
}
|
||||
|
||||
TEST(TestEtkMap, add_ordered) {
|
||||
etk::Map<uint32_t, etk::String> testData(0,true);
|
||||
EXPECT_EQ(testData.size(), 0);
|
||||
testData.add(2, "a 2");
|
||||
testData.add(19, "b 19");
|
||||
testData.add(1, "c 1");
|
||||
testData.add(5, "d 5");
|
||||
testData.add(66, "e 66");
|
||||
EXPECT_EQ(testData.size(), 5);
|
||||
EXPECT_EQ(testData[1], "c 1");
|
||||
EXPECT_EQ(testData.getValue(0), "c 1");
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ememory/memory.hpp>
|
||||
#include <test-debug/debug.hpp>
|
||||
#define NAME "Shared_ptr"
|
||||
|
||||
class Example : public ememory::EnableSharedFromThis<Example> {
|
||||
protected:
|
||||
int32_t m_id;
|
||||
public:
|
||||
Example() {
|
||||
static int32_t mid = 0;
|
||||
m_id = mid++;
|
||||
std::cout << "create Example [" << m_id << "]" << std::endl;
|
||||
}
|
||||
~Example() {
|
||||
std::cout << "Remove Example [" << m_id << "]" << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
TEST(TestSTDSharedPtr, testBaseLocal) {
|
||||
Example();
|
||||
}
|
||||
|
||||
TEST(TestSTDSharedPtr, testBaseShared) {
|
||||
ememory::SharedPtr<Example> tmp = ememory::makeShared<Example>();
|
||||
}
|
||||
|
||||
|
||||
TEST(TestSTDSharedPtr, testBaseSharedDouble) {
|
||||
ememory::SharedPtr<Example> tmp = ememory::makeShared<Example>();
|
||||
ememory::SharedPtr<Example> tmp2 = tmp;
|
||||
}
|
||||
/*
|
||||
TEST(TestSTDSharedPtr, testBaseSharedDirectAndShared) {
|
||||
Example tmp;
|
||||
ememory::SharedPtr<Example> tmp2 = ememory::makeShared<tmp>;
|
||||
}
|
||||
*/
|
Loading…
Reference in New Issue
Block a user