Merged branch 'msgq' from http://gnuradio.org/git/jblum.git
[debian/gnuradio] / gnuradio-core / src / lib / general / gri_fft.cc
index 30b012716d932d67bf0197dbab18bb23d79d3eee..e535f28c75ea15aecdc66f0f2caa23b9a3a36aaa 100644 (file)
@@ -1,12 +1,12 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2003 Free Software Foundation, Inc.
+ * Copyright 2003,2008 Free Software Foundation, Inc.
  * 
  * This file is part of GNU Radio
  * 
  * GNU Radio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
+ * the Free Software Foundation; either version 3, or (at your option)
  * any later version.
  * 
  * GNU Radio is distributed in the hope that it will be useful,
@@ -16,8 +16,8 @@
  * 
  * You should have received a copy of the GNU General Public License
  * along with GNU Radio; see the file COPYING.  If not, write to
- * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
  */
 
 #include <gri_fft.h>
 #include <cassert>
 #include <stdexcept>
 
+
+boost::mutex &
+gri_fft_planner::mutex()
+{
+  static boost::mutex  s_planning_mutex;
+
+  return s_planning_mutex;
+}
+
 static char *
 wisdom_filename ()
 {
-  static char *filename = ".gr_fftw_wisdom";
+  static const char *filename = ".gr_fftw_wisdom";
 
   char *home = getenv ("HOME");
   if (home){
@@ -80,6 +89,9 @@ gri_fftw_export_wisdom ()
 
 gri_fft_complex::gri_fft_complex (int fft_size, bool forward)
 {
+  // Hold global mutex during plan construction and destruction.
+  gri_fft_planner::scoped_lock lock(gri_fft_planner::mutex());
+
   assert (sizeof (fftwf_complex) == sizeof (gr_complex));
   
   if (fft_size <= 0)
@@ -96,10 +108,6 @@ gri_fft_complex::gri_fft_complex (int fft_size, bool forward)
     throw std::runtime_error ("fftwf_malloc");
   }
 
-  // FIXME If there's ever a chance that the planning functions
-  // will be called in multiple threads, we've got to ensure single
-  // threaded access.  They are not thread-safe.
-  
   gri_fftw_import_wisdom ();   // load prior wisdom from disk
   d_plan = fftwf_plan_dft_1d (fft_size,
                              reinterpret_cast<fftwf_complex *>(d_inbuf), 
@@ -116,6 +124,9 @@ gri_fft_complex::gri_fft_complex (int fft_size, bool forward)
 
 gri_fft_complex::~gri_fft_complex ()
 {
+  // Hold global mutex during plan construction and destruction.
+  gri_fft_planner::scoped_lock lock(gri_fft_planner::mutex());
+
   fftwf_destroy_plan ((fftwf_plan) d_plan);
   fftwf_free (d_inbuf);
   fftwf_free (d_outbuf);
@@ -131,6 +142,9 @@ gri_fft_complex::execute ()
 
 gri_fft_real_fwd::gri_fft_real_fwd (int fft_size)
 {
+  // Hold global mutex during plan construction and destruction.
+  gri_fft_planner::scoped_lock lock(gri_fft_planner::mutex());
+
   assert (sizeof (fftwf_complex) == sizeof (gr_complex));
   
   if (fft_size <= 0)
@@ -147,10 +161,6 @@ gri_fft_real_fwd::gri_fft_real_fwd (int fft_size)
     throw std::runtime_error ("fftwf_malloc");
   }
 
-  // FIXME If there's ever a chance that the planning functions
-  // will be called in multiple threads, we've got to ensure single
-  // threaded access.  They are not thread-safe.
-  
   gri_fftw_import_wisdom ();   // load prior wisdom from disk
   d_plan = fftwf_plan_dft_r2c_1d (fft_size,
                                  d_inbuf,
@@ -166,6 +176,9 @@ gri_fft_real_fwd::gri_fft_real_fwd (int fft_size)
 
 gri_fft_real_fwd::~gri_fft_real_fwd ()
 {
+  // Hold global mutex during plan construction and destruction.
+  gri_fft_planner::scoped_lock lock(gri_fft_planner::mutex());
+
   fftwf_destroy_plan ((fftwf_plan) d_plan);
   fftwf_free (d_inbuf);
   fftwf_free (d_outbuf);
@@ -181,6 +194,9 @@ gri_fft_real_fwd::execute ()
 
 gri_fft_real_rev::gri_fft_real_rev (int fft_size)
 {
+  // Hold global mutex during plan construction and destruction.
+  gri_fft_planner::scoped_lock lock(gri_fft_planner::mutex());
+
   assert (sizeof (fftwf_complex) == sizeof (gr_complex));
   
   if (fft_size <= 0)