diff --git a/Makefile b/Makefile index 2dce900..4cb1bac 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,12 @@ examples: clang++ -flto -O3 -s *.o -o HelloWorld rm *.o +# HelloWorldThreaded (non-SSL, non-Zlib compile) + clang -DLIBUS_NO_SSL -flto -O3 -c -IuSockets/src uSockets/src/*.c uSockets/src/eventing/*.c + clang++ -DLIBUS_NO_SSL -DUWS_NO_ZLIB -flto -O3 -c -std=c++17 -Isrc -IuSockets/src examples/HelloWorldThreaded.cpp + clang++ -lpthread -flto -O3 -s *.o -o HelloWorldThreaded + rm *.o + # EchoServer (non-SSL, non-Zlib compile) clang -DLIBUS_NO_SSL -flto -O3 -c -IuSockets/src uSockets/src/*.c uSockets/src/eventing/*.c clang++ -DLIBUS_NO_SSL -DUWS_NO_ZLIB -flto -O3 -c -std=c++17 -Isrc -IuSockets/src examples/EchoServer.cpp diff --git a/examples/HelloWorldThreaded.cpp b/examples/HelloWorldThreaded.cpp new file mode 100644 index 0000000..a35e9b5 --- /dev/null +++ b/examples/HelloWorldThreaded.cpp @@ -0,0 +1,28 @@ +#include "App.h" +#include +#include + +int main() { + /* Overly simple hello world app, using multiple threads */ + std::vector threads(std::thread::hardware_concurrency()); + + std::transform(threads.begin(), threads.end(), threads.begin(), [](std::thread *t) { + return new std::thread([]() { + + uWS::App().get("/*", [](auto *res, auto *req) { + res->end("Hello world!"); + }).listen(3000, [](auto *token) { + if (token) { + std::cout << "Thread " << std::this_thread::get_id() << " listening on port " << 3000 << std::endl; + } else { + std::cout << "Thread " << std::this_thread::get_id() << " failed to listen on port 3000" << std::endl; + } + }).run(); + + }); + }); + + std::for_each(threads.begin(), threads.end(), [](std::thread *t) { + t->join(); + }); +} diff --git a/src/Loop.h b/src/Loop.h index f030755..810a8a9 100644 --- a/src/Loop.h +++ b/src/Loop.h @@ -24,7 +24,7 @@ #include #include -#include +#include namespace uWS { struct Loop { @@ -86,9 +86,13 @@ private: public: /* Returns the default loop if called from one thread, or a dedicated per-thread loop if called from multiple threads */ static Loop *defaultLoop() { + /* Lock this whole function */ + static std::mutex m; + std::lock_guard lock(m); + /* Deliver and attach the default loop to the first thread who calls us */ static thread_local bool ownsDefaultLoop; - static std::atomic defaultLoop; + static Loop *defaultLoop; if (!defaultLoop) { ownsDefaultLoop = true; defaultLoop = create(true);