1

I have a simple Threads class based on pthreads which works fine with a standard static callback function.

Is it possible to generalize Threads to work with lambdas, too?

problems:

  • sandbox.cpp:27:26: error: invalid cast from type ‘main(int, char*)::’ to type ‘void

  • thread_cb() needs to deal with generically casting void* back into something callable

I suspect the second problem may be solved with template methods or maybe std::function, but not sure how.

#include <vector>
#include <iostream>

#include <pthread.h>

class Threads 
{
    public:
        Threads()  { }
        ~Threads() { }

    private:
        static void *thread_cb( void *v )
        {
            // following will also need to change
            void (*my_fptr)() =
                reinterpret_cast<void(*)()>(reinterpret_cast<long long>(v));   
            my_fptr();
            return nullptr;
        }

    public:
        template<typename CALLBACK>
        void spawn( CALLBACK cb )
        {
            pthread_t t;
            void *p = (void*)( cb ); // problem here
            pthread_create( &t, nullptr, thread_cb, p );
            m_threads.push_back( t );
        }

        void join_all()
        {
            for ( auto& p : m_threads )
                pthread_join( p, nullptr );
        }

    private:
        std::vector< pthread_t > m_threads;
};

static void my_cb()
{
    std::cerr << "bar" << std::endl;
}

int main(int argc, char** argv)
{
    Threads t;

    t.spawn( my_cb );  // ok
    t.spawn( []() { std::cerr << "foo" << std::endl; } ); // not ok

    t.join_all();

    return 0;
}
ildjarn
  • 62,044
  • 9
  • 127
  • 211
kfmfe04
  • 14,936
  • 14
  • 74
  • 140
  • 2
    Is there some reason you can't just use `std::thread`, since you're already in C++11 land (as you're talking about lambdas)? – Nicol Bolas Dec 05 '11 at 09:47
  • 2
    If you're using c++11 why bother with pthreads? Just use std::thread. You can use then directly with lambdas or any callable thing. – bames53 Dec 05 '11 at 09:50
  • No special reason (transitioning from legacy code) - ty for the recommendation to move to std::thread - I will recode to std::thread – kfmfe04 Dec 05 '11 at 19:39

1 Answers1

1

You can use "lambda to function pointer" conversion. ...be that as it may, I strongly recommend std::thread.

template<typename CALLBACK>
void spawn( CALLBACK cb )
{
  pthread_t t;
  // void *p = (void*)( cb );
  // pthread_create( &t, nullptr, thread_cb, p );
  void (*pfn)() = cb;  // function pointer to `void()`
  pthread_create( &t, nullptr, thread_cb, reinterpret_cast<void*>(pfn) );
  m_threads.push_back( t );
}
yohjp
  • 2,985
  • 3
  • 30
  • 100