Merge branch 'master' into windows
[ardour.git] / libs / pbd / pbd / abstract_ui.cc
index b300a62dd8e780e0d260e2750c1f2a7a64f1b5d1..9c405745ac3fc6f4b7d693f244c5cfc840763871 100644 (file)
@@ -1,3 +1,22 @@
+/*
+    Copyright (C) 2012 Paul Davis 
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
 #include <unistd.h>
 #include <iostream>
 
 
 #include "i18n.h"
 
-using namespace std;
+#ifdef COMPILER_MSVC
+#include <ardourext/misc.h>  // Needed for 'DECLARE_DEFAULT_COMPARISONS'. Objects in an STL container can be
+                             // searched and sorted. Thus, when instantiating the container, MSVC complains
+                             // if the type of object being contained has no appropriate comparison operators
+                             // defined (specifically, if operators '<' and '==' are undefined). This seems
+                             // to be the case with ptw32 'pthread_t' which is a simple struct.
+DECLARE_DEFAULT_COMPARISONS(pthread_t)
+#endif
 
-template<typename R>
-Glib::StaticPrivate<typename AbstractUI<R>::RequestBuffer> AbstractUI<R>::per_thread_request_buffer;
+using namespace std;
 
 template<typename RequestBuffer> void 
 cleanup_request_buffer (void* ptr)
@@ -28,11 +53,14 @@ cleanup_request_buffer (void* ptr)
         
 
         {
-                Glib::Mutex::Lock lm (rb->ui.request_buffer_map_lock);
+                Glib::Threads::Mutex::Lock lm (rb->ui.request_buffer_map_lock);
                 rb->dead = true;
         }
 }
 
+template<typename R>
+Glib::Threads::Private<typename AbstractUI<R>::RequestBuffer> AbstractUI<R>::per_thread_request_buffer (cleanup_request_buffer<AbstractUI<R>::RequestBuffer>);
+
 template <typename RequestObject>
 AbstractUI<RequestObject>::AbstractUI (const string& name)
        : BaseUI (name)
@@ -87,7 +115,7 @@ AbstractUI<RequestObject>::register_thread (string target_gui, pthread_t thread_
                   only at thread initialization time, not repeatedly, 
                   and so this is of little consequence.
                */
-               Glib::Mutex::Lock lm (request_buffer_map_lock);
+               Glib::Threads::Mutex::Lock lm (request_buffer_map_lock);
                request_buffers[thread_id] = b;
        }
 
@@ -100,7 +128,7 @@ AbstractUI<RequestObject>::register_thread (string target_gui, pthread_t thread_
           dead. it will then be deleted during a call to handle_ui_requests()
        */
        
-       per_thread_request_buffer.set (b, cleanup_request_buffer<RequestBuffer>);
+       per_thread_request_buffer.set (b);
 }
 
 template <typename RequestObject> RequestObject*
@@ -127,7 +155,7 @@ AbstractUI<RequestObject>::get_request (RequestType rt)
                        return 0;
                }
 
-               DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1: allocated per-thread request of type %2, caller %3\n", name(), rt, pthread_self()));
+               DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1: allocated per-thread request of type %2, caller %3\n", name(), rt, pthread_name()));
 
                vec.buf[0]->type = rt;
                 vec.buf[0]->valid = true;
@@ -139,7 +167,7 @@ AbstractUI<RequestObject>::get_request (RequestType rt)
         * are not at work.
         */
 
-       DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1: allocated normal heap request of type %2, caller %3\n", name(), rt, pthread_self()));
+       DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1: allocated normal heap request of type %2, caller %3\n", name(), rt, pthread_name()));
 
        RequestObject* req = new RequestObject;
        req->type = rt;
@@ -194,7 +222,7 @@ AbstractUI<RequestObject>::handle_ui_requests ()
        for (i = request_buffers.begin(); i != request_buffers.end(); ) {
              if ((*i).second->dead) {
                     DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 deleting dead per-thread request buffer for %3 @ %4\n",
-                                                                         name(), pthread_self(), i->first, i->second));
+                                                                         name(), pthread_name(), i->second));
                      delete (*i).second;
                      RequestBufferMapIterator tmp = i;
                      ++tmp;
@@ -209,7 +237,7 @@ AbstractUI<RequestObject>::handle_ui_requests ()
 
        /* and now, the generic request buffer. same rules as above apply */
 
-       Glib::Mutex::Lock lm (request_list_lock);
+       Glib::Threads::Mutex::Lock lm (request_list_lock);
 
        while (!request_list.empty()) {
                RequestObject* req = request_list.front ();
@@ -222,7 +250,7 @@ AbstractUI<RequestObject>::handle_ui_requests ()
 
                 request_buffer_map_lock.lock ();
                 if (!req->valid) {
-                       DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 handling invalid heap request, type %3, deleting\n", name(), pthread_self(), req->type));
+                       DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 handling invalid heap request, type %3, deleting\n", name(), pthread_name(), req->type));
                         delete req;
                         request_buffer_map_lock.unlock ();
                         continue;
@@ -234,7 +262,7 @@ AbstractUI<RequestObject>::handle_ui_requests ()
                 */
 
                 if (req->invalidation) {
-                       DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 remove request from its invalidation list\n", name(), pthread_self()));
+                       DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 remove request from its invalidation list\n", name(), pthread_name()));
                        
                        /* after this call, if the object referenced by the
                         * invalidation record is deleted, it will no longer
@@ -262,7 +290,7 @@ AbstractUI<RequestObject>::handle_ui_requests ()
 
                lm.release ();
 
-               DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 execute request type %3\n", name(), pthread_self(), req->type));
+               DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 execute request type %3\n", name(), pthread_name(), req->type));
 
                /* and lets do it ... this is a virtual call so that each
                 * specific type of UI can have its own set of requests without
@@ -271,7 +299,7 @@ AbstractUI<RequestObject>::handle_ui_requests ()
 
                do_request (req);
 
-               DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 delete heap request type %3\n", name(), pthread_self(), req->type));
+               DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 delete heap request type %3\n", name(), pthread_name(), req->type));
                delete req;
 
                /* re-acquire the list lock so that we check again */
@@ -296,7 +324,7 @@ AbstractUI<RequestObject>::send_request (RequestObject *req)
                /* the thread that runs this UI's event loop is sending itself
                   a request: we dispatch it immediately and inline.
                */
-               DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 direct dispatch of request type %3\n", name(), pthread_self(), req->type));
+               DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 direct dispatch of request type %3\n", name(), pthread_name(), req->type));
                do_request (req);
        } else {        
 
@@ -315,14 +343,14 @@ AbstractUI<RequestObject>::send_request (RequestObject *req)
                RequestBuffer* rbuf = per_thread_request_buffer.get ();
 
                if (rbuf != 0) {
-                       DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 send per-thread request type %3\n", name(), pthread_self(), req->type));
+                       DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 send per-thread request type %3\n", name(), pthread_name(), req->type));
                        rbuf->increment_write_ptr (1);
                } else {
                        /* no per-thread buffer, so just use a list with a lock so that it remains
                           single-reader/single-writer semantics
                        */
-                       DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 send heap request type %3\n", name(), pthread_self(), req->type));
-                       Glib::Mutex::Lock lm (request_list_lock);
+                       DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 send heap request type %3\n", name(), pthread_name(), req->type));
+                       Glib::Threads::Mutex::Lock lm (request_list_lock);
                        request_list.push_back (req);
                }
 
@@ -330,7 +358,7 @@ AbstractUI<RequestObject>::send_request (RequestObject *req)
                   at the per-thread and generic request lists.
                */
 
-               request_channel.wakeup ();
+               signal_new_request ();
        }
 }
 
@@ -338,7 +366,7 @@ template<typename RequestObject> void
 AbstractUI<RequestObject>::call_slot (InvalidationRecord* invalidation, const boost::function<void()>& f)
 {
        if (caller_is_self()) {
-               DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 direct dispatch of call slot via functor @ %3, invalidation %4\n", name(), pthread_self(), &f, invalidation));
+               DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 direct dispatch of call slot via functor @ %3, invalidation %4\n", name(), pthread_name(), &f, invalidation));
                f ();
                return;
        }
@@ -349,7 +377,7 @@ AbstractUI<RequestObject>::call_slot (InvalidationRecord* invalidation, const bo
                return;
        }
 
-       DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 queue call-slot using functor @ %3, invalidation %4\n", name(), pthread_self(), &f, invalidation));
+       DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 queue call-slot using functor @ %3, invalidation %4\n", name(), pthread_name(), &f, invalidation));
 
        /* copy semantics: copy the functor into the request object */