Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Trouble with pointer to templated class method

I was writing code for the following parallel processing task:

  1. A std::vector<T> contains data items that need to be processed
  2. 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:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

  1. A number of threads is started and they all run the same worker method
  2. 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.

>Solution :

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).

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading