13
0

manually revert 4b3043cc and 141e6fb8181; add detailed explanatory comment

This commit is contained in:
Paul Davis 2016-01-14 09:04:59 -05:00
parent da087e920b
commit 077c65cc2a
2 changed files with 32 additions and 29 deletions

View File

@ -175,25 +175,42 @@ EventLoop::pre_register (const string& emitting_thread_name, uint32_t num_reques
AbstractUI constructor. Note that if
*/
const string key = string_compose ("%1/%2", mapping.emitting_thread, mapping.target_thread_name);
const string key = string_compose ("%1/%2", emitting_thread_name, mapping.target_thread_name);
/* note that there is no cleanup mechanism to remove
* dead/out-of-date entries from this map.
/* management of the thread_request_buffers map works as
* follows:
*
* the request buffers themselves will be cleaned up
* when the requesting thread exits (by the
* thread-local-storage (TLS) cleanup mechanism).
* when the factory method was called above, the pointer to the
* created buffer is set as a thread-local-storage (TLS) value
* for this (the emitting) thread.
*
* but an entry will remain in the map.
* The TLS value is set up with a destructor that marks the
* request buffer as "dead" when the emitting thread exits.
*
* really need a way to register some end-of-thread callback
* that will remove the entry from the thread_buffer_requests
* container. but there is no such thing in the pthreads API
* An entry will remain in the map after the thread exits.
*
* the target thread only searches the map once, when the event
* loop object is constructed. if it finds invalid buffers
* it will (a) never get any requests for them anyway (b) will
* find them marked "dead" and delete them.
* The receiving thread may (if it receives requests from other
* threads) notice the dead buffer. If it does, it will delete
* the request buffer, and call
* ::remove_request_buffer_from_map() to get rid of it from the map.
*
* This does mean that the lifetime of the request buffer is
* indeterminate: if the receiving thread were to receive no
* further requests, the request buffer will live on
* forever. But this is OK, because if there are no requests
* arriving, the receiving thread is not attempting to use the
* request buffer(s) in any way.
*
* Note, however, that *if* an emitting thread is recreated
* with the same name (e.g. when a control surface is
* enabled/disabled/enabled), then the request buffer for the
* new thread will replace the map entry for the key, because
* of the matching thread names. This does mean that
* potentially the request buffer can leak in this case, but
* (a) these buffers are not really that large anyway (b) the
* scenario is not particularly common (c) the buffers would
* typically last across a session instance if not program
* lifetime anyway.
*/
thread_buffer_requests[key] = mapping;

View File

@ -80,21 +80,7 @@ AbstractUI<RequestObject>::AbstractUI (const string& name)
{
Glib::Threads::Mutex::Lock lm (request_buffer_map_lock);
for (vector<EventLoop::ThreadBufferMapping>::iterator t = tbm.begin(); t != tbm.end(); ++t) {
RequestBuffer* rb = static_cast<RequestBuffer*> (t->request_buffer);
/* it could be dead */
if (!rb->dead) {
request_buffers[t->emitting_thread] = rb;
} else {
/* don't delete it, because we have no way to
remove it from the
EventLoop::thread_request_buffers map here,
which means that we will rediscover the
pointer in the future, and indirect to check
"dead".
*/
}
request_buffers[t->emitting_thread] = static_cast<RequestBuffer*> (t->request_buffer);
}
}
}