简体   繁体   中英

Submitting a task to a Thread Pool Implementation Issue

I'm using thread pools for the first time, working out of Anthony Williams' Concurrency In Action book. He provides a basic thread pool class that I'm trying to use but not an implementation - just the class. The issue is that I'm new to templates and thread-pools. This is probably a simple question/answer but I can't figure it out. I have this function to submit jobs to the pool:

class SimpleThreadPool
{
public:
    ...
    // -- Submit a task to the thread pool
    template <typename FunctionType>
    void submit(FunctionType f);
    ...
};

I'm trying to call it but honestly don't know how (have tried a few different things):

boost::interprocess::scoped_lock<std::mutex> lock(m_mtx_map);
for(const auto& elem : m_logger_map)
{
    m_thread_pool->submit< std::function< void > >(elem.second->operator());
}

Here the m_thread_pool is a pointer to the thread pool and the map contains (string,pointer) pairs where the pointer points to a logging object which has it's main run/processing method in operator().

I'm getting a: error: no matching function call 'SimpleThreadPool::submit(< unresolved overloaded function type >)'

How do I correctly use this submit function?

Thank you!

UPDATE -----

Here's the implementation in the thread pool class:

// -- Submit Method
/** void submit(FunctionType f)
 *  @desc   :   Submit a job (function pointer) to the pool
 */
template <typename FunctionType> void SimpleThreadPool::submit(FunctionType f)
{
    m_q_work.push(std::function<void()>(f));
}

m_q_work is a thread-safe Queue.

// -- Launch a new worker thread
/** void m_worker_thread()
 *  @desc   :   Worker thread main method for getting tasks and executing
 */
void SimpleThreadPool::m_worker_thread()
{
    while(!m_done)
    {
        std::function<void()> task;

        if(m_q_work.try_pop(task))
        {
            task();
        }
        else
        {
            std::this_thread::yield();
        }
    }
}

I'm guessing I probably need to change the implementation based on my comment to the response below.

The following compiled in g++

#include <map>
#include <string>
#include <functional>

class SimpleThreadPool {
public:    
   template <typename FunctionType>
   void submit(FunctionType f) { }
};

class Logger {
public:
   void operator()() { }
};


int main(int argc,char **argv) {
    std::map<std::string,Logger*> m_logger_map;    
    m_logger_map["one"]=new Logger();
    SimpleThreadPool *m_thread_pool=new SimpleThreadPool();
    for (const auto& elem: m_logger_map) {
        m_thread_pool->submit<std::function< void() > >(*elem.second);
    }    
}

Changes are:

1.- std::function< void() > , instead of std::function<void> (yours only had the return type, but not the parameters (note that I've defined the operator() with empty parameters).

2.- *elem.second as the argument to submit (instead of elem.second->operator() ). Note that a function object (ie an object of class with an operator() defined) can be used as a std::function (refer to the examples in the std::function reference )

Edit: avoid the lack of copy constructor

Instead of using directly the Logger object that cannot be copy-constructed, we can use a Wrapper object. This Wrapper object contains a reference to the Logger class.

I've also changed the code to use shared_ptr, because memory ownership becomes more complex:

#include <map>
#include <string>
#include <functional>
#include <memory>

class SimpleThreadPool {
public:
   template <typename FunctionType>
   void submit(FunctionType f) { }
};

class Logger {
public:
   Logger() { }
   Logger(const Logger&) = delete; // Logger cannot be copied
   void operator()() { }
};

template <typename T>
class Wrapper {
public:
   Wrapper(const std::shared_ptr<T> &l):mWrapped(l) { } // Wraps a T reference
   void operator()() {
      (*mWrapped)(); // expected to be a function object
   }
private:
  std::shared_ptr<T> mWrapped;
};


int main(int argc,char **argv) {
    // Need to change the definition of the map
    // to contain shared_ptr.
    std::map<std::string,std::shared_ptr<Logger> > m_logger_map;
    m_logger_map["one"]=std::make_shared<Logger>();
    SimpleThreadPool *m_thread_pool=new SimpleThreadPool();
    for (const auto& elem: m_logger_map) {
        // Create the Wrapper object from the reference we've 
        // obtained from the map.... The wrapper can be copied
        // around, but the reference will not change.
        std::function<void()> f=Wrapper<Logger>(elem.second);
        m_thread_pool->submit<std::function< void() > >(f);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM