Store Templated Object in Container - c++

Is it possible to store a templated class like
template <typename rtn, typename arg>
class BufferAccessor {
public:
int ThreadID;
virtual rtn do_work(arg) = 0;
};
BufferAccessor<void,int> access1;
BufferAccessor<int,void> access2;
in the same container like a vector or list
edit:
The purpose for this is I am trying to make a circular buffer where the objects that want to use the buffer need to register with the buffer. The buffer will store a boost::shared_ptr to the accessor objects and generate a callback to there functions that will push or pull data to/from the buffer. The callback will be used in a generic thread worker function that I have created similar to a thread pool with the fact that they need to access a shared memory object. Below is some code I have typed up that might help illustrate what I am trying to do, but it hasn't been compiled it yet and this is also my first time using bind, function, multi-threading
typedef boost::function<BUF_QObj (void)> CallbackT_pro;
typedef boost::function<void (BUF_QObj)> CallbackT_con;
typedef boost::shared_ptr<BufferAccessor> buf_ptr;
// Register the worker object
int register_consumer(BufferAccesser &accessor) {
mRegCons[mNumConsumers] = buf_ptr(accessor);
return ++mNumConsumers;
}
int register_producer(BufferAccesser &accessor) {
mRegPros[mNumProducers] = buf_ptr(accessor);
return ++mNumProducers;
}
// Dispatch consumer threads
for(;x<mNumConsumers; ++x) {
CallBack_Tcon callback_con = boost::bind(&BufferAccessor::do_work, mRegCons[x]);
tw = new boost:thread(boost::bind(&RT_ActiveCircularBuffer::consumerWorker, this, callback_con));
consumers.add(tw);
}
// Dispatch producer threads
for(x=0;x<mNumProducers; ++x) {
CallBack_Tpro callback_pro = boost::bind(&BufferAccessor::do_work, mRegPros[x], _1);
tw = new boost:thread(boost::bind(&RT_ActiveCircularBuffer::producerWorker, this, callback_pro));
producers.add(tw);
}
// Thread Template Workers - Consumer
void consumerWorker(CallbackT_con worker) {
struct BUF_QObj *qData;
while(!mRun)
cond.wait(mLock);
while(!mTerminate) {
// Set interruption point so that thread can be interrupted
boost::thread::interruption_point();
{ // Code Block
boost::mutex::scoped_lock lock(mLock);
if(buf.empty()) {
cond.wait(mLock)
qData = mBuf.front();
mBuf.pop_front(); // remove the front element
} // End Code Block
worker(qData); // Process data
// Sleep that thread for 1 uSec
boost::thread::sleep(boost::posix_time::nanoseconds(1000));
} // End of while loop
}
// Thread Template Workers - Producer
void producerWorker(CallbackT_pro worker) {
struct BUF_QObj *qData;
boost::thread::sleep(boost::posix_time::nanoseconds(1000));
while(!mRun)
cond.wait(mLock);
while(!mTerminate) {
// Set interruption point so that thread can be interrupted
boost::thread::interruption_point();
qData = worker(); // get data to be processed
{ // Code Block
boost::mutex::scoped_lock lock(mLock);
buf.push_back(qData);
cond.notify_one(mLock);
} // End Code Block
// Sleep that thread for 1 uSec
boost::thread::sleep(boost::posix_time::nanoseconds(1000));
} // End of while loop
}

No it's not, because STL containers are homogenous, and access1 and access2 have completely different unrelated types. But you could make the class BufferAccessor non-template one but the do-work member as a template, like this:
class BufferAccessor
{
template<class R, class A>
R doWork(A arg) {...}
};
In this case you could store BufferAccessors in a container, but you can't make a member template function virtual.

Yes, you can use vector<BufferAccessor<void,int> > to store BufferAccessor<void,int> objects and vector<BufferAccessor<int,void> > to store BufferAccessor<int,void> objects.
What you cant do is use same vector to store both BufferAccessor<int,void> and BufferAccessor<void,int> object
The reason it doesnt work is because BufferAccessor<void,int>, and BufferAccessor<int,void> are two different classes
Note: it is possible to use same vector to store both BufferAccessor<int,void> and BufferAccessor<void,int> but you would have to either store them as void * using shared_ptr<void>. Or better yet you can use a boost::variant

Related

Trouble with pointer to templated class method [duplicate]

This question already has answers here:
Using c++ 11 multithreading on non-static member function
(1 answer)
How to pass member function of class to thread?
(2 answers)
Closed 7 months ago.
I was writing code for the following parallel processing task:
A std::vector<T> contains data items that need to be processed
A function process_data<T&> does that processing on such a single data item
In my software I want to do this for different types T, so I wrote a template class:
#include <mutex>
#include <thread>
#include <vector>
// Parallel processing class.
template <class T>
class parallel_processing {
public:
// Do parallel processing for all items in the vector.
void do_parallel_processing(std::vector<T>& items,
void (*item_processor)(T&),
size_t thread_count = 1)
{
// Check if we should do sequential processing after all.
if (thread_count <= 1) {
for (size_t i = 0; i < items.size(); i++)
item_processor(items[i]);
return;
}
// Proceed with parallel processing.
item_processor_ptr = item_processor;
items_ptr = &items;
next_item_index = 0;
// Spawn all threads.
std::vector<std::thread> threads;
for (size_t i = 0; i < thread_count; i++)
threads.push_back(std::thread(item_thread_worker));
// The current thread should also work hard. This has an advantage: calling join()
// (see below) blocks the thread, costing time. Method 'item_thread_worker' however
// only returns if all items are processed and thus all threads must also have
// finished (or are busy with their last item...).
item_thread_worker();
// Wait for all threads to finish and call join on them.
for (auto& this_thread : threads)
this_thread.join();
}
private:
// Get the next index to process.
int get_next_item_index()
{
const std::lock_guard<std::mutex> lock(next_item_index_mutex);
// Check if we're already done.
if (next_item_index >= (int)items_ptr->size())
return -1;
// Next index (first return, then increment).
return next_item_index++;
}
// Thread-worker method for items.
void item_thread_worker()
{
int item_index;
// Keep on processing while not all items are processed.
while ((item_index = get_next_item_index()) >= 0)
item_processor_ptr((*items_ptr)[item_index]);
}
// Properties.
std::mutex next_item_index_mutex; // For thread-safe access to 'next_item_index'.
int next_item_index; // Identifies the next item index to process.
void (*item_processor_ptr)(T& items); // The item processing function.
std::vector<T>* items_ptr; // Pointer to the vector with items to be processed.
};
The idea is simple and worked when it was not yet in a template class but separate functions but then of course could only be coded for a single type T:
A number of threads is started and they all run the same worker method
The workers pick a data item to be processed from the std::vector<T>, and call the function to process the selected item until all items are processed
The compiler (VS2019) complains about the line:
threads.push_back(std::thread(item_thread_worker));
'use & to create a pointer to a member'
So I tried threads.push_back(std::thread(&item_thread_worker)); which gives me the error:
''&': illegal operation on bound member function expression'
So I tried all kind of things: with (), with the class in front &parallel_processing<T>:: or &parallel_processing:: but all I get are different errors...
My knowledge about C++ is clearly not enough to solve this, help is appreciated.
As item_thread_worker is a non-static member function, it needs a object to be called with.
When you create your threads, you don't specify any objects. Those objects (which becomes the this pointer inside the functions) are passed as a hidden "first" argument.
Another point is that to get a pointer to a member function, you must use the pointer-to operator &. Unlike non-member functions, member functions do not decay to pointers to themselves. And you need to use the full scope, with the class-name.
So to create a thread using a non-static member function, that should be called on this object, you need to do std::thread(&parallel_processing::item_thread_worker, this).

c++ thread pool: alternative to std::function for passing functions/lambdas to threads?

I have a thread pool that I use to execute many tiny jobs (millions of jobs, dozens/hundreds of milliseconds each). The jobs are passed in the form of either:
std::bind(&fn, arg1, arg2, arg3...)
or
[&](){fn(arg1, arg2, arg3...);}
with the thread pool taking them like this:
std::queue<std::function<void(void)>> queue;
void addJob(std::function<void(void)> fn)
{
queue.emplace_back(std::move(fn));
}
Pretty standard stuff....except that I've noticed a bottleneck where if jobs execute in a fast enough time (less than a millisecond), the conversion from lambda/binder to std::function in the addJob function actually takes longer than execution of the jobs themselves. After doing some reading, std::function is notoriously slow and so my bottleneck isn't necessarily unexpected.
Is there a faster way of doing this type of thing? I've looked into drop-in std::function replacements but they either weren't compatible with my compiler or weren't faster. I've also looked into "fast delegates" by Don Clugston but they don't seem to allow the passing of arguments along with functions (maybe I don't understand them correctly?).
I'm compiling with VS2015u3, and the functions passed to the jobs are all static, with their arguments being either ints/floats or pointers to other objects.
Have a separate queue for each of the task types - you probably don't have tens of thousands of task types. Each of these can be e.g. a static member of your tasks. Then addJob() is actually the ctor of Task and it's perfectly type-safe.
Then define a compile-time list of your task types and visit it via template metaprogramming (for_each). It'll be way faster as you don't need any virtual call fnptr / std::function<> to achieve this.
This will only work if your tuple code sees all the Task classes (so you can't e.g. add a new descendant of Task to an already running executable by loading the image from disc - hope that's a non-issue).
template<typename D> // CRTP on D
class Task {
public:
// you might want to static_assert at some point that D is in TaskTypeList
Task() : it_(tasks_.end()) {} // call enqueue() in descendant
~Task() {
// add your favorite lock here
if (queued()) {
tasks_.erase(it_);
}
}
bool queued() const { return it_ != tasks_.end(); }
static size_t ExecNext() {
if (!tasks_.empty()) {
// add your favorite lock here
auto&& itTask = tasks_.begin();
tasks_.pop_front();
// release lock
(*itTask)();
itTask->it_ = tasks_.end();
}
return tasks_.size();
}
protected:
void enqueue() const
{
// add your favorite lock here
tasks_.push_back(static_cast<D*>(this));
it_ = tasks_.rbegin();
}
private:
std::list<D*>::iterator it_;
static std::list<D*> tasks_; // you can have one per thread, too - then you don't need locking, but tasks are assigned to threads statically
};
struct MyTask : Task<MyTask> {
MyTask() { enqueue(); } // call enqueue only when the class is ready
void operator()() { /* add task here */ }
// ...
};
struct MyTask2; // etc.
template<typename...>
struct list_ {};
using TaskTypeList = list_<MyTask, MyTask2>;
void thread_pocess(list_<>) {}
template<typename TaskType, typename... TaskTypes>
void thread_pocess(list_<TaskType, TaskTypes...>)
{
TaskType::ExecNext();
thread_process(list_<TaskTypes...>());
}
void thread_process(void*)
{
for (;;) {
thread_process(TaskTypeList());
}
}
There's a lot to tune on this code: different threads should start from different parts of the queue (or one would use a ring, or several queues and either static/dynamic assignment to threads), you'd send it to sleep when there are absolutely no tasks, one could have an enum for the tasks, etc.
Note that this can't be used with arbitrary lambdas: you need to list task types. You need to 'communicate' the lambda type out of the function where you declare it (e.g. by returning `std::make_pair(retval, list_) and sometimes it's not easy. However, you can always convert a lambda to a functor, which is straightforward - just ugly.

Lock-free multiple producer multiple consumer in C++

I have to program a multiple producer-consumer system in C++, but I'm lost trying to put together each part of the model (threads with its correct buffer). The basic functioning of the model is: I have an initial thread that executes a function. This returned results need to be put in an undetermined number of buffers, because each elements that the function proccess is different and it needs to be treated in a single thread. Then, with the data stored in the buffers, another n threads need to get the data of this buffers to do another function, and the return of this need to be put in some buffers again.
At the moment I have got this buffer structure created:
template <typename T>
class buffer {
public:
atomic_buffer(int n);
int bufSize() const noexcept;
bool bufEmpty() const noexcept;
bool full() const noexcept;
~atomic_buffer() = default;
void put(const T & x, bool last) noexcept;
std::pair<bool,T> get() noexcept;
private:
int next_pos(int p) const noexcept;
private:
struct item {
bool last;
T value;
};
const int size_;
std::unique_ptr<item[]> buf_;
alignas(64) std::atomic<int> nextRd_ {0};
alignas(64) std::atomic<int> nextWrt_ {0};
};
I've also created a vectorstructure which stores a collection un buffers, in order to satisfy the undetermined number of threads necessity.
std::vector<std::unique_ptr<locked_buffer<std::pair<int, std::vector<std::vector<unsigned char>>>>>> v1;
for(int i=0; i<n; i++){
v1.push_back(std::unique_ptr<locked_buffer<std::pair<int,std::vector<std::vector<unsigned char>>>>> (new locked_buffer<std::pair<int, std::vector<std::vector<unsigned char>>>>(aux)));
}
Edit:
Without knowing more context, this looks like an application for a standard thread pool. You have different tasks that are enqueued to a synchronized queue (like the buffer class you have there). Each worker thread of the thread pool polls this queue and processes one task each time (by executing a run() method for example). They write the results back into another synchronized queue.
Each worker thread has an own thread-local pair of input and output buffers. They don't need synchronization because they are only accessed from within the owner thread itself.
Edit: Actually, I think this can be simplified a lot: Just use a thread pool and one synchronized queue. The worker threads can enqueue new tasks directly into the queue. Each of your threads in the drawing would correspond to one type of task and implement a common Task interface.
You don't need mutiple buffers. You can use polymorphism and put everything in one buffer.
Edit 2 - Explanation of thread pools:
A thread pool is just a concept. Forget about the pooling aspect, use a fixed number of threads. The main idea is: Instead of having several threads with a specific function, have N threads that can process any kind of task. Where N is the number of cores of the CPU.
You can transform this
into
The worker thread does something like the following. Note that this is simplified, but you should get the idea.
void Thread::run(buffer<Task*>& queue) {
while(true) {
Task* task = queue.get();
if(task)
task->execute();
while(queue.isEmpty())
waitUntilQueueHasElement();
}
}
And your tasks implement a common interface so you can put Task* pointers into a single queue:
struct Task {
virtual void execute() = 0;
}
struct Task1 : public Task {
virtual void execute() override {
A();
B1();
C();
}
}
...
Also, do yourself a favour and use typedefs ;)
`std::vector<std::unique_ptr<locked_buffer<std::pair<int, std::vector<std::vector<unsigned char>>>>>> v1;`
becomes
typedef std::vector<std::vector<unsigned char>> vector2D_uchar;
typedef std::pair<int, vector2D_uchar> int_vec_pair;
typedef std::unique_ptr<locked_buffer<int_vec_pair>> locked_buffer_ptr;
std::vector<locked_buffer_ptr> v1;

C++ thread safe bound queue returning object for original thread to delete - 1 writer - 1 reader

The goal is to have a writer thread and a reader thread but only the writer news and deletes the action object. There is only one reader and one writer.
something like:
template<typename T, std::size_t MAX>
class TSQ
{
public:
// blocks if there are MAX items in queue
// returns used Object to be deleted or 0 if none exist
T * push(T * added); // added will be processed by reader
// blocks if there are no objects in queue
// returns item pushed from writer for deletion
T * pop(T * used); // used will be freed by writer
private:
// stuff here
};
-or better if the delete and return can be encapsulated:
template<typename T, std::size_t MAX>
class TSQ
{
public:
// blocks if there are MAX items in queue
push(T * added); // added will be processed by reader
// blocks if there are no objects in queue
// returns item pushed from writer for deletion
T& pop();
private:
// stuff here
};
where the writer thread has a loop like:
my_object *action;
while (1) {
// create action
delete my_queue.push(action);
}
and the reader has a loop like:
my_object * action=0;
while(1) {
action=my_queue.pop(action);
// do stuff with action
}
The reason to have the writer delete the action item is for performance
Is there an optimal way to do this?
Bonus points if MAX=0 is specialized to be unbounded (not required, just tidy)
I'm not looking for the full code, just the data structure and general approach
This is an instance of the producer-consumer problem. A popular way to solve this is to use a lockfree queue.
Also, the first practical change you might want to make is to add a sleep(0) into the production/consumption loops, so you will give up your time slice every iteration and won't end up using 100% of a CPU core.
The most common solution to this problem is to pass values, not pointers.
You can pass shared_ptr to this queue. Your queue doesn't need to know how to free memory after you.
If you use something like Lamport's ring buffer for single producer - single consumer blocking queue, it's a natural solution to use std::vector under the hood that will call destructors for every element automatically.
template<typename T, std::size_t MAX>
class TSQ
{
public:
// blocks if there are MAX items in queue
void push(T added); // added will be processed by reader
// blocks if there are no objects in queue
T pop();
private:
std::vector<T> _content;
size_t _push_index;
size_t _pop_index;
...
};

C++ return value on concurrent queue pushing functions

After receiving answers to a previous question on logging on a different thread, I am currently at the following bit of code (note: the concurrent_queue here is from ppl, but any other concurrent_queue should work):
class concurrentFuncQueue
{
private:
typedef std::function<void()> LambdaFunction;
mutable concurrency::concurrent_queue<LambdaFunction> functionQueue;
mutable std::atomic<bool> endcond;
LambdaFunction function;
std::thread thd;
public:
concurrentFuncQueue() : endcond(false), thd([=]{
while (endcond != true)
{
if (functionQueue.try_pop( function ))
{
function(); //note: I am popping a function and adding () to execute it
}
}
}){}
~concurrentFuncQueue() { functionQueue.push([=]{ endcond = true; }); thd.join(); }
void pushFunction(LambdaFunction function) const { functionQueue.push(function); }
};
Basically the functions I push are run on a different thread sequentially (ex. a logging function) as to avoid performance issues on the main thread.
Current usage is along the following:
static concurrentFuncQueue Logger;
vector<char> outstring(256);
Logger.pushFunction([=]{ OutputDebugString(debugString.c_str()) });
Great so far. I can push functions on to a concurrent queue that will run my functions sequentially on a separate thread.
One thing I also need to have, but currently don't are return values so that ex (pseudo-code):
int x = y = 3;
auto intReturn = Logger.pushFunction([=]()->int { return x * y; });
will push x * y on to the concurrent queue, and after the pop and completion of the function (on the other thread), returns the value calculated to the caller thread.
(I understand that I'll be blocking the caller thread until the pushed function is returned. That is exactly what I want)
I get the feeling that I might have to use something along the line of std::promise, but sadly my current low understanding of them prevent me from formulating something codable.
Any ideas? Thoughts on the above C++ code and any other comments are also much welcome (please just ignore the code completely if you feel another implementation is more appropriate or solves the problem).
You should be able to use something along the lines of:
template<typename Foo>
std::future<typename std::result_of<Foo()>::type> pushFunction(Foo&& f) {
using result_type = typename std::result_of<Foo()>::type; // change to typedef if using is not supported
std::packaged_task<result_type()> t(f);
auto ret_fut = t.get_future();
functionQueue.push(std::move(t));
return ret_fut;
}
For this to work you need to make your LambdaFunction a type-erased function handler.