3 #include <pbd/abstract_ui.h>
4 #include <pbd/pthread_utils.h>
5 #include <pbd/failed_constructor.h>
11 template <typename RequestObject>
12 AbstractUI<RequestObject>::AbstractUI (string name, bool with_signal_pipes)
13 : BaseUI (name, with_signal_pipes)
15 if (pthread_key_create (&thread_request_buffer_key, 0)) {
16 cerr << _("cannot create thread request buffer key") << endl;
17 throw failed_constructor();
20 PBD::ThreadCreatedWithRequestSize.connect (mem_fun (*this, &AbstractUI<RequestObject>::register_thread_with_request_count));
23 template <typename RequestObject> void
24 AbstractUI<RequestObject>::register_thread (pthread_t thread_id, string name)
26 register_thread_with_request_count (thread_id, name, 256);
29 template <typename RequestObject> void
30 AbstractUI<RequestObject>::register_thread_with_request_count (pthread_t thread_id, string thread_name, uint32_t num_requests)
32 RequestBuffer* b = new RequestBuffer (num_requests);
35 Glib::Mutex::Lock lm (request_buffer_map_lock);
36 request_buffers[thread_id] = b;
39 pthread_setspecific (thread_request_buffer_key, b);
42 template <typename RequestObject> RequestObject*
43 AbstractUI<RequestObject>::get_request (RequestType rt)
45 RequestBuffer* rbuf = static_cast<RequestBuffer*>(pthread_getspecific (thread_request_buffer_key));
48 /* Cannot happen, but if it does we can't use the error reporting mechanism */
49 cerr << _("programming error: ")
50 << string_compose ("no %1-UI request buffer found for thread %2", name(), pthread_name())
55 RequestBufferVector vec;
59 rbuf->get_write_vector (&vec);
61 if (vec.len[0] == 0) {
62 if (vec.len[1] == 0) {
63 cerr << string_compose ("no space in %1-UI request buffer for thread %2", name(), pthread_name())
67 vec.buf[1]->type = rt;
71 vec.buf[0]->type = rt;
76 template <typename RequestObject> void
77 AbstractUI<RequestObject>::handle_ui_requests ()
79 RequestBufferMapIterator i;
81 request_buffer_map_lock.lock ();
83 for (i = request_buffers.begin(); i != request_buffers.end(); ++i) {
85 RequestBufferVector vec;
89 /* we must process requests 1 by 1 because
90 the request may run a recursive main
91 event loop that will itself call
92 handle_ui_requests. when we return
93 from the request handler, we cannot
94 expect that the state of queued requests
95 is even remotely consistent with
96 the condition before we called it.
99 i->second->get_read_vector (&vec);
101 if (vec.len[0] == 0) {
104 request_buffer_map_lock.unlock ();
105 do_request (vec.buf[0]);
106 request_buffer_map_lock.lock ();
107 i->second->increment_read_ptr (1);
112 request_buffer_map_lock.unlock ();
115 template <typename RequestObject> void
116 AbstractUI<RequestObject>::send_request (RequestObject *req)
118 if (base_instance() == 0) {
119 return; /* XXX is this the right thing to do ? */
122 if (caller_is_ui_thread()) {
123 // cerr << "GUI thread sent request " << req << " type = " << req->type << endl;
126 RequestBuffer* rbuf = static_cast<RequestBuffer*> (pthread_getspecific (thread_request_buffer_key));
129 /* can't use the error system to report this, because this
130 thread isn't registered!
132 cerr << _("programming error: ")
133 << string_compose ("AbstractUI::send_request() called from %1 (%2), but no request buffer exists for that thread", name(), pthread_name())
138 // cerr << "thread " << pthread_self() << " sent request " << req << " type = " << req->type << endl;
140 rbuf->increment_write_ptr (1);
142 if (signal_pipe[1] >= 0) {
144 write (signal_pipe[1], &c, 1);