split apart ardour_ui.cc into a series of distinct source modules.
[ardour.git] / libs / pbd / crossthread.posix.cc
index 6dbca9dcec148ab4832e7097c77d100eda171316..97625ce2aa5284267c02962621dda2fc92205e39 100644 (file)
@@ -1,7 +1,27 @@
+/*
+ * Copyright (C) 2014-2016 Paul Davis <paul@linuxaudiosystems.com>
+ * Copyright (C) 2015-2016 Robin Gareus <robin@gareus.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
 #include <poll.h>
 
 CrossThreadChannel::CrossThreadChannel (bool non_blocking)
         : receive_channel (0)
+        , receive_source (0)
 {
        fds[0] = -1;
        fds[1] = -1;
@@ -16,7 +36,7 @@ CrossThreadChannel::CrossThreadChannel (bool non_blocking)
                        error << "cannot set non-blocking mode for x-thread pipe (read) (" << ::strerror (errno) << ')' << endmsg;
                        return;
                }
-               
+
                if (fcntl (fds[1], F_SETFL, O_NONBLOCK)) {
                        error << "cannot set non-blocking mode for x-thread pipe (write) (%2)" << ::strerror (errno) << ')' << endmsg;
                        return;
@@ -28,19 +48,28 @@ CrossThreadChannel::CrossThreadChannel (bool non_blocking)
 
 CrossThreadChannel::~CrossThreadChannel ()
 {
-        if (receive_channel) {
+       if (receive_source) {
+               /* this disconnects it from any main context it was attached in
+                  in ::attach(), this prevent its callback from being invoked
+                  after the destructor has finished.
+               */
+               g_source_destroy (receive_source);
+       }
+
+       if (receive_channel) {
                 g_io_channel_unref (receive_channel);
+                receive_channel = 0;
         }
 
        if (fds[0] >= 0) {
                close (fds[0]);
                fds[0] = -1;
-       } 
+       }
 
        if (fds[1] >= 0) {
                close (fds[1]);
                fds[1] = -1;
-       } 
+       }
 }
 
 void
@@ -87,7 +116,7 @@ CrossThreadChannel::poll_for_request()
        return false;
 }
 
-int 
+int
 CrossThreadChannel::receive (char& msg, bool wait)
 {
        if (wait) {