mtrebi / thread-pool

Thread pool implementation using c++11 threads
MIT License
1.15k stars 225 forks source link

Is there a way to have a member method as the executed function? #14

Open eyalfrish opened 6 years ago

eyalfrish commented 6 years ago

Hi,

I assume the answer is "no" of course, but, before I make that conclusion, I would prefer asking in here :). Can I somehow have a member-method (non-static) be my executed function when submitting?

Thanks!

mtrebi commented 6 years ago

Hello,

Yes, its actually pretty simple.

Let's say this is your class:

class ClassName
{
private:
  int one;
public:
  ClassName() 
   : one(1)
  {}

  int AddOne(const int b)
  {
    return one + b;
  }
};

Then, you have to do this:

  ClassName classInstance;

  // Creates a copy of classInstace, use std::ref(classInstance) to force pass by ref
  auto function = std::bind(&ClassName::AddOne, classInstance, 3); 
  auto future = pool.submit(function);

  // Get result, should be equals to 4 (3+1)
  int result = future.get();
  std::cout << "Last operation result is equals to " << result << std::endl;

I'll add this example to the readme whenever I have some time. Thanks for pointing that out.

PS: If you dont like std::bind you can also use lambdas.

Hope this helps

mariano.

dangulod commented 4 years ago

Hi,

I was using your thread pool implementation. And I implemented a method to address this in a different way. I post here if it helps:

template<typename F,  class T, class T1, typename...Args>
  auto submit(F T::*f, T1 *obj, Args&&... args) -> std::future<decltype((std::declval<T>().*f)(args...))>
  {
    // Create a function with bounded parameters ready to execute

    std::function<decltype((std::declval<T>().*f)(args...))()> func = [=] ()
    {
        (obj->*f)(args...);
    };
    // Encapsulate it into a shared ptr in order to be able to copy construct / assign
    auto task_ptr = std::make_shared<std::packaged_task<decltype((std::declval<T>().*f)(args...))()>>(func);

    // Wrap packaged task into void function
    std::function<void()> wrapper_func = [task_ptr]() {
      (*task_ptr)();
    };

    // Enqueue generic wrapper function
    m_queue.enqueue(wrapper_func);

    // Wake up one thread if its waiting
    m_conditional_lock.notify_one();

    // Return future from promise
    return task_ptr->get_future();
  }

By the way, thank you for your library, you really did a good work!