Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I've created this very small header that allows direct creation of threads from lambdas. I can't find anything else similar on the net so I want to know whether there are any problems with this that I have not thought of. It is based on tinythread++, but can easily be altered to work with pthread or other threading libraries that can take a void (void*) (or void* (void*)) function and a void* argument for the function to start a thread. Note that this implementation is assuming limited C++0x/11 support, i.e. just lambdas.

#include "tinythread.h"

namespace lthread {
    /// implementation details - do not use directly
    namespace impl {
        template<typename Func>
        void use_function_once(void* _f) {
            const Func* f = (const Func*)_f;
            (*f)();
            delete f; // delete - no longer needed
        }
        template<typename Func>
        void use_function(void* _f) {
            const Func* f = (const Func*)_f;
            (*f)();
        }
    }

    /// Creates a thread based on a temporary function.
    /// Copies the function onto the heap for use outside of the local scope, removes from the heap when finished.
    template<typename Func>
    tthread::thread* new_thread(const Func& f) {
        Func* _f = new Func(f); // copy to heap
        return new tthread::thread(&impl::use_function_once<Func>,(void*)_f);
    }

    /// Creates a thread based on a guaranteed persistent function.
    /// Does not copy or delete the function.
    template<typename Func>
    tthread::thread* new_thread(const Func* f) {
        return new tthread::thread(&impl::use_function<Func>, (void*)f);
    }
}

Example usage:

size_t a = 1;
size_t b = 0;
tthread::thread* t = lthread::new_thread([&] () {
    std::cout << "I'm in a thread!\n";
    std::cout << "'a' is " << a << std::endl;
    b = 1;
});
t->join();
std::cout << "'b' is " << b << std::endl;
delete t;
share|improve this question
1  
What if (*f)(); should throw? You get a leak. –  user1095108 Aug 3 '13 at 23:17
    
@user1095108 Good point. –  Dylan Aug 5 '13 at 10:39

1 Answer 1

  1. surely you can just use std::function<void()> instead of templating on the function type?

  2. capturing by reference can go horribly wrong. It's not a bug in your library, just an observation ...

    tthread::thread* startthread(size_t a, size_t b)
    {
        return lthread::new_thread([&] ()
            {
                std::cout << "I'm in a thread!\n";
                std::cout << "'a' is " << a << std::endl;
                b = 1;
            }
            );
    }
    
    int main()
    {
        tthread::thread *t = startthread(1,2);
        t->join();
        delete t;
    }
    
  3. use_function_once is vulnerable to the function call throwing an exception: you should probably assign it to a smart pointer before calling, and lose the explicit delete.

  4. that overload of new_thread also has a problem if either new or tthread::thread can throw: it will leak the heap-allocated Func. You can fix this with a smart pointer too.

share|improve this answer
    
I have already made a change to the code - the two new_thread functions now have different names - the by reference version was capturing the pointer argument instead of the pointer version and thus didn't compile as intended. –  Dylan Sep 19 '12 at 16:59
    
Also, I am fully aware of the point you are making with that snippet, but that also applies to any other deferred running of a lambda function. Users should be aware of this as when using by-reference lambdas in other situations. –  Dylan Sep 19 '12 at 17:01

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.