LALGSL.h

Go to the documentation of this file.
00001 /*
00002 *  Copyright (C) 2007 Jolien Creighton
00003 *
00004 *  This program is free software; you can redistribute it and/or modify
00005 *  it under the terms of the GNU General Public License as published by
00006 *  the Free Software Foundation; either version 2 of the License, or
00007 *  (at your option) any later version.
00008 *
00009 *  This program is distributed in the hope that it will be useful,
00010 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 *  GNU General Public License for more details.
00013 *
00014 *  You should have received a copy of the GNU General Public License
00015 *  along with with program; see the file COPYING. If not, write to the
00016 *  Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00017 *  MA  02111-1307  USA
00018 */
00019 
00020 /****************************** <lalVerbatim file="LALGSLHV">
00021 Author: Creighton, J. D. E.
00022 $Id: LALGSL.h,v 1.5 2007/06/08 14:41:52 bema Exp $
00023 ******************************* </lalVerbatim> */
00024 
00025 /* <lalLaTeX>
00026 
00027 \section{Header \texttt{LALGSL.h}}
00028 \label{s:LALGSL.h}
00029 
00030 Provides macros for integrating the GSL error handler with
00031 the LAL status structure.
00032 
00033 \subsection*{Synopsis}
00034 \begin{verbatim}
00035 #include <lal/LALGSL.h>
00036 \end{verbatim}
00037 
00038 \noindent This header provides macros and functions for tracking and
00039 reporting the runtime status of a GSL calls.  The intent is
00040 simultaneously to standardize the error reporting, and to make the
00041 reporting as transparent as possible to people coding individual
00042 routines.
00043 
00044 \emph{Please always use these macros when making a GSL call
00045 within LAL.  This will ensure that the LAL functions always have the
00046 same behaviour and will also ensure that the LAL functions are reenterant
00047 and threadsafe (when LAL is configured appropriately).}
00048 
00049 \subsubsection{GSL function calls}
00050 
00051 The behaviour of GSL functions depends on the error handler that has been
00052 assigned.  In order that LAL functions always have the same behaviour, it
00053 is necessary to use a LAL-specific GSL error handler.  This error handler
00054 populates a LAL status structure with the GSL error message and code so that
00055 GSL functions behave much the same way as LAL functions.  After the GSL
00056 functions are called, the error handler needs to be restored to the original
00057 handler so that the program calling the LAL routine has the same error handler
00058 after the LAL function was called as it did before the LAL function was called.
00059 
00060 This module provides a simple set of macros and the default LAL GSL error
00061 handler.  The macros provide a standard way to assign the LAL GSL error
00062 handler before a GSL function call and to restore the original handler after
00063 the call.
00064 
00065 Note that changing the GSL error handler is \emph{not} a thread-safe
00066 action.  Therefore it is necessary to block other threads from performing
00067 GSL function calls while one thread has changed the handler.  These macros
00068 ensure that such blocking is done for GSL function calls
00069 \emph{within other LAL routines} if LAL is configured with the
00070 \verb+--enable-pthread-lock+ flag.  See below for instructions on how
00071 to make other GSL function calls outside LAL thread-safe when used with LAL.
00072 
00073 \begin{verbatim}
00074 ATTATCHSTATUSPTR( status );
00075 CALLGSL( gsl_function( x ), status );
00076 CHECKSTATUSPTR( status );
00077 DETATCHSTATUSPTR( status );
00078 \end{verbatim}
00079 Note that the LAL function must attach (and detach) a status pointer as if
00080 a LAL routine were called.
00081 Note also that you need to use the \verb+CHECKSTATUSPTR+ macro to check
00082 the status of the call.  The equivalent to the \verb+TRY+ macro for GSL
00083 functions is the \verb+TRYGSL+ macro, which is used as follows:
00084 \begin{verbatim}
00085 ATTATCHSTATUSPTR( status );
00086 TRYGSL( gsl_function( x ), status );
00087 DETATCHSTATUSPTR( status );
00088 \end{verbatim}
00089 
00090 If you are using GSL functions both in LAL and in the calling program, and
00091 you are worried about thread-safety, the GSL function calls outside of LAL
00092 need to be blocked so that they do not access the GSL error handler while
00093 it has been changed to the LAL GSL error handler in a LAL function.  To do
00094 this, you need to do the following:
00095 \begin{verbatim}
00096 #include<lal/LALGSL.h>
00097 ...
00098 LALGSL_PTHREAD_MUTEX_LOCK;
00099 gsl_function( x );
00100 LALGSL_PTHREAD_MUTEX_UNLOCK;
00101 \end{verbatim}
00102 This ensures that \verb+gsl_function+ is not called while a LAL routine
00103 is calling a GSL function in a different thread.  You can do this even if
00104 you don't always run your code with multiple threads.  If you configure LAL
00105 without the \verb+--enable-pthread-lock+ flag, the macros
00106 \verb+LALGSL_PTHREAD_MUTEX_LOCK+ and \verb+LALGSL_PTHREAD_MUTEX_UNLOCK+
00107 do nothing.
00108 
00109 \vfill{\footnotesize\input{LALGSLHV}}
00110 \newpage\input{LALGSLC}
00111 \newpage\input{LALGSLTestC}
00112 </lalLaTeX> */
00113 
00114 #ifndef _LALGSL_H
00115 #define _LALGSL_H
00116 
00117 #include <lal/LALConfig.h>
00118 #ifdef NDEBUG 
00119 #ifndef LAL_NDEBUG
00120 #define LAL_NDEBUG
00121 #endif
00122 #endif
00123 
00124 #include <stdlib.h>
00125 #include <string.h>
00126 
00127 #include <lal/LALMalloc.h>
00128 #include <lal/LALDatatypes.h>
00129 #include <lal/LALError.h>
00130 #include <lal/LALRCSID.h>
00131 
00132 #include <lal/XLALGSL.h>
00133 
00134 #include <gsl/gsl_errno.h>
00135 
00136 #ifdef  __cplusplus
00137 extern "C" {
00138 #endif
00139 
00140 NRCSID( LALGSLH, "$Id: LALGSL.h,v 1.5 2007/06/08 14:41:52 bema Exp $" );
00141 
00142 extern LALStatus * lalGSLGlobalStatusPtr;
00143 void
00144 LALGSLErrorHandler(
00145     const char *reason,
00146     const char *file,
00147     int line,
00148     int errnum
00149     );
00150 
00151 #ifdef LAL_PTHREAD_LOCK
00152 #include <pthread.h>
00153 extern pthread_mutex_t lalGSLPthreadMutex;
00154 #define LALGSL_PTHREAD_MUTEX_LOCK pthread_mutex_lock( &lalGSLPthreadMutex )
00155 #define LALGSL_PTHREAD_MUTEX_UNLOCK pthread_mutex_unlock( &lalGSLPthreadMutex )
00156 #else
00157 #define LALGSL_PTHREAD_MUTEX_LOCK  ((void)(0))
00158 #define LALGSL_PTHREAD_MUTEX_UNLOCK  ((void)(0))
00159 #endif
00160 
00161 /*
00162  *
00163  * FIXME: Must disable pthread safety commands.... Problems arise if the
00164  * statement calls a LAL function that tries to call a GSL function using
00165  * CALLGSL ... this blocks!  TODO: Instead, use thread-specific globals.
00166  * 
00167  */
00168 
00169 #define CALLGSL( statement, statusptr )                                       \
00170   if ( (statusptr) )                                                          \
00171   {                                                                           \
00172     LALStatus *saveLALGSLGlobalStatusPtr_;                                    \
00173     gsl_error_handler_t *saveGSLErrorHandler_;                                \
00174     if ( !( (statusptr)->statusPtr ) )                                        \
00175       { ABORT( (statusptr), -8, "CALLGSL: null status pointer pointer" ); }   \
00176     /* LALGSL_PTHREAD_MUTEX_LOCK; */                                          00177     saveGSLErrorHandler_ = gsl_set_error_handler( LALGSLErrorHandler );       00178     saveLALGSLGlobalStatusPtr_ = lalGSLGlobalStatusPtr;                       00179     lalGSLGlobalStatusPtr = (statusptr)->statusPtr;                           00180     statement;                                                                00181     lalGSLGlobalStatusPtr = saveLALGSLGlobalStatusPtr_;                       00182     gsl_set_error_handler( saveGSLErrorHandler_ );                            00183     /* LALGSL_PTHREAD_MUTEX_UNLOCK; */                                        00184   }                                                                           00185   else                                                                        00186     lalAbortHook( "Abort: CALLGSL, file %s, line %d\n"                        00187                   "       Null status pointer passed to CALLGSL\n",           00188                   __FILE__, __LINE__ )
00189 
00190 
00191 #define TRYGSL( statement, statusptr )                                        \
00192   if ( (statusptr) )                                                          \
00193   {                                                                           \
00194     LALStatus *saveLALGSLGlobalStatusPtr_;                                    \
00195     gsl_error_handler_t *saveGSLErrorHandler_;                                \
00196     if ( !( (statusptr)->statusPtr ) )                                        \
00197       { ABORT( (statusptr), -8, "CALLGSL: null status pointer pointer" ); }   \
00198     /* LALGSL_PTHREAD_MUTEX_LOCK;  */                                         00199     saveGSLErrorHandler_ = gsl_set_error_handler( LALGSLErrorHandler );       00200     saveLALGSLGlobalStatusPtr_ = lalGSLGlobalStatusPtr;                       00201     lalGSLGlobalStatusPtr = (statusptr)->statusPtr;                           00202     statement;                                                                00203     lalGSLGlobalStatusPtr = saveLALGSLGlobalStatusPtr_;                       00204     gsl_set_error_handler( saveGSLErrorHandler_ );                            00205     /* LALGSL_PTHREAD_MUTEX_UNLOCK; */                                        00206     if ( (statusptr)->statusPtr->statusCode )                                 00207     {                                                                         00208       SETSTATUS( statusptr, -1, "Recursive error" );                          00209       (void) LALError( statusptr, "Statement \"" #statement "\" failed:" );   00210       (void) LALTrace( statusptr, 1 );                                        00211       return;                                                                 00212     }                                                                         00213   }                                                                           00214   else                                                                        00215     lalAbortHook( "Abort: CALLGSL, file %s, line %d\n"                        00216                   "       Null status pointer passed to CALLGSL\n",           00217                   __FILE__, __LINE__ )
00218 
00219 #ifdef  __cplusplus
00220 }
00221 #endif
00222 
00223 #endif /* _LALGSL_H */

Generated on Fri Sep 5 03:07:04 2008 for LAL by  doxygen 1.5.2