I've been reading a tutorial by Ben Hoffman (https://benhoffman.tech/cpp/general/2018/11/13/cpp-job-system.html)
I've had a go at bashing together a version of the Job/Worker system he has, but instead of using void*
for arguments then casting to a known struct, I've been trying to use variadic arguments. The idea is, a job takes in a "parent" to perform a method on, the function pointer to said method, and an Args...
for the argument(s). However, I get an internal compiler error if I try to build. Here is the job class:
template <class T, typename... Args>
struct JobMemberFunc : IJob
{
JobMemberFunc(T* aParent, void (T::* f)(Args...), Args... Args)
{
parentObj = aParent;
func_ptr = f;
saved_args = ::std::make_tuple (::std::move(Args)...);
}
virtual bool invoke() override
{
if (!parentObj) { return false; }
(parentObj->*func_ptr)(::std::move(saved_args));
return true;
}
/** the object to invoke the function pointer on */
T* parentObj;
/** The function pointer to call when we invoke this function */
void (T::* func_ptr)(Args...);
::std::tuple<Args...> saved_args;
};
struct CpuJob
{
IJob* jobPtr = nullptr;
};
Then there's the AddJob method, where the internal compiler error is actually happening.
template <typename T, typename... Args>
void AddJob(T* aParent, void(T::* func_ptr)(Args...), Args... args)
{//This curly bracket is where the internal compiler error happens
CpuJob aJob = {};
JobMemberFunc<T, Args...>* jobPtr = new JobMemberFunc<T, Args...>(aParent, func_ptr,
std::forward<Args>(args)...);
aJob.jobPtr = jobPtr;
locklessReadyQueue.enqueue(aJob);
}
More than happy to be told this is a bad/wrong way of trying to do it anyway. I have thought about doing away with it and having a standardized argument list or doing something polymorphic but I really wanna make this work so I can literally ask the job system to do anything I like.
Thanks!