From 375a2fdeb4dc162d8bdf7cd1d76d2e34e4c6fde4 Mon Sep 17 00:00:00 2001 From: David Rose Date: Tue, 12 Jun 2001 18:58:04 +0000 Subject: [PATCH] fix threading crash in pstats --- pandatool/src/gtk-stats/gtkStatsMonitor.cxx | 4 +- pandatool/src/pstatserver/pStatReader.cxx | 62 +++++++++++++++------ pandatool/src/pstatserver/pStatReader.h | 16 ++++++ 3 files changed, 61 insertions(+), 21 deletions(-) diff --git a/pandatool/src/gtk-stats/gtkStatsMonitor.cxx b/pandatool/src/gtk-stats/gtkStatsMonitor.cxx index e1bed14be3..3b5308d373 100644 --- a/pandatool/src/gtk-stats/gtkStatsMonitor.cxx +++ b/pandatool/src/gtk-stats/gtkStatsMonitor.cxx @@ -219,9 +219,7 @@ has_idle() { //////////////////////////////////////////////////////////////////// bool GtkStatsMonitor:: is_thread_safe() { - // Temporarily set to false to check a possible threading bug. In - // principle, this should work at true. - return false; + return true; } //////////////////////////////////////////////////////////////////// diff --git a/pandatool/src/pstatserver/pStatReader.cxx b/pandatool/src/pstatserver/pStatReader.cxx index fdfb60420f..6efd8a55bc 100644 --- a/pandatool/src/pstatserver/pStatReader.cxx +++ b/pandatool/src/pstatserver/pStatReader.cxx @@ -122,6 +122,7 @@ lost_connection() { //////////////////////////////////////////////////////////////////// void PStatReader:: idle() { + dequeue_frame_data(); _monitor->idle(); } @@ -267,24 +268,49 @@ handle_client_udp_data(const Datagram &datagram) { nassertv(initial_byte == 0); } - int thread_index = source.get_uint16(); - int frame_number = source.get_uint32(); - PStatFrameData *frame_data = new PStatFrameData; - frame_data->read_datagram(source, _client_data); - - // Check to see if any new collectors have level data. - int num_levels = frame_data->get_num_levels(); - for (int i = 0; i < num_levels; i++) { - int collector_index = frame_data->get_level_collector(i); - if (!_client_data->get_collector_has_level(collector_index)) { - // This collector is now reporting level data, and it wasn't - // before. - _client_data->set_collector_has_level(collector_index, true); - _monitor->new_collector(collector_index); - } + if (!_queued_frame_data.full()) { + FrameData data; + data._thread_index = source.get_uint16(); + data._frame_number = source.get_uint32(); + data._frame_data = new PStatFrameData; + data._frame_data->read_datagram(source, _client_data); + + // Queue up the data till we're ready to handle it in a + // single-threaded way. + _queued_frame_data.push_back(data); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: PStatReader::dequeue_frame_data +// Access: Private +// Description: Called during the idle loop to pull out all the frame +// data that we might have read while the threaded +// reader was running. +//////////////////////////////////////////////////////////////////// +void PStatReader:: +dequeue_frame_data() { + while (!_queued_frame_data.empty()) { + const FrameData &data = _queued_frame_data.front(); + + // Check to see if any new collectors have level data. + int num_levels = data._frame_data->get_num_levels(); + for (int i = 0; i < num_levels; i++) { + int collector_index = data._frame_data->get_level_collector(i); + if (!_client_data->get_collector_has_level(collector_index)) { + // This collector is now reporting level data, and it wasn't + // before. + _client_data->set_collector_has_level(collector_index, true); + _monitor->new_collector(collector_index); + } + } + + _client_data->record_new_frame(data._thread_index, + data._frame_number, + data._frame_data); + _monitor->new_data(data._thread_index, data._frame_number); + + _queued_frame_data.pop_front(); } - - _client_data->record_new_frame(thread_index, frame_number, frame_data); - _monitor->new_data(thread_index, frame_number); } diff --git a/pandatool/src/pstatserver/pStatReader.h b/pandatool/src/pstatserver/pStatReader.h index 48e3a4e86c..3a8da0ae3a 100644 --- a/pandatool/src/pstatserver/pStatReader.h +++ b/pandatool/src/pstatserver/pStatReader.h @@ -27,10 +27,16 @@ #include #include #include +#include class PStatServer; class PStatMonitor; class PStatClientControlMessage; +class PStatFrameData; + +// This is the maximum number of frame records that will be queued up +// from this particular client between processing loops. +static const int queued_frame_records = 500; //////////////////////////////////////////////////////////////////// // Class : PStatReader @@ -58,6 +64,7 @@ private: void handle_client_control_message(const PStatClientControlMessage &message); void handle_client_udp_data(const Datagram &datagram); + void dequeue_frame_data(); private: PStatServer *_manager; @@ -71,6 +78,15 @@ private: PT(PStatClientData) _client_data; string _hostname; + + class FrameData { + public: + int _thread_index; + int _frame_number; + PStatFrameData *_frame_data; + }; + typedef CircBuffer QueuedFrameData; + QueuedFrameData _queued_frame_data; }; #endif