Browse Source

Revised deinitialization

Paul-Louis Ageneau 5 years ago
parent
commit
777f5a8dfe
3 changed files with 65 additions and 39 deletions
  1. 4 4
      include/rtc/init.hpp
  2. 57 35
      src/init.cpp
  3. 4 0
      test/main.cpp

+ 4 - 4
include/rtc/init.hpp

@@ -25,8 +25,7 @@
 
 namespace rtc {
 
-class Init;
-using init_token = std::shared_ptr<Init>;
+using init_token = std::shared_ptr<void>;
 
 class Init {
 public:
@@ -38,9 +37,10 @@ public:
 
 private:
 	Init();
+	static init_token Load(bool preloading);
 
-	static std::weak_ptr<Init> Weak;
-	static init_token Global;
+	static std::weak_ptr<void> Weak;
+	static std::shared_ptr<void> *Global;
 	static std::mutex Mutex;
 };
 

+ 57 - 35
src/init.cpp

@@ -40,34 +40,9 @@ using std::shared_ptr;
 
 namespace rtc {
 
-std::weak_ptr<Init> Init::Weak;
-init_token Init::Global;
-std::mutex Init::Mutex;
-
-init_token Init::Token() {
-	std::lock_guard lock(Mutex);
-
-	if (!Global) {
-		if (auto token = Weak.lock())
-			Global = token;
-		else
-			Global = shared_ptr<Init>(new Init());
-	}
-	return Global;
-}
-
-void Init::Preload() {
-	init_token token = Token(); // pre-init
-	make_certificate().wait(); // preload certificate
-}
-
-void Init::Cleanup() {
-	Global.reset();
-}
-
-Init::Init() {
-	// Mutex is locked by Token() here
+namespace {
 
+void doInit() {
 #ifdef _WIN32
 	WSADATA wsaData;
 	if (WSAStartup(MAKEWORD(2, 2), &wsaData))
@@ -92,12 +67,8 @@ Init::Init() {
 #endif
 }
 
-Init::~Init() {
-	// We need to lock Mutex ourselves
-	std::lock_guard lock(Mutex);
-	if (Global)
-		return;
-
+void doCleanup() {
+	ThreadPool::Instance().join();
 	CleanupCertificateCache();
 
 	SctpTransport::Cleanup();
@@ -109,12 +80,63 @@ Init::~Init() {
 	DtlsSrtpTransport::Cleanup();
 #endif
 
-	ThreadPool::Instance().join();
-
 #ifdef _WIN32
 	WSACleanup();
 #endif
 }
 
+} // namespace
+
+std::weak_ptr<void> Init::Weak;
+std::shared_ptr<void> *Init::Global = nullptr;
+std::mutex Init::Mutex;
+
+init_token Init::Token() { return Load(false); }
+
+init_token Init::Load(bool preloading) {
+	std::lock_guard lock(Mutex);
+	if (auto token = Weak.lock()) {
+		if (preloading) {
+			// if preloading, set Global
+			delete Global;
+			Global = new shared_ptr<void>(token);
+		}
+		return token;
+	}
+
+	delete Global;
+	Global = new shared_ptr<void>(new Init());
+	Weak = *Global;
+	return *Global;
+}
+
+void Init::Preload() {
+	init_token token = Load(true);
+	make_certificate().wait();  // preload certificate
+}
+
+void Init::Cleanup() {
+	std::lock_guard lock(Mutex);
+	delete Global;
+	Global = nullptr;
+}
+
+Init::Init() {
+	// Mutex is locked by Token() here
+	doInit();
+}
+
+Init::~Init() {
+	std::thread t([]() {
+		// We need to lock Mutex ourselves
+		std::lock_guard lock(Mutex);
+		if (Weak.lock())
+			return;
+
+		doCleanup();
+	});
+	t.detach();
+}
+
 } // namespace rtc
 

+ 4 - 0
test/main.cpp

@@ -18,6 +18,7 @@
 
 #include <chrono>
 #include <iostream>
+#include <thread>
 
 using namespace std;
 using namespace chrono_literals;
@@ -71,7 +72,10 @@ int main(int argc, char **argv) {
 		cout << "*** Finished WebRTC benchmark" << endl;
 	} catch (const exception &e) {
 		cerr << "WebRTC benchmark failed: " << e.what() << endl;
+		std::this_thread::sleep_for(2s);
 		return -1;
 	}
+
+	std::this_thread::sleep_for(2s);
 	return 0;
 }