discuss-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Discuss-gnuradio] Thread Synchronization


From: Tom Lutz
Subject: Re: [Discuss-gnuradio] Thread Synchronization
Date: Wed, 13 May 2009 15:33:41 -0400

Please use the boost mutexs:

 #include <boost/thread.hpp>

 boost::mutex  m;                      // the mutex

 boost::mutex::scoped_lock guard(m)    // the scoped guard

Eric

Would it severely affect performance to create a boost::mutex::scoped_lock inside the function gr_oscope_guts::process_sample?  It looks to me as if this would hurt performance because this function is called for every single sample the scope receives.  If a boost::mutex is based on an OS primitive that requires a syscall.....could be sloow.

The reason I'd like to place a mutex in this function is so that the buffers can be resized per user preference while the scope is running.  In my case, I needed more than 2048 samples, so I'm working on making the scope with a configurable output record size (up to 2^21 samples per channel, or 8MiB of data per channel). 

I currently have a thread-safe *cue spock brow* way of re-allocating the buffers while the scope is running but it is not as clean as using a mutex (although it is faster, I'm sure). Here's how my method works.  Tell me if you think it is flawed or a hack-job...

Two booleans (private member vars of the gr_oscope_guts class) control the synchronization of the threads:
  bool        _update_record_count_internal;
  bool        _update_record_count_state_internal;

Thread A (the GUI), inverts the boolean _update_record_count_internal to signal the other thread to perform an action (via the set_samples_per_output_record function)

Thread B (the data flow), compares the two booleans inside the process_sample function and takes action if they are inequal. It inverts its boolean after performing the operation.

------SNIP --- Added this function to the gr_oscope_guts class------
bool gr_oscope_guts::set_samples_per_output_record(int record_size)
{
  int tmp_record_size = record_size;
  //if record_size is out of bounds, fail
  if((record_size < MINIMUM_OUTPUT_RECORD_SIZE) || (record_size > MAXIMUM_OUTPUT_RECORD_SIZE))
    return false;
  while(!(tmp_record_size&0x01)) // shift right until LSB is set, then ensure the number is a power of 2
    tmp_record_size = tmp_record_size>>1;
  if(tmp_record_size^0x1) //see if any other bits are set. if so, it is NOT a power of 2
    return false;
    _new_record_count_internal = record_size;
    _update_record_count_internal = !_update_record_count_internal; //do the actual re-allocation inside the process_sample function
}
------------------------------------------------------------------------------


----SNIP from beginning of gr_oscope_guts::process_sample(const float*)-----
  if(_update_record_count_state_internal != _update_record_count_internal)
  {
    set_samples_per_output_record_internal(_new_record_count_internal);
    _update_record_count_state_internal = !_update_record_count_state_internal;
  }
----------------------------------

The function _update_record_count_state_internal performs the actual de/re-allocation of buffers.

By the way -- what is the most graceful way of handling a failed memory allocation?

Thanks in advance,
Tom






reply via email to

[Prev in Thread] Current Thread [Next in Thread]