diff --git a/include/util/common.hpp b/include/util/common.hpp index 4bf221fa..d061f416 100644 --- a/include/util/common.hpp +++ b/include/util/common.hpp @@ -11,6 +11,9 @@ #include #include +//////////////////// +// Handy macros +//////////////////// /** Surrounds raw text with quotes Example: @@ -51,6 +54,9 @@ Example: namespace rack { +//////////////////// +// Template hacks +//////////////////// /** C#-style property constructor Example: @@ -68,6 +74,32 @@ T *construct(F f, V v, Args... args) { return o; } +/** Delays code until the scope is destructed +From http://www.gingerbill.org/article/defer-in-cpp.html + +Example: + file = fopen(...); + defer({ + fclose(file); + }); +*/ +template +struct DeferWrapper { + F f; + DeferWrapper(F f) : f(f) {} + ~DeferWrapper() { f(); } +}; + +template +DeferWrapper deferWrapper(F f) { + return DeferWrapper(f); +} + +#define DEFER_1(x, y) x##y +#define DEFER_2(x, y) DEFER_1(x, y) +#define DEFER_3(x) DEFER_2(x, __COUNTER__) +#define defer(code) auto DEFER_3(_defer_) = deferWrapper([&]() code) + //////////////////// // Random number generator // random.cpp diff --git a/src/bridge.cpp b/src/bridge.cpp index 3928569d..64fb822e 100644 --- a/src/bridge.cpp +++ b/src/bridge.cpp @@ -234,6 +234,9 @@ static void serverRun() { #ifdef ARCH_WIN WSADATA wsaData; err = WSAStartup(MAKEWORD(2,2), &wsaData); + defer({ + WSACleanup(); + }); if (err) { warn("Could not initialize Winsock"); return; @@ -250,6 +253,9 @@ static void serverRun() { hints.ai_protocol = IPPROTO_TCP; hints.ai_flags = AI_PASSIVE; err = getaddrinfo(NULL, "5000", &hints, &result); + defer({ + freeaddrinfo(result); + }); #else struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); @@ -273,6 +279,10 @@ static void serverRun() { warn("Bridge server socket() failed"); return; } + defer({ + close(server); + }); + // Bind socket to address #ifdef ARCH_WIN @@ -282,14 +292,14 @@ static void serverRun() { #endif if (err) { warn("Bridge server bind() failed"); - goto serverRun_cleanup; + return; } // Listen for clients err = listen(server, 20); if (err) { warn("Bridge server listen() failed"); - goto serverRun_cleanup; + return; } info("Bridge server started"); @@ -319,15 +329,7 @@ static void serverRun() { clientThread.detach(); } - // Cleanup -serverRun_cleanup: - err = close(server); - (void) err; info("Bridge server closed"); -#ifdef ARCH_WIN - freeaddrinfo(result); - WSACleanup(); -#endif }