#pragma once // Like C++11's std::thread, but with a reduced API, and works on Windows with MSVC2010+. // Wraps std::thread on other OSes. Perhaps the most significant departure between // std::thread and this mini-library is that join() is called implicitly in the destructor, // if the thread is joinable. The thread callback functions should not throw exceptions. #include #include namespace details { template struct ArgWrapper { typename std::remove_reference::type arg1; typename std::remove_reference::type arg2; typename std::remove_reference::type arg3; template ArgWrapper(T&& a1, U&& a2, V&& a3) : arg1(std::forward(a1)), arg2(std::forward(a2)), arg3(std::forward(a3)) { } template void callCallback(TCallback&& callback) const { std::forward(callback)(std::move(arg1), std::move(arg2), std::move(arg3)); } }; template struct ArgWrapper { typename std::remove_reference::type arg1; typename std::remove_reference::type arg2; template ArgWrapper(T&& a1, U&& a2) : arg1(std::forward(a1)), arg2(std::forward(a2)) { } template void callCallback(TCallback&& callback) const { std::forward(callback)(std::move(arg1), std::move(arg2)); } }; template struct ArgWrapper { typename std::remove_reference::type arg1; template ArgWrapper(T&& a1) : arg1(std::forward(a1)) { } template void callCallback(TCallback&& callback) const { std::forward(callback)(std::move(arg1)); } }; template<> struct ArgWrapper { template void callCallback(TCallback&& callback) const { std::forward(callback)(); } }; } class SimpleThread { private: struct ThreadRef; template struct CallbackWrapper { template CallbackWrapper(TCallback&& callback, U&& args) : callback(std::forward(callback)), args(std::forward(args)) { } static void callAndDelete(void* wrapper) { auto typedWrapper = static_cast(wrapper); typedWrapper->args.callCallback(std::move(typedWrapper->callback)); delete typedWrapper; } typename std::decay::type callback; TArgs args; }; typedef void (*CallbackFunc)(void*); void startThread(void* callbackObj, CallbackFunc callbackFunc); public: static const int StackSize = 4 * 1024; // bytes SimpleThread() : thread(nullptr) { } SimpleThread(SimpleThread&& other) : thread(other.thread) { other.thread = nullptr; } SimpleThread& operator=(SimpleThread&& other) { thread = other.thread; other.thread = nullptr; return *this; } // Disable copying and copy-assignment private: SimpleThread(SimpleThread const&); SimpleThread& operator=(SimpleThread const&); public: template explicit SimpleThread(TCallback&& callback) { auto wrapper = new CallbackWrapper>( std::forward(callback), details::ArgWrapper<>() ); startThread(wrapper, &CallbackWrapper>::callAndDelete); } template explicit SimpleThread(TCallback&& callback, TArg1&& arg1) { auto wrapper = new CallbackWrapper>( std::forward(callback), details::ArgWrapper(std::forward(arg1)) ); startThread(wrapper, &CallbackWrapper>::callAndDelete); } template explicit SimpleThread(TCallback&& callback, TArg1&& arg1, TArg2&& arg2) { auto wrapper = new CallbackWrapper>( std::forward(callback), details::ArgWrapper(std::forward(arg1), std::forward(arg2)) ); startThread(wrapper, &CallbackWrapper>::callAndDelete); } template explicit SimpleThread(TCallback&& callback, TArg1&& arg1, TArg2&& arg2, TArg3&& arg3) { auto wrapper = new CallbackWrapper>( std::forward(callback), details::ArgWrapper(std::forward(arg1), std::forward(arg2), std::forward(arg3)) ); startThread(wrapper, &CallbackWrapper>::callAndDelete); } ~SimpleThread(); void join(); private: ThreadRef* thread; };