patterncppMinor
Function object passing for a task scheduler
Viewed 0 times
schedulerpassingfunctionforobjecttask
Problem
Here is my full implementation of a generic Functor-like class:
```
#ifndef FUNCTIONHPP
#define FUNCTIONHPP
#include "Types.hpp"
#include
#include
BEGIN_NAMESPACE //This is a define in "Types.hpp"
namespace FN_HELPERS
{
template
struct seq
{
};
template
struct gens : gens
{
};
template
struct gens
{
typedef seq type;
};
//Global Function Pointer Return Type Identification
template
struct returnType;
template
struct returnType
{
typedef R type;
};
template
struct returnType
{
typedef R type;
};
};
//A generic functor to pass between threads
class Function
{
public:
Function() {}
virtual ~Function() {}
Function(const Function&) = delete;
void operator=(const Function&) = delete;
virtual void call()=0;
virtual void* returnValue()=0;
};
template
class GlobalFunction : public Function
{
public:
GlobalFunction(F func,Args&&... args) : m_func(func),
m_args(std::forward(args)...)
{
}
virtual ~GlobalFunction()
{
}
GlobalFunction(const GlobalFunction&) = delete;
void operator=(const GlobalFunction&) = delete;
virtual void call()
{
callFunction(typename FN_HELPERS::gens::type());
}
virtual void* returnValue()
{
return static_cast(&m_returnValue);
}
template
void callFunction(FN_HELPERS::seq)
{
m_returnValue = (*m_func)(std::get(m_args) ...);
}
private:
F m_func;
R m_returnValue;
std::tuple m_args;
};
template
class GlobalFunction : public Function
{
public:
GlobalFunction(F func,Args&&... args) : m_func(func),
m_args(std::forward(args)...)
{
}
virtual ~GlobalFunction()
{
}
GlobalFunction(const GlobalFunction&) = delete;
void operator=(const GlobalFunction&) = de
```
#ifndef FUNCTIONHPP
#define FUNCTIONHPP
#include "Types.hpp"
#include
#include
BEGIN_NAMESPACE //This is a define in "Types.hpp"
namespace FN_HELPERS
{
template
struct seq
{
};
template
struct gens : gens
{
};
template
struct gens
{
typedef seq type;
};
//Global Function Pointer Return Type Identification
template
struct returnType;
template
struct returnType
{
typedef R type;
};
template
struct returnType
{
typedef R type;
};
};
//A generic functor to pass between threads
class Function
{
public:
Function() {}
virtual ~Function() {}
Function(const Function&) = delete;
void operator=(const Function&) = delete;
virtual void call()=0;
virtual void* returnValue()=0;
};
template
class GlobalFunction : public Function
{
public:
GlobalFunction(F func,Args&&... args) : m_func(func),
m_args(std::forward(args)...)
{
}
virtual ~GlobalFunction()
{
}
GlobalFunction(const GlobalFunction&) = delete;
void operator=(const GlobalFunction&) = delete;
virtual void call()
{
callFunction(typename FN_HELPERS::gens::type());
}
virtual void* returnValue()
{
return static_cast(&m_returnValue);
}
template
void callFunction(FN_HELPERS::seq)
{
m_returnValue = (*m_func)(std::get(m_args) ...);
}
private:
F m_func;
R m_returnValue;
std::tuple m_args;
};
template
class GlobalFunction : public Function
{
public:
GlobalFunction(F func,Args&&... args) : m_func(func),
m_args(std::forward(args)...)
{
}
virtual ~GlobalFunction()
{
}
GlobalFunction(const GlobalFunction&) = delete;
void operator=(const GlobalFunction&) = de
Solution
Really don't like this.
In the old days (15 years ago) this was used as a trick to help support non conforming compilers that did not have namespace. That's not really relevant now and you use namespace on the next line.
These helper functions look like they are already supported by the standard
Return types from anonymous functions are covered by
Don't see the need to define the default constructor here.
The compiler generated one should work just fine.
But seems like you are re-building the
After all that nice template code:
You now resort to a macro!
Great. But
Also you need to pass the address of f.
A lot of the same problems with the read.
You should check the return value. Use inside a loop to make sure you send it all. You should pass a pointer to
In the old days (15 years ago) this was used as a trick to help support non conforming compilers that did not have namespace. That's not really relevant now and you use namespace on the next line.
BEGIN_NAMESPACE //This is a define in "Types.hpp"
namespace FN_HELPERSThese helper functions look like they are already supported by the standard
std::integer_sequence.template
struct seq;
template
struct gens : gens;
template
struct gens;Return types from anonymous functions are covered by
std::promise and std::future.//Global Function Pointer Return Type Identification
template
struct returnType;
template
struct returnType;
template
struct returnType;Don't see the need to define the default constructor here.
class Function
{
public:
Function() {}
virtual ~Function() {}
Function(const Function&) = delete;
void operator=(const Function&) = delete;
virtual void call()=0;
virtual void* returnValue()=0;
};The compiler generated one should work just fine.
But seems like you are re-building the
std::function class.After all that nice template code:
//Create function object
//F - Function Pointer
#define S_FN(F, ... ) \
_wrapGFn(F, ##__VA_ARGS__)You now resort to a macro!
Great. But
nn_send() has error codes you need to check. You should never use functions like this directly. As they don't guarantee to send all the data first try. This is something that goes in a loop:Also you need to pass the address of f.
&f otherwise you are sending the bytes pointed to by f (after it is cast to void). So that fails. Also your use of C-cast here is horrible. You were using C++ casts before (why change now). Its also un-necessary. All pointers auto convert when used as a void.Function* f = S_FN(&someFunction,someArg);
nn_send(sockfd,(void*)f,sizeof(f),0); //Send itA lot of the same problems with the read.
You should check the return value. Use inside a loop to make sure you send it all. You should pass a pointer to
buf (as you are writing over that pointer). No need for buf to be a void* that just means an extra cast (which again is a C-Cast).void* buf;
nn_recv(sockfd,buf,sizeof(Function*),0);
Function* f = (Function*)buf;
f->call();Code Snippets
BEGIN_NAMESPACE //This is a define in "Types.hpp"
namespace FN_HELPERStemplate<int ...>
struct seq;
template<int N,int ...S>
struct gens : gens<N-1,N-1,S...>;
template<int ...S>
struct gens<0, S...>;//Global Function Pointer Return Type Identification
template <typename R>
struct returnType;
template <typename R, typename ...Args>
struct returnType<R (*)(Args...)>;
template <typename R,typename ...Args>
struct returnType<R (*)(Args...,...)>;class Function
{
public:
Function() {}
virtual ~Function() {}
Function(const Function&) = delete;
void operator=(const Function&) = delete;
virtual void call()=0;
virtual void* returnValue()=0;
};//Create function object
//F - Function Pointer
#define S_FN(F, ... ) \
_wrapGFn(F, ##__VA_ARGS__)Context
StackExchange Code Review Q#54943, answer score: 3
Revisions (0)
No revisions yet.