Made everything threadsafe.
This commit is contained in:
parent
ea12c8f494
commit
d800a8c0bc
@ -113,10 +113,6 @@ Profiler::Profiler()
|
|||||||
m_time_between_sync = 0.0;
|
m_time_between_sync = 0.0;
|
||||||
m_freeze_state = UNFROZEN;
|
m_freeze_state = UNFROZEN;
|
||||||
|
|
||||||
// By limiting the number of threads that can be created, we avoid the
|
|
||||||
// problem that all access to m_all_event_data need to be locked
|
|
||||||
// (otherwise adding a thread to m_all_event_data can trigger a
|
|
||||||
// reallocate, which makes concurrent access invalid)
|
|
||||||
m_max_frames = int( UserConfigParams::m_profiler_buffer_duration
|
m_max_frames = int( UserConfigParams::m_profiler_buffer_duration
|
||||||
* UserConfigParams::m_max_fps );
|
* UserConfigParams::m_max_fps );
|
||||||
m_current_frame = 0;
|
m_current_frame = 0;
|
||||||
@ -124,7 +120,7 @@ Profiler::Profiler()
|
|||||||
m_threads_used = 0;
|
m_threads_used = 0;
|
||||||
const int MAX_THREADS = 10;
|
const int MAX_THREADS = 10;
|
||||||
m_all_threads_data.resize(MAX_THREADS);
|
m_all_threads_data.resize(MAX_THREADS);
|
||||||
m_thread_mapping.getData().resize(MAX_THREADS);
|
m_thread_mapping.resize(MAX_THREADS);
|
||||||
m_gpu_times.resize(Q_LAST*m_max_frames);
|
m_gpu_times.resize(Q_LAST*m_max_frames);
|
||||||
} // Profile
|
} // Profile
|
||||||
|
|
||||||
@ -134,27 +130,28 @@ Profiler::~Profiler()
|
|||||||
} // ~Profiler
|
} // ~Profiler
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
/** Returns a unique index for a thread. If the calling thread is not yet in
|
||||||
|
* the mapping, it will assign a new unique id to this thread. This function
|
||||||
|
* is NOT thread-safe and must be called from a properly protected code
|
||||||
|
* section. */
|
||||||
int Profiler::getThreadID()
|
int Profiler::getThreadID()
|
||||||
{
|
{
|
||||||
m_thread_mapping.lock();
|
|
||||||
pthread_t thread = pthread_self();
|
pthread_t thread = pthread_self();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while(i < m_threads_used)
|
while(i < m_threads_used)
|
||||||
{
|
{
|
||||||
if (memcmp( &m_thread_mapping.getData()[i],
|
if (memcmp( &m_thread_mapping[i],
|
||||||
&thread,
|
&thread,
|
||||||
sizeof(thread)) ==0 )
|
sizeof(thread)) ==0 )
|
||||||
{
|
{
|
||||||
m_thread_mapping.unlock();
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
} // for i <m_threads_used
|
} // for i <m_threads_used
|
||||||
|
|
||||||
assert(m_threads_used < (int)m_thread_mapping.getData().size());
|
assert(m_threads_used < (int)m_thread_mapping.size());
|
||||||
m_thread_mapping.getData()[m_threads_used] = thread;
|
m_thread_mapping[m_threads_used] = thread;
|
||||||
m_threads_used++;
|
m_threads_used++;
|
||||||
m_thread_mapping.unlock();
|
|
||||||
|
|
||||||
return m_threads_used - 1;
|
return m_threads_used - 1;
|
||||||
} // getThreadID
|
} // getThreadID
|
||||||
@ -168,6 +165,10 @@ void Profiler::pushCPUMarker(const char* name, const video::SColor& colour)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
double start = getTimeMilliseconds() - m_time_last_sync;
|
double start = getTimeMilliseconds() - m_time_last_sync;
|
||||||
|
|
||||||
|
// We need to look before getting the thread id (since this might
|
||||||
|
// be a new thread which changes the structure).
|
||||||
|
m_lock.lock();
|
||||||
int thread_id = getThreadID();
|
int thread_id = getThreadID();
|
||||||
|
|
||||||
ThreadData &td = m_all_threads_data[thread_id];
|
ThreadData &td = m_all_threads_data[thread_id];
|
||||||
@ -182,8 +183,8 @@ void Profiler::pushCPUMarker(const char* name, const video::SColor& colour)
|
|||||||
ed.setStart(m_current_frame, start, td.m_event_stack.size());
|
ed.setStart(m_current_frame, start, td.m_event_stack.size());
|
||||||
td.m_all_event_data[name] = ed;
|
td.m_all_event_data[name] = ed;
|
||||||
}
|
}
|
||||||
|
|
||||||
td.m_event_stack.push_back(name);
|
td.m_event_stack.push_back(name);
|
||||||
|
m_lock.unlock();
|
||||||
} // pushCPUMarker
|
} // pushCPUMarker
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -194,6 +195,7 @@ void Profiler::popCPUMarker()
|
|||||||
if(m_freeze_state == FROZEN || m_freeze_state == WAITING_FOR_UNFREEZE)
|
if(m_freeze_state == FROZEN || m_freeze_state == WAITING_FOR_UNFREEZE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
m_lock.lock();
|
||||||
int thread_id = getThreadID();
|
int thread_id = getThreadID();
|
||||||
ThreadData &td = m_all_threads_data[thread_id];
|
ThreadData &td = m_all_threads_data[thread_id];
|
||||||
|
|
||||||
@ -204,6 +206,7 @@ void Profiler::popCPUMarker()
|
|||||||
getTimeMilliseconds() - m_time_last_sync);
|
getTimeMilliseconds() - m_time_last_sync);
|
||||||
|
|
||||||
td.m_event_stack.pop_back();
|
td.m_event_stack.pop_back();
|
||||||
|
m_lock.unlock();
|
||||||
} // popCPUMarker
|
} // popCPUMarker
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -222,6 +225,7 @@ void Profiler::synchronizeFrame()
|
|||||||
// which would yield different results
|
// which would yield different results
|
||||||
double now = getTimeMilliseconds();
|
double now = getTimeMilliseconds();
|
||||||
|
|
||||||
|
m_lock.lock();
|
||||||
// Set index to next frame
|
// Set index to next frame
|
||||||
int next_frame = m_current_frame+1;
|
int next_frame = m_current_frame+1;
|
||||||
if (next_frame >= m_max_frames)
|
if (next_frame >= m_max_frames)
|
||||||
@ -257,6 +261,8 @@ void Profiler::synchronizeFrame()
|
|||||||
m_freeze_state = FROZEN;
|
m_freeze_state = FROZEN;
|
||||||
else if(m_freeze_state == WAITING_FOR_UNFREEZE)
|
else if(m_freeze_state == WAITING_FOR_UNFREEZE)
|
||||||
m_freeze_state = UNFROZEN;
|
m_freeze_state = UNFROZEN;
|
||||||
|
|
||||||
|
m_lock.unlock();
|
||||||
} // synchronizeFrame
|
} // synchronizeFrame
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -269,8 +275,10 @@ void Profiler::draw()
|
|||||||
|
|
||||||
// Current frame points to the frame in which currently data is
|
// Current frame points to the frame in which currently data is
|
||||||
// being accumulated. Draw the previous (i.e. complete) frame.
|
// being accumulated. Draw the previous (i.e. complete) frame.
|
||||||
|
m_lock.lock();
|
||||||
int indx = m_current_frame - 1;
|
int indx = m_current_frame - 1;
|
||||||
if (indx < 0) indx = m_max_frames - 1;
|
if (indx < 0) indx = m_max_frames - 1;
|
||||||
|
m_lock.unlock();
|
||||||
|
|
||||||
drawBackground();
|
drawBackground();
|
||||||
|
|
||||||
@ -492,6 +500,7 @@ void Profiler::drawBackground()
|
|||||||
*/
|
*/
|
||||||
void Profiler::writeToFile()
|
void Profiler::writeToFile()
|
||||||
{
|
{
|
||||||
|
m_lock.lock();
|
||||||
std::string base_name =
|
std::string base_name =
|
||||||
file_manager->getUserConfigFile(file_manager->getStdoutName());
|
file_manager->getUserConfigFile(file_manager->getStdoutName());
|
||||||
// First CPU data
|
// First CPU data
|
||||||
@ -551,4 +560,6 @@ void Profiler::writeToFile()
|
|||||||
start = (start + 1) % m_max_frames;
|
start = (start + 1) % m_max_frames;
|
||||||
}
|
}
|
||||||
f.close();
|
f.close();
|
||||||
|
m_lock.unlock();
|
||||||
|
|
||||||
} // writeFile
|
} // writeFile
|
||||||
|
@ -219,7 +219,7 @@ private:
|
|||||||
std::vector< ThreadData> m_all_threads_data;
|
std::vector< ThreadData> m_all_threads_data;
|
||||||
|
|
||||||
/** A mapping of thread_t pointers to a unique integer (starting from 0).*/
|
/** A mapping of thread_t pointers to a unique integer (starting from 0).*/
|
||||||
Synchronised< std::vector<pthread_t> > m_thread_mapping;
|
std::vector<pthread_t> m_thread_mapping;
|
||||||
|
|
||||||
/** Buffer for the GPU times (in ms). */
|
/** Buffer for the GPU times (in ms). */
|
||||||
std::vector<int> m_gpu_times;
|
std::vector<int> m_gpu_times;
|
||||||
@ -230,6 +230,12 @@ private:
|
|||||||
/** Index of the current frame in the buffer. */
|
/** Index of the current frame in the buffer. */
|
||||||
int m_current_frame;
|
int m_current_frame;
|
||||||
|
|
||||||
|
/** We don't need the bool, but easiest way to get a lock for the whole
|
||||||
|
* instance (since we need to avoid that a synch is done which changes
|
||||||
|
* the current frame while another threaded uses this variable, or
|
||||||
|
* while a new thread is added. */
|
||||||
|
Synchronised<bool> m_lock;
|
||||||
|
|
||||||
/** True if the circular buffer has wrapped around. */
|
/** True if the circular buffer has wrapped around. */
|
||||||
bool m_has_wrapped_around;
|
bool m_has_wrapped_around;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user