From 0dc1e2357e3284a108928f9017126163a9d093f0 Mon Sep 17 00:00:00 2001 From: Stelios Bounanos Date: Wed, 2 Jan 2008 20:42:16 +0000 Subject: [PATCH] Use std::bind if available --- ChangeLog | 2 + INSTALL | 8 ++- configure.ac | 58 +++++++++++++++----- m4/ax_boost_base.m4 | 2 +- src/Makefile.am | 2 +- src/dialogs/fl_digi.cxx | 16 +++--- src/include/qrunner.h | 119 ++++++++++------------------------------ 7 files changed, 90 insertions(+), 117 deletions(-) diff --git a/ChangeLog b/ChangeLog index 95890f6c..ad9098a2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,8 @@ Change Log: 2.08 1) Use PortAudio's C API; the C++ bindings are no longer required + 2) Boost is no longer required when std::(tr1::)bind is available, as is + the case with g++ >= 4.0 2.07 1) bug fix for mode changes via SysV interface (pskmail / flarq) 2) bug fix for modem configuration post quick change from status diff --git a/INSTALL b/INSTALL index e2660bd0..3d1402bb 100644 --- a/INSTALL +++ b/INSTALL @@ -3,10 +3,12 @@ Installation Instructions for fldigi To compile fldigi you will need: - * version 1.1.x of the Fast Light Tool Kit (FLTK), with its - development libraries and headers, and + * A recent C++ compiler. The GNU C++ compilers in the 4.x series are + known to work. Building with g++ 3.x requires the development files + for the Boost C++ library. - * the development files for the Boost C++ library. + * Version 1.1.x of the Fast Light Tool Kit (FLTK), with its + development libraries and headers. You should also install the libraries and headers for PortAudio, the Portable audio I/O library. It is possible, but not recommended, to diff --git a/configure.ac b/configure.ac index afd3e07d..a38b7471 100644 --- a/configure.ac +++ b/configure.ac @@ -110,11 +110,43 @@ fi ########################### -# Boost +# bind ########################### -AX_BOOST_BASE(1.32.0) -if test "x$want_boost" = "xno"; then - AC_MSG_ERROR([Boost is required]) +# Look for a working std::bind or std::tr1::bind. If neither is present +# we will need Boost >= 1.32.0, which provides boost::bind. +AC_LANG_PUSH(C++) +AC_MSG_CHECKING([for std::bind in ]) +AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[#include + void f(void) { }]], + [[std::bind(f)();]])], + [ac_cv_std_bind=yes], [ac_cv_std_bind=no] ) +AC_MSG_RESULT([$ac_cv_std_bind]) +if test "x$ac_cv_std_bind" = "xyes"; then + AC_DEFINE(HAVE_STD_BIND, 1, [Define to 1 if we have std::bind in ]) +else + AC_DEFINE(HAVE_STD_BIND, 0, [Define to 1 if we have std::bind in ]) +fi + +if test "x$ac_cv_std_bind" = "xno"; then + AC_MSG_CHECKING([for std::tr1::bind in ]) + AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[#include + void f(void) { }]], + [[std::tr1::bind(f)();]])], + [ac_cv_std_tr1_bind=yes], [ac_cv_std_tr1_bind=no] ) + AC_MSG_RESULT([$ac_cv_std_tr1_bind]) + if test "x$ac_cv_std_tr1_bind" = "xyes"; then + AC_DEFINE(HAVE_STD_TR1_BIND, 1, [Define to 1 if we have std::tr1::bind in ]) + else + AC_DEFINE(HAVE_STD_TR1_BIND, 0, [Define to 1 if we have std::tr1::bind in ]) + fi +fi +AC_LANG_POP(C++) + +if test "x$ac_cv_std_bind" = "xno" && test "x$ac_cv_std_tr1_bind" = "xno"; then + AX_BOOST_BASE(1.32.0) + if test "x$want_boost" = "xno"; then + AC_MSG_ERROR([Boost is required]) + fi fi ########################### @@ -178,22 +210,22 @@ AC_ARG_WITH([sndfile], esac], [ac_cv_want_sndfile=check]) if test "x$ac_cv_want_sndfile" = "xno"; then - AC_DEFINE(USE_SNDFILE, 0, [Set to 1 if we are using sndfile, 0 otherwise]) + AC_DEFINE(USE_SNDFILE, 0, [Define to 1 if we are using sndfile]) ac_cv_sndfile=no else PKG_CHECK_EXISTS(sndfile >= 1.0.10, ac_cv_sndfile=yes, ac_cv_sndfile=no) if test "x$ac_cv_want_sndfile" = "xcheck"; then PKG_CHECK_MODULES(SNDFILE, sndfile >= 1.0.10, [:], [:]) if test "x$ac_cv_sndfile" = "xyes"; then - AC_DEFINE(USE_SNDFILE, 1, [Set to 1 if we are using sndfile, 0 otherwise]) + AC_DEFINE(USE_SNDFILE, 1, [Define to 1 if we are using sndfile]) else - AC_DEFINE(USE_SNDFILE, 0, [Set to 1 if we are using sndfile, 0 otherwise]) + AC_DEFINE(USE_SNDFILE, 0, [Define to 1 if we are using sndfile]) fi else # $ac_cv_want_sndfile is yes if test "x$ac_cv_sndfile" = "xno"; then AC_MSG_NOTICE([--with-sndfile was given, but test for sndfile failed]) else - AC_DEFINE(USE_SNDFILE, 1, [Set to 1 if we are using sndfile, 0 otherwise]) + AC_DEFINE(USE_SNDFILE, 1, [Define to 1 if we are using sndfile]) fi PKG_CHECK_MODULES(SNDFILE, sndfile >= 1.0.10) # for the error message fi @@ -216,13 +248,13 @@ AC_ARG_WITH([portaudio], if test "x$ac_cv_want_portaudio" = "xyes"; then PKG_CHECK_EXISTS(portaudio-2.0 >= 19, ac_cv_portaudio=yes, ac_cv_portaudio=no) if test "x$ac_cv_portaudio" = "xyes"; then - AC_DEFINE(USE_PORTAUDIO, 1, [Set to 1 if we are using PortAudio, 0 otherwise]) + AC_DEFINE(USE_PORTAUDIO, 1, [Define to 1 if we are using PortAudio]) else AC_MSG_NOTICE([portaudio test failed (use --without-portaudio to disable)]) fi PKG_CHECK_MODULES(PORTAUDIO, portaudio-2.0 >= 19) else - AC_DEFINE(USE_PORTAUDIO, 0, [Set to 1 if we are using PortAudio, 0 otherwise]) + AC_DEFINE(USE_PORTAUDIO, 0, [Define to 1 if we are using PortAudio]) ac_cv_portaudio=no fi AC_SUBST([PORTAUDIO_CFLAGS]) @@ -248,15 +280,15 @@ else if test "x$ac_cv_want_hamlib" = "xcheck"; then PKG_CHECK_MODULES(HAMLIB, hamlib >= 1.2.0, [:], [:]) if test "x$ac_cv_hamlib" = "xyes"; then - AC_DEFINE(USE_HAMLIB, 1, [Set to 1 if we are using hamlib, 0 otherwise]) + AC_DEFINE(USE_HAMLIB, 1, [Define to 1 if we are using hamlib]) else - AC_DEFINE(USE_HAMLIB, 0, [Set to 1 if we are using hamlib, 0 otherwise]) + AC_DEFINE(USE_HAMLIB, 0, [Define to 1 if we are using hamlib]) fi else # $ac_cv_want_hamlib is yes if test "x$ac_cv_hamlib" = "xno"; then AC_MSG_NOTICE([--with-hamlib was given, but test for hamlib failed]) else - AC_DEFINE(USE_HAMLIB, 1, [Set to 1 if we are using hamlib, 0 otherwise]) + AC_DEFINE(USE_HAMLIB, 1, [Define to 1 if we are using hamlib]) fi PKG_CHECK_MODULES(HAMLIB, hamlib >= 1.2.0) # for the error message fi diff --git a/m4/ax_boost_base.m4 b/m4/ax_boost_base.m4 index 6d1b05a5..2326d226 100644 --- a/m4/ax_boost_base.m4 +++ b/m4/ax_boost_base.m4 @@ -36,7 +36,7 @@ AC_DEFUN([AX_BOOST_BASE], [ AC_ARG_WITH([boost], - AS_HELP_STRING([--with-boost=DIR], [specify the root directory for boost]), + AS_HELP_STRING([--with-boost=DIR], [specify the root directory for boost @<:@autodetect@:>@]), [ if test "$withval" = "no"; then want_boost="no" diff --git a/src/Makefile.am b/src/Makefile.am index ff03c0e1..c82ed949 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -7,7 +7,7 @@ AM_CPPFLAGS = -I$(srcdir) -I$(srcdir)/include -I$(srcdir)/irrxml @BOOST_CPPFLAGS AM_CXXFLAGS = @FLTK_CFLAGS@ @PORTAUDIO_CFLAGS@ @SNDFILE_CFLAGS@ \ @SAMPLERATE_CFLAGS@ @HAMLIB_CFLAGS@ \ - -pipe -Wall -O2 -ffast-math -fno-rtti -fexceptions -finline-functions + -pipe -Wall -O2 -ffast-math -fexceptions -finline-functions AM_CFLAGS = $(AM_CXXFLAGS) LDADD = @BOOST_LDFLAGS@ @FLTK_LIBS@ @PORTAUDIO_LIBS@ @SNDFILE_LIBS@ \ diff --git a/src/dialogs/fl_digi.cxx b/src/dialogs/fl_digi.cxx index 55da7e2a..a7cf038b 100644 --- a/src/dialogs/fl_digi.cxx +++ b/src/dialogs/fl_digi.cxx @@ -1202,7 +1202,7 @@ void put_Bandwidth(int bandwidth) void display_metric(double metric) { FL_LOCK_D(); - QUEUE(CMP_CB(&Fl_Progress::value, pgrsSquelch, metric)); //pgrsSquelch->value(metric); + QUEUE(CMP_CB(static_cast(&Fl_Progress::value), pgrsSquelch, metric)); //pgrsSquelch->value(metric); FL_UNLOCK_D(); FL_AWAKE_D(); } @@ -1213,8 +1213,8 @@ void put_cwRcvWPM(double wpm) int L = progdefaults.CWlowerlimit; double dWPM = 100.0*(wpm - L)/(U - L); FL_LOCK_D(); - QUEUE(CMP_CB(&Fl_Progress::value, prgsCWrcvWPM, dWPM)); //prgsCWrcvWPM->value(dWPM); - QUEUE(CMP_CB(&Fl_Value_Output::value, valCWrcvWPM, (int)wpm)); //valCWrcvWPM->value((int)wpm); + QUEUE(CMP_CB(static_cast(&Fl_Progress::value), prgsCWrcvWPM, dWPM)); //prgsCWrcvWPM->value(dWPM); + QUEUE(CMP_CB(static_cast(&Fl_Value_Output::value), valCWrcvWPM, (int)wpm)); //valCWrcvWPM->value((int)wpm); FL_UNLOCK_D(); FL_AWAKE_D(); } @@ -1295,7 +1295,7 @@ void put_sec_char( char chr ) if (strSecText.length() > 60) strSecText.erase(0,1); FL_LOCK_D(); - QUEUE(CMP_CB(&Fl_Box::label, StatusBar, strSecText.c_str())); //StatusBar->label(strSecText.c_str()); + QUEUE(CMP_CB(static_cast(&Fl_Box::label), StatusBar, strSecText.c_str())); //StatusBar->label(strSecText.c_str()); FL_UNLOCK_D(); FL_AWAKE_D(); } @@ -1313,7 +1313,7 @@ void put_status(const char *msg, double timeout) m[sizeof(m) - 1] = '\0'; FL_LOCK_D(); - QUEUE(CMP_CB(&Fl_Box::label, StatusBar, m)); // StatusBar->label(m); + QUEUE(CMP_CB(static_cast(&Fl_Box::label), StatusBar, m)); // StatusBar->label(m); // While it is safe to call to use Fl::add_timeout without qrunner // regardless of our caller's context, queuing ensures that clear_status_cb // really gets called at least ``timeout'' seconds after the label is set. @@ -1332,7 +1332,7 @@ void put_Status2(const char *msg) m[sizeof(m) - 1] = '\0'; FL_LOCK_D(); - QUEUE(CMP_CB(&Fl_Box::label, Status2, m)); //Status2->label(m); + QUEUE(CMP_CB(static_cast(&Fl_Box::label), Status2, m)); //Status2->label(m); FL_UNLOCK_D(); FL_AWAKE_D(); } @@ -1344,7 +1344,7 @@ void put_Status1(const char *msg) m[sizeof(m) - 1] = '\0'; FL_LOCK_D(); - QUEUE(CMP_CB(&Fl_Box::label, Status1, m)); //Status1->label(m); + QUEUE(CMP_CB(static_cast(&Fl_Box::label), Status1, m)); //Status1->label(m); FL_UNLOCK_D(); FL_AWAKE_D(); } @@ -1387,7 +1387,7 @@ void clear_StatusMessages() void put_MODEstatus(trx_mode mode) { FL_LOCK_D(); - QUEUE(CMP_CB(&Fl_Button::label, MODEstatus, mode_info[mode].sname)); //MODEstatus->label(mode_names[mode]); + QUEUE(CMP_CB(static_cast(&Fl_Button::label), MODEstatus, mode_info[mode].sname)); //MODEstatus->label(mode_names[mode]); FL_UNLOCK_D(); FL_AWAKE_D(); } diff --git a/src/include/qrunner.h b/src/include/qrunner.h index ae5404fd..7303f5eb 100644 --- a/src/include/qrunner.h +++ b/src/include/qrunner.h @@ -24,14 +24,23 @@ #define QRUNNER_H_ #ifndef NDEBUG -# include +# include #endif #include #include #include -#include -#include + +#if HAVE_STD_BIND +# include + using std::bind; +#elif HAVE_STD_TR1_BIND +# include + using std::tr1::bind; +#else +# include + using boost::bind; +#endif #include "threads.h" #include "qrunner/fqueue.h" @@ -48,66 +57,24 @@ private: std::string msg; }; -struct signal_after +struct fsignal { + typedef void result_type; Fl_Mutex *m; Fl_Cond *c; - signal_after(Fl_Mutex *m_, Fl_Cond *c_) : m(m_), c(c_) { } - template - void operator()(const F& f) const + fsignal(Fl_Mutex *m_, Fl_Cond *c_) : m(m_), c(c_) { } + void operator()(void) const { - f(); fl_lock(m); fl_cond_signal(c); fl_unlock(m); } }; -struct deadline -{ - struct timespec dl; - - deadline(const struct timespec &dl_) : dl(dl_) { } - template - void operator()(const F& f) const - { - struct timespec now; - if (clock_gettime(CLOCK_REALTIME, &now) == -1) - throw qexception(errno); - - if (dl > now) - f(); -#ifndef NDEBUG - else - std::cerr << "too late for event\n"; -#endif - } -}; - -#ifndef NDEBUG -struct timer -{ - struct timespec t; - - timer(const struct timespec &t_) : t(t_) { } - template - void operator()(const F& f) const - { - struct timespec now; - if (clock_gettime(CLOCK_REALTIME, &now) == -1) - throw qexception(errno); - - struct timespec diff = now - t; - std::cout << "t: " << (double)diff.tv_sec + diff.tv_nsec/1e9 << '\n'; - - f(); - } -}; -#endif - struct nop { + typedef void result_type; void operator()(void) const { } }; @@ -146,13 +113,17 @@ public: if (!attached) return request(f, pri); + for (;;) { + if (request(f, pri)) + break; + sched_yield(); + } Fl_Mutex m = PTHREAD_MUTEX_INITIALIZER; Fl_Cond c = PTHREAD_COND_INITIALIZER; - + fsignal s(&m, &c); fl_lock(&m); - signal_after sa(&m, &c); for (;;) { - if (request(boost::bind(sa, f), pri)) + if (request(s, pri)) break; sched_yield(); } @@ -162,30 +133,6 @@ public: return true; } - template - bool request_dl(const F &f, double dtime, size_t pri = 0) - { - struct timespec now, dl; - if (clock_gettime(CLOCK_REALTIME, &now) == -1) - throw qexception(errno); - dl = now + dtime; - - deadline d(dl); - return request(boost::bind(d, f), pri); - } - -#ifndef NDEBUG - template - bool request_time(const F &f, size_t pri = 0) - { - struct timespec now; - if (clock_gettime(CLOCK_REALTIME, &now) == -1) - throw qexception(errno); - timer t(now); - return request(boost::bind(t, f), pri); - } -#endif - static void execute(int fd, void *arg); void flush(void); @@ -211,29 +158,19 @@ extern qrunner *cbq[NUM_QRUNNER_THREADS]; #define QUEUE_ASYNC(...) \ do { \ if (GET_THREAD_ID() != FLMAIN_TID) \ - cbq[GET_THREAD_ID()]->request(boost::bind(__VA_ARGS__)); \ + cbq[GET_THREAD_ID()]->request(bind(__VA_ARGS__)); \ else \ - boost::bind(__VA_ARGS__)(); \ + bind(__VA_ARGS__)(); \ } while (0) #define QUEUE_SYNC(...) \ do { \ if (GET_THREAD_ID() != FLMAIN_TID) \ - cbq[GET_THREAD_ID()]->request_sync(boost::protect(boost::bind(__VA_ARGS__))); \ + cbq[GET_THREAD_ID()]->request_sync(bind(__VA_ARGS__)); \ else \ - boost::bind(__VA_ARGS__)(); \ + bind(__VA_ARGS__)(); \ } while (0) -#define QUEUE_DL(d_, ...) \ - do { \ - if (GET_THREAD_ID() != FLMAIN_TID) \ - cbq[GET_THREAD_ID()]->request_dl(boost::protect(boost::bind(__VA_ARGS__)), d_); \ - else \ - boost::bind(__VA_ARGS__)(); \ - } while (0) - - - #define QUEUE_FLUSH() \ do { \ if (GET_THREAD_ID() != FLMAIN_TID) \