[glibmm] examples/network: Improve the time-out functionality



commit 55a88dd5a7cfe9644f44fefbce8764140796dcc5
Author: Kjell Ahlstedt <kjell ahlstedt bredband net>
Date:   Sun Dec 6 18:57:02 2015 +0100

    examples/network: Improve the time-out functionality
    
    * examples/network/socket-client.cc:
    * examples/network/socket-server.cc: Store the thread pointer in a
    std::unique_ptr. Then the thread is always joined and deleted. Stop the thread
    immediately in case of error, or if the user requests end of transmission.

 examples/network/socket-client.cc |   39 +++++++++++++++++++++++---------
 examples/network/socket-server.cc |   44 +++++++++++++++++++++++++-----------
 2 files changed, 58 insertions(+), 25 deletions(-)
---
diff --git a/examples/network/socket-client.cc b/examples/network/socket-client.cc
index ebde5b6..3fdb30d 100644
--- a/examples/network/socket-client.cc
+++ b/examples/network/socket-client.cc
@@ -2,6 +2,10 @@
 #include <giomm.h>
 #include <glibmm.h>
 #include <thread>
+#include <mutex>
+#include <condition_variable>
+#include <chrono>
+#include <memory>
 #include <iostream>
 
 namespace
@@ -15,6 +19,9 @@ bool use_udp = false;
 bool use_source = false;
 bool use_ipv6 = false;
 int cancel_timeout = 0;
+bool stop_thread = false;
+std::mutex mutex_thread;
+std::condition_variable cond_thread;
 
 class ClientOptionGroup : public Glib::OptionGroup
 {
@@ -112,11 +119,28 @@ ensure_condition (const Glib::RefPtr<Gio::Socket>& socket,
 static void
 cancel_thread (Glib::RefPtr<Gio::Cancellable> cancellable)
 {
-    g_usleep (1000*1000*cancel_timeout);
+  std::unique_lock<std::mutex> lock(mutex_thread);
+  if (!cond_thread.wait_for(lock, std::chrono::seconds(cancel_timeout),
+      [](){ return stop_thread; }))
+  {
+    // !stop_thread, i.e. timeout
     std::cout << "Cancelling\n";
-    cancellable->cancel ();
+    cancellable->cancel();
+  }
 }
 
+class JoinAndDelete
+{
+public:
+  void operator()(std::thread* thread)
+  {
+    stop_thread = true;
+    cond_thread.notify_all();
+    thread->join();
+    delete thread;
+  }
+};
+
 } // end anonymous namespace
 
 int
@@ -160,11 +184,11 @@ main (int argc,
         return 1;
     }
 
-    std::thread* thread = nullptr;
+    std::unique_ptr<std::thread, JoinAndDelete> thread;
     if (cancel_timeout)
     {
         cancellable = Gio::Cancellable::create ();
-        thread = new std::thread(&cancel_thread, cancellable);
+        thread.reset(new std::thread(&cancel_thread, cancellable));
     }
 
     loop = Glib::MainLoop::create ();
@@ -322,12 +346,5 @@ main (int argc,
         return 1;
     }
 
-    //TODO: This won't happen if we returned earlier.
-    if(thread)
-    {
-      thread->join();
-      delete thread;
-    }
-
     return 0;
 }
diff --git a/examples/network/socket-server.cc b/examples/network/socket-server.cc
index 43c0e6e..835a6b7 100644
--- a/examples/network/socket-server.cc
+++ b/examples/network/socket-server.cc
@@ -1,7 +1,11 @@
-#include <thread>
-#include <iostream>
 #include <giomm.h>
 #include <glibmm.h>
+#include <thread>
+#include <mutex>
+#include <condition_variable>
+#include <chrono>
+#include <memory>
+#include <iostream>
 
 namespace
 {
@@ -16,6 +20,9 @@ bool use_udp = false;
 bool use_source = false;
 bool use_ipv6 = false;
 int cancel_timeout = 0;
+bool stop_thread = false;
+std::mutex mutex_thread;
+std::condition_variable cond_thread;
 
 class ServerOptionGroup : public Glib::OptionGroup
 {
@@ -118,11 +125,28 @@ ensure_condition (const Glib::RefPtr<Gio::Socket>& socket,
 static void
 cancel_thread (Glib::RefPtr<Gio::Cancellable> cancellable)
 {
-    g_usleep (1000*1000*cancel_timeout);
+  std::unique_lock<std::mutex> lock(mutex_thread);
+  if (!cond_thread.wait_for(lock, std::chrono::seconds(cancel_timeout),
+      [](){ return stop_thread; }))
+  {
+    // !stop_thread, i.e. timeout
     std::cout << "Cancelling\n";
-    cancellable->cancel ();
+    cancellable->cancel();
+  }
 }
 
+class JoinAndDelete
+{
+public:
+  void operator()(std::thread* thread)
+  {
+    stop_thread = true;
+    cond_thread.notify_all();
+    thread->join();
+    delete thread;
+  }
+};
+
 } // end anonymous namespace
 
 int
@@ -148,11 +172,11 @@ main (int argc,
       return 1;
     }
 
-    std::thread* thread = nullptr;
+    std::unique_ptr<std::thread, JoinAndDelete> thread;
     if (cancel_timeout)
     {
         cancellable = Gio::Cancellable::create ();
-        thread = new std::thread(&cancel_thread, cancellable);
+        thread.reset(new std::thread(&cancel_thread, cancellable));
     }
 
     loop = Glib::MainLoop::create ();
@@ -323,13 +347,5 @@ main (int argc,
         return 1;
     }
 
-
-    //TODO: This won't happen if we returned earlier.
-    if(thread)
-    {
-      thread->join();
-      delete thread;
-    }
-
     return 0;
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]