[Installation Guides] Building OpenCV 3.1 SfM sample code in Windows 10 with MSVC 2015
#include <algorithm>
at the beginning of fileconst int copy = min<int>(data_->num_chars_to_log_,
sizeof(fatal_message)-1);
to
const int copy = std::min<int>(data_->num_chars_to_log_,
sizeof(fatal_message)-1);
./glog-0.3.3
to ./ceres-windows-master/glog
../ceres-solver-1.11.0
to ./ceres-windows-master/ceres-solver
../eigen-eigen-ce5a455b34c0
to ./ceres-windows-master\eigen
.In order to run OpenCV Sfm example we need to build the libmv and replacing them onto the "light version" module (libmv_light) that comes with opencv_contribute. At the moment it will be too complicated to build all modules for libmv on Windows environment, for now we only focus on the modules that is required to build the OpenCV Sfm example.
libmv-master\src\libmv
Copy the following files under ./libmv_light/libmv/base
and replace these files under ./libmv-master/src/libmv/base
.
Copy the following files under ./libmv_light/libmv/correspondence
and replace these files under ./libmv-master/src/libmv/correspondence
.
Change the CMakeLists.txt as follow:
# define the source files
SET(CORRESPONDENCE_SRC matches.cc
feature_matching.cc
nRobustViewMatching.cc)
# define the header files (make the headers appear in IDEs.)
FILE(GLOB CORRESPONDENCE_HDRS *.h)
ADD_LIBRARY(correspondence ${CORRESPONDENCE_SRC} ${CORRESPONDENCE_HDRS})
# make the name of debug libraries end in _d.
SET_TARGET_PROPERTIES(correspondence PROPERTIES DEBUG_POSTFIX "_d")
TARGET_LINK_LIBRARIES(correspondence multiview)
# installation rules for the library
LIBMV_INSTALL_LIB(correspondence)
# LIBMV_TEST(klt "correspondence;image;numeric")
# LIBMV_TEST(bipartite_graph "")
# LIBMV_TEST(kdtree "")
# LIBMV_TEST(feature_set "correspondence;image;numeric")
# LIBMV_TEST(matches "correspondence;image;numeric")
# LIBMV_TEST(Array_Matcher "correspondence;numeric;flann")
# LIBMV_TEST(tracker "correspondence;reconstruction;numeric;flann")
Copy the following files under ./libmv_light/libmv/multiview
and replace these files under ./libmv-master/src/libmv/multiview
.
Change the CMakeLists.txt as follow:
# define the source files
SET(MULTIVIEW_SRC conditioning.cc
euclidean_resection.cc
fundamental.cc
fundamental_kernel.cc
homography.cc
panography.cc
panography_kernel.cc
projection.cc
robust_estimation.cc
robust_fundamental.cc
robust_resection.cc
triangulation.cc
twoviewtriangulation.cc)
# define the header files (make the headers appear in IDEs.)
FILE(GLOB MULTIVIEW_HDRS *.h)
ADD_LIBRARY(multiview ${MULTIVIEW_SRC} ${MULTIVIEW_HDRS})
TARGET_LINK_LIBRARIES(multiview numeric V3D colamd ldl)
# make the name of debug libraries end in _d.
SET_TARGET_PROPERTIES(multiview PROPERTIES DEBUG_POSTFIX "_d")
# installation rules for the library
LIBMV_INSTALL_LIB(multiview)
#IF (BUILD_TESTS)
#ADD_LIBRARY(multiview_test_data
# test_data_sets.cc)
# make the name of debug libraries end in _d.
#SET_TARGET_PROPERTIES(multiview_test_data PROPERTIES DEBUG_POSTFIX "_d")
#ENDIF (BUILD_TESTS)
#MACRO (MULTIVIEW_TEST NAME)
# LIBMV_TEST(${NAME} "multiview_test_data;multiview;numeric")
#ENDMACRO (MULTIVIEW_TEST)
#MULTIVIEW_TEST(projection)
#MULTIVIEW_TEST(triangulation)
#MULTIVIEW_TEST(fundamental)
#MULTIVIEW_TEST(fundamental_kernel)
#MULTIVIEW_TEST(fundamental_parameterization)
#MULTIVIEW_TEST(homography)
#MULTIVIEW_TEST(homography_error)
#MULTIVIEW_TEST(homography_kernel)
#MULTIVIEW_TEST(homography_parameterization)
#MULTIVIEW_TEST(panography)
#MULTIVIEW_TEST(focal_from_fundamental)
#MULTIVIEW_TEST(nviewtriangulation)
#MULTIVIEW_TEST(resection)
#MULTIVIEW_TEST(resection_kernel)
#MULTIVIEW_TEST(robust_homography)
#MULTIVIEW_TEST(robust_fundamental)
#MULTIVIEW_TEST(robust_estimation)
#MULTIVIEW_TEST(sixpointnview)
#MULTIVIEW_TEST(bundle)
#MULTIVIEW_TEST(autocalibration)
#MULTIVIEW_TEST(five_point)
#MULTIVIEW_TEST(five_point_kernel)
#MULTIVIEW_TEST(essential_kernel)
#MULTIVIEW_TEST(affine)
#MULTIVIEW_TEST(affine_kernel)
#MULTIVIEW_TEST(affine_parameterization)
#MULTIVIEW_TEST(robust_affine)
#MULTIVIEW_TEST(euclidean_resection)
#MULTIVIEW_TEST(euclidean_resection_kernel)
#MULTIVIEW_TEST(robust_euclidean_resection)
#MULTIVIEW_TEST(twoviewtriangulation)
#MULTIVIEW_TEST(robust_resection)
#MULTIVIEW_TEST(similarity)
#MULTIVIEW_TEST(similarity_kernel)
#MULTIVIEW_TEST(similarity_parameterization)
#MULTIVIEW_TEST(robust_similarity)
#MULTIVIEW_TEST(euclidean)
#MULTIVIEW_TEST(euclidean_kernel)
#MULTIVIEW_TEST(euclidean_parameterization)
#MULTIVIEW_TEST(robust_euclidean)
#MULTIVIEW_TEST(rotation_parameterization)
# TODO(keir): Make tests that depend on generated.cc to use generated sources.
#ADD_GENERATED_SOURCE(generated.cc generator.py)
Copy the following files under ./libmv_light/libmv/numeric
and replace these files under ./libmv-master/src/libmv/numeric
.
Since there is no simple_pipeline module in libmv, simply copy the whole simple_pipeline folder and paste it to ./libmv-master/src/libmv
.
Change the CMakeLists.txt as follow:
SET(SIMPLE_PIPELINE_SRC
bundle.cc
camera_intrinsics.cc
distortion_models.cc
initialize_reconstruction.cc
intersect.cc
keyframe_selection.cc
pipeline.cc
reconstruction.cc
reconstruction_scale.cc
resect.cc
tracks.cc
)
# Define the header files so that they appear in IDEs.
FILE(GLOB SIMPLE_PIPELINE_HDRS *.h)
ADD_LIBRARY(simple_pipeline STATIC ${SIMPLE_PIPELINE_SRC} ${SIMPLE_PIPELINE_HDRS})
TARGET_LINK_LIBRARIES(simple_pipeline multiview)
LIBMV_INSTALL_LIB(simple_pipeline)
libmv-master\src\libmv
Now all the modules has been replaced, we also need to modify the CMakeList.txt under ./libmv-master/src/libmv/
.
Change the CMakeLists.txt as follow:
ADD_SUBDIRECTORY(base)
ADD_SUBDIRECTORY(camera)
ADD_SUBDIRECTORY(detector)
ADD_SUBDIRECTORY(descriptor)
ADD_SUBDIRECTORY(image)
ADD_SUBDIRECTORY(numeric)
ADD_SUBDIRECTORY(correspondence)
ADD_SUBDIRECTORY(optimize)
ADD_SUBDIRECTORY(multiview)
ADD_SUBDIRECTORY(reconstruction)
ADD_SUBDIRECTORY(scene_graph)
ADD_SUBDIRECTORY(tools)
ADD_SUBDIRECTORY(simple_pipeline)
#Installation macro for all headers
LIBMV_INSTALL_ALL_HEADERS()
ibmv-master\src\third_party
Copy the following folders under ceres-windows-master\eigen
and replace them to libmv-master\src\third_party\eigen
Copy the following files under glog-0.3.3\src\glog
and replace them to libmv-master\src\third_party\glog\src\glog
Copy the following files under glog-0.3.3\src\windows\glog
and replace them to libmv-master\src\third_party\glog\src\windows\glog
.
Open logging.h
and inser the following code below line #1146
LogStream(const LogStream &) = delete;
void operator=(const LogStream &) = delete;
Open ``libmv-master\src\third_party\glog\src\windows\port.cc``` and modify the code from line #59 - #65 with the following code:
#if !(defined(_MSC_VER) && (_MSC_VER >= 1900))
int snprintf(char *str, size_t size, const char *format, ...) {
va_list ap;
va_start(ap, format);
const int r = vsnprintf(str, size, format, ap);
va_end(ap);
return r;
}
#endif
Copy the following file under glog-0.3.3\src
and replace it to libmv-master\src\third_party\glog\src
libmv-master
libmv-master\src\third_party\glog\src\glog.logging.h
###Change the code from line #130 - #136 to the following code:
#ifndef GOOGLE_PREDICT_BRANCH_NOT_TAKEN
#if 0
#define GOOGLE_PREDICT_BRANCH_NOT_TAKEN(x) (__builtin_expect(x, 0))
#define GOOGLE_PREDICT_FALSE(x) (__builtin_expect(x, 0))
#define GOOGLE_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
#else
#define GOOGLE_PREDICT_BRANCH_NOT_TAKEN(x) x
#define GOOGLE_PREDICT_FALSE(x) x
#define GOOGLE_PREDICT_TRUE(x) x
#endif
#endif
libmv-master\src\libmv\numeric\poly.h
###Above line #24 insert the following code:
#define M_E 2.71828182845904523536
#define M_LOG2E 1.44269504088896340736
#define M_LOG10E 0.434294481903251827651
#define M_LN2 0.693147180559945309417
#define M_LN10 2.30258509299404568402
#define M_PI 3.14159265358979323846
#define M_PI_2 1.57079632679489661923
#define M_PI_4 0.785398163397448309616
#define M_1_PI 0.318309886183790671538
#define M_2_PI 0.636619772367581343076
#define M_2_SQRTPI 1.12837916709551257390
#define M_SQRT2 1.41421356237309504880
#define M_SQRT1_2 0.707106781186547524401
libmv-master\src\third_party\gflags\gflags.cc
###Open gflags.cc and modify the code from line #383 - #406 with the following code:
string FlagValue::ToString() const {
char intbuf[64]; // enough to hold even the biggest number
switch (type_) {
case FV_BOOL:
return VALUE_AS(bool) ? "true" : "false";
case FV_INT32:
snprintf(intbuf, sizeof(intbuf), "%d", VALUE_AS(int32));
return intbuf;
case FV_INT64:
snprintf(intbuf, sizeof(intbuf), "%llu", VALUE_AS(int64));
return intbuf;
case FV_UINT64:
snprintf(intbuf, sizeof(intbuf), "%llu", VALUE_AS(uint64));
return intbuf;
case FV_DOUBLE:
snprintf(intbuf, sizeof(intbuf), "%.17g", VALUE_AS(double));
return intbuf;
case FV_STRING:
return VALUE_AS(string);
default:
assert(false);
return ""; // unknown type
}
}
libmv-master\src\third_party\pthreads-w32\include\pthread.h
###Open pthread.h and modify the code from line #307 - #310 with the following code:
//struct timespec {
// long tv_sec;
// long tv_nsec;
//};
\libmv-master\src
and build binaries to \libmv-master\src\build
. Then press configure then generate.Before building, open the project property and add the following configuration to ** Additional Include Directories **.
correspondence
C:\ceres-windows-master\glog\src\windows;
$(OPENCV_DIR)\build\include;
multiview
C:\ceres-windows-master\glog\src\windows;
simple_pipeline
C:\ceres-windows-master\glog\src\windows;
C:\ceres-windows-master\win\include;
C:\ceres-windows-master\ceres-solver\include;
After the build is done, you should obtain the following packages:
correspondence_d.lib
correspondence.lib
gflags_d.lib (Need to rename yourself after building)
gflags.lib
multiview_d.lib
multiview.lib
numeric_d.lib
numeric.lib
simple_pipeline_d.lib (Need to rename yourself after building)
simple_pipeline.lib
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_XPRHELPER_H
#define EIGEN_XPRHELPER_H
// just a workaround because GCC seems to not really like empty structs
// FIXME: gcc 4.3 generates bad code when strict-aliasing is enabled
// so currently we simply disable this optimization for gcc 4.3
#if EIGEN_COMP_GNUC && !EIGEN_GNUC_AT(4,3)
#define EIGEN_EMPTY_STRUCT_CTOR(X) \
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE X() {} \
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE X(const X& ) {}
#else
#define EIGEN_EMPTY_STRUCT_CTOR(X)
#endif
namespace Eigen {
typedef EIGEN_DEFAULT_DENSE_INDEX_TYPE DenseIndex;
/**
* \brief The Index type as used for the API.
* \details To change this, \c \#define the preprocessor symbol \c EIGEN_DEFAULT_DENSE_INDEX_TYPE.
* \sa \ref TopicPreprocessorDirectives, StorageIndex.
*/
typedef EIGEN_DEFAULT_DENSE_INDEX_TYPE Index;
namespace internal {
template<typename IndexDest, typename IndexSrc>
EIGEN_DEVICE_FUNC
inline IndexDest convert_index(const IndexSrc& idx) {
// for sizeof(IndexDest)>=sizeof(IndexSrc) compilers should be able to optimize this away:
eigen_internal_assert(idx <= NumTraits<IndexDest>::highest() && "Index value to big for target type");
return IndexDest(idx);
}
//classes inheriting no_assignment_operator don't generate a default operator=.
class no_assignment_operator
{
private:
no_assignment_operator& operator=(const no_assignment_operator&);
};
/** \internal return the index type with the largest number of bits */
template<typename I1, typename I2>
struct promote_index_type
{
typedef typename conditional<(sizeof(I1)<sizeof(I2)), I2, I1>::type type;
};
/** \internal If the template parameter Value is Dynamic, this class is just a wrapper around a T variable that
* can be accessed using value() and setValue().
* Otherwise, this class is an empty structure and value() just returns the template parameter Value.
*/
template<typename T, int Value> class variable_if_dynamic
{
public:
EIGEN_EMPTY_STRUCT_CTOR(variable_if_dynamic)
EIGEN_DEVICE_FUNC explicit variable_if_dynamic(T v) { EIGEN_ONLY_USED_FOR_DEBUG(v); eigen_assert(v == T(Value)); }
EIGEN_DEVICE_FUNC static T value() { return T(Value); }
EIGEN_DEVICE_FUNC void setValue(T) {}
};
template<typename T> class variable_if_dynamic<T, Dynamic>
{
T m_value;
EIGEN_DEVICE_FUNC variable_if_dynamic() { eigen_assert(false); }
public:
EIGEN_DEVICE_FUNC explicit variable_if_dynamic(T value) : m_value(value) {}
EIGEN_DEVICE_FUNC T value() const { return m_value; }
EIGEN_DEVICE_FUNC void setValue(T value) { m_value = value; }
};
/** \internal like variable_if_dynamic but for DynamicIndex
*/
template<typename T, int Value> class variable_if_dynamicindex
{
public:
EIGEN_EMPTY_STRUCT_CTOR(variable_if_dynamicindex)
EIGEN_DEVICE_FUNC explicit variable_if_dynamicindex(T v) { EIGEN_ONLY_USED_FOR_DEBUG(v); eigen_assert(v == T(Value)); }
EIGEN_DEVICE_FUNC static T value() { return T(Value); }
EIGEN_DEVICE_FUNC void setValue(T) {}
};
template<typename T> class variable_if_dynamicindex<T, DynamicIndex>
{
T m_value;
EIGEN_DEVICE_FUNC variable_if_dynamicindex() { eigen_assert(false); }
public:
EIGEN_DEVICE_FUNC explicit variable_if_dynamicindex(T value) : m_value(value) {}
EIGEN_DEVICE_FUNC T value() const { return m_value; }
EIGEN_DEVICE_FUNC void setValue(T value) { m_value = value; }
};
template<typename T> struct functor_traits
{
enum
{
Cost = 10,
PacketAccess = false,
IsRepeatable = false
};
};
template<typename T> struct packet_traits;
template<typename T> struct unpacket_traits
{
typedef T type;
typedef T half;
enum
{
size = 1,
alignment = 1
};
};
template<int Size, typename PacketType,
bool Stop = Size==Dynamic || (Size%unpacket_traits<PacketType>::size)==0 || is_same<PacketType,typename unpacket_traits<PacketType>::half>::value>
struct find_best_packet_helper;
template< int Size, typename PacketType>
struct find_best_packet_helper<Size,PacketType,true>
{
typedef PacketType type;
};
template<int Size, typename PacketType>
struct find_best_packet_helper<Size,PacketType,false>
{
typedef typename find_best_packet_helper<Size,typename unpacket_traits<PacketType>::half>::type type;
};
template<typename T, int Size>
struct find_best_packet
{
typedef typename find_best_packet_helper<Size,typename packet_traits<T>::type>::type type;
};
#if EIGEN_MAX_STATIC_ALIGN_BYTES>0
template<int ArrayBytes, int AlignmentBytes,
bool Match = bool((ArrayBytes%AlignmentBytes)==0),
bool TryHalf = bool(AlignmentBytes>EIGEN_MIN_ALIGN_BYTES) >
struct compute_default_alignment_helper
{
enum { value = 0 };
};
template<int ArrayBytes, int AlignmentBytes, bool TryHalf>
struct compute_default_alignment_helper<ArrayBytes, AlignmentBytes, true, TryHalf> // Match
{
enum { value = AlignmentBytes };
};
template<int ArrayBytes, int AlignmentBytes>
struct compute_default_alignment_helper<ArrayBytes, AlignmentBytes, false, true> // Try-half
{
// current packet too large, try with an half-packet
enum { value = compute_default_alignment_helper<ArrayBytes, AlignmentBytes/2>::value };
};
#else
// If static alignment is disabled, no need to bother.
// This also avoids a division by zero in "bool Match = bool((ArrayBytes%AlignmentBytes)==0)"
template<int ArrayBytes, int AlignmentBytes>
struct compute_default_alignment_helper
{
enum { value = 0 };
};
#endif
template<typename T, int Size> struct compute_default_alignment {
enum { value = compute_default_alignment_helper<Size*sizeof(T),EIGEN_MAX_STATIC_ALIGN_BYTES>::value };
};
template<typename T> struct compute_default_alignment<T,Dynamic> {
enum { value = EIGEN_MAX_ALIGN_BYTES };
};
template<typename _Scalar, int _Rows, int _Cols,
int _Options = AutoAlign |
( (_Rows==1 && _Cols!=1) ? RowMajor
: (_Cols==1 && _Rows!=1) ? ColMajor
: EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION ),
int _MaxRows = _Rows,
int _MaxCols = _Cols
> class make_proper_matrix_type
{
enum {
IsColVector = _Cols==1 && _Rows!=1,
IsRowVector = _Rows==1 && _Cols!=1,
Options = IsColVector ? (_Options | ColMajor) & ~RowMajor
: IsRowVector ? (_Options | RowMajor) & ~ColMajor
: _Options
};
public:
typedef Matrix<_Scalar, _Rows, _Cols, Options, _MaxRows, _MaxCols> type;
};
template<typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
class compute_matrix_flags
{
enum { row_major_bit = Options&RowMajor ? RowMajorBit : 0 };
public:
// FIXME currently we still have to handle DirectAccessBit at the expression level to handle DenseCoeffsBase<>
// and then propagate this information to the evaluator's flags.
// However, I (Gael) think that DirectAccessBit should only matter at the evaluation stage.
enum { ret = DirectAccessBit | LvalueBit | NestByRefBit | row_major_bit };
};
template<int _Rows, int _Cols> struct size_at_compile_time
{
enum { ret = (_Rows==Dynamic || _Cols==Dynamic) ? Dynamic : _Rows * _Cols };
};
template<typename XprType> struct size_of_xpr_at_compile_time
{
enum { ret = size_at_compile_time<traits<XprType>::RowsAtCompileTime,traits<XprType>::ColsAtCompileTime>::ret };
};
/* plain_matrix_type : the difference from eval is that plain_matrix_type is always a plain matrix type,
* whereas eval is a const reference in the case of a matrix
*/
template<typename T, typename StorageKind = typename traits<T>::StorageKind> struct plain_matrix_type;
template<typename T, typename BaseClassType, int Flags> struct plain_matrix_type_dense;
template<typename T> struct plain_matrix_type<T,Dense>
{
typedef typename plain_matrix_type_dense<T,typename traits<T>::XprKind, traits<T>::Flags>::type type;
};
template<typename T> struct plain_matrix_type<T,DiagonalShape>
{
typedef typename T::PlainObject type;
};
template<typename T, int Flags> struct plain_matrix_type_dense<T,MatrixXpr,Flags>
{
typedef Matrix<typename traits<T>::Scalar,
traits<T>::RowsAtCompileTime,
traits<T>::ColsAtCompileTime,
AutoAlign | (Flags&RowMajorBit ? RowMajor : ColMajor),
traits<T>::MaxRowsAtCompileTime,
traits<T>::MaxColsAtCompileTime
> type;
};
template<typename T, int Flags> struct plain_matrix_type_dense<T,ArrayXpr,Flags>
{
typedef Array<typename traits<T>::Scalar,
traits<T>::RowsAtCompileTime,
traits<T>::ColsAtCompileTime,
AutoAlign | (Flags&RowMajorBit ? RowMajor : ColMajor),
traits<T>::MaxRowsAtCompileTime,
traits<T>::MaxColsAtCompileTime
> type;
};
/* eval : the return type of eval(). For matrices, this is just a const reference
* in order to avoid a useless copy
*/
template<typename T, typename StorageKind = typename traits<T>::StorageKind> struct eval;
template<typename T> struct eval<T,Dense>
{
typedef typename plain_matrix_type<T>::type type;
// typedef typename T::PlainObject type;
// typedef T::Matrix<typename traits<T>::Scalar,
// traits<T>::RowsAtCompileTime,
// traits<T>::ColsAtCompileTime,
// AutoAlign | (traits<T>::Flags&RowMajorBit ? RowMajor : ColMajor),
// traits<T>::MaxRowsAtCompileTime,
// traits<T>::MaxColsAtCompileTime
// > type;
};
template<typename T> struct eval<T,DiagonalShape>
{
typedef typename plain_matrix_type<T>::type type;
};
// for matrices, no need to evaluate, just use a const reference to avoid a useless copy
template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
struct eval<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>, Dense>
{
typedef const Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>& type;
};
template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
struct eval<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>, Dense>
{
typedef const Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>& type;
};
/* similar to plain_matrix_type, but using the evaluator's Flags */
template<typename T, typename StorageKind = typename traits<T>::StorageKind> struct plain_object_eval;
template<typename T>
struct plain_object_eval<T,Dense>
{
typedef typename plain_matrix_type_dense<T,typename traits<T>::XprKind, evaluator<T>::Flags>::type type;
};
/* plain_matrix_type_column_major : same as plain_matrix_type but guaranteed to be column-major
*/
template<typename T> struct plain_matrix_type_column_major
{
enum { Rows = traits<T>::RowsAtCompileTime,
Cols = traits<T>::ColsAtCompileTime,
MaxRows = traits<T>::MaxRowsAtCompileTime,
MaxCols = traits<T>::MaxColsAtCompileTime
};
typedef Matrix<typename traits<T>::Scalar,
Rows,
Cols,
(MaxRows==1&&MaxCols!=1) ? RowMajor : ColMajor,
MaxRows,
MaxCols
> type;
};
/* plain_matrix_type_row_major : same as plain_matrix_type but guaranteed to be row-major
*/
template<typename T> struct plain_matrix_type_row_major
{
enum { Rows = traits<T>::RowsAtCompileTime,
Cols = traits<T>::ColsAtCompileTime,
MaxRows = traits<T>::MaxRowsAtCompileTime,
MaxCols = traits<T>::MaxColsAtCompileTime
};
typedef Matrix<typename traits<T>::Scalar,
Rows,
Cols,
(MaxCols==1&&MaxRows!=1) ? RowMajor : ColMajor,
MaxRows,
MaxCols
> type;
};
/** \internal The reference selector for template expressions. The idea is that we don't
* need to use references for expressions since they are light weight proxy
* objects which should generate no copying overhead. */
template <typename T>
struct ref_selector
{
typedef typename conditional<
bool(traits<T>::Flags & NestByRefBit),
T const&,
const T
>::type type;
typedef typename conditional<
bool(traits<T>::Flags & NestByRefBit),
T &,
T
>::type non_const_type;
};
/** \internal Adds the const qualifier on the value-type of T2 if and only if T1 is a const type */
template<typename T1, typename T2>
struct transfer_constness
{
typedef typename conditional<
bool(internal::is_const<T1>::value),
typename internal::add_const_on_value_type<T2>::type,
T2
>::type type;
};
// However, we still need a mechanism to detect whether an expression which is evaluated multiple time
// has to be evaluated into a temporary.
// That's the purpose of this new nested_eval helper:
/** \internal Determines how a given expression should be nested when evaluated multiple times.
* For example, when you do a * (b+c), Eigen will determine how the expression b+c should be
* evaluated into the bigger product expression. The choice is between nesting the expression b+c as-is, or
* evaluating that expression b+c into a temporary variable d, and nest d so that the resulting expression is
* a*d. Evaluating can be beneficial for example if every coefficient access in the resulting expression causes
* many coefficient accesses in the nested expressions -- as is the case with matrix product for example.
*
* \param T the type of the expression being nested.
* \param n the number of coefficient accesses in the nested expression for each coefficient access in the bigger expression.
* \param PlainObject the type of the temporary if needed.
*/
template<typename T, int n, typename PlainObject = typename plain_object_eval<T>::type> struct nested_eval
{
enum {
ScalarReadCost = NumTraits<typename traits<T>::Scalar>::ReadCost,
CoeffReadCost = evaluator<T>::CoeffReadCost, // NOTE What if an evaluator evaluate itself into a tempory?
// Then CoeffReadCost will be small (e.g., 1) but we still have to evaluate, especially if n>1.
// This situation is already taken care by the EvalBeforeNestingBit flag, which is turned ON
// for all evaluator creating a temporary. This flag is then propagated by the parent evaluators.
// Another solution could be to count the number of temps?
NAsInteger = n == Dynamic ? HugeCost : n,
CostEval = (NAsInteger+1) * ScalarReadCost + CoeffReadCost,
CostNoEval = NAsInteger * CoeffReadCost
};
typedef typename conditional<
( (int(evaluator<T>::Flags) & EvalBeforeNestingBit) ||
(int(CostEval) < int(CostNoEval)) ),
PlainObject,
typename ref_selector<T>::type
>::type type;
};
template<typename T>
EIGEN_DEVICE_FUNC
inline T* const_cast_ptr(const T* ptr)
{
return const_cast<T*>(ptr);
}
template<typename Derived, typename XprKind = typename traits<Derived>::XprKind>
struct dense_xpr_base
{
/* dense_xpr_base should only ever be used on dense expressions, thus falling either into the MatrixXpr or into the ArrayXpr cases */
};
template<typename Derived>
struct dense_xpr_base<Derived, MatrixXpr>
{
typedef MatrixBase<Derived> type;
};
template<typename Derived>
struct dense_xpr_base<Derived, ArrayXpr>
{
typedef ArrayBase<Derived> type;
};
template<typename Derived, typename XprKind = typename traits<Derived>::XprKind, typename StorageKind = typename traits<Derived>::StorageKind>
struct generic_xpr_base;
template<typename Derived, typename XprKind>
struct generic_xpr_base<Derived, XprKind, Dense>
{
typedef typename dense_xpr_base<Derived,XprKind>::type type;
};
/** \internal Helper base class to add a scalar multiple operator
* overloads for complex types */
template<typename Derived, typename Scalar, typename OtherScalar, typename BaseType,
bool EnableIt = !is_same<Scalar,OtherScalar>::value >
struct special_scalar_op_base : public BaseType
{
// dummy operator* so that the
// "using special_scalar_op_base::operator*" compiles
struct dummy {};
void operator*(dummy) const;
void operator/(dummy) const;
};
template<typename Derived,typename Scalar,typename OtherScalar, typename BaseType>
struct special_scalar_op_base<Derived,Scalar,OtherScalar,BaseType,true> : public BaseType
{
const CwiseUnaryOp<scalar_multiple2_op<Scalar,OtherScalar>, Derived>
operator*(const OtherScalar& scalar) const
{
#ifdef EIGEN_SPECIAL_SCALAR_MULTIPLE_PLUGIN
EIGEN_SPECIAL_SCALAR_MULTIPLE_PLUGIN
#endif
return CwiseUnaryOp<scalar_multiple2_op<Scalar,OtherScalar>, Derived>
(*static_cast<const Derived*>(this), scalar_multiple2_op<Scalar,OtherScalar>(scalar));
}
inline friend const CwiseUnaryOp<scalar_multiple2_op<Scalar,OtherScalar>, Derived>
operator*(const OtherScalar& scalar, const Derived& matrix)
{
#ifdef EIGEN_SPECIAL_SCALAR_MULTIPLE_PLUGIN
EIGEN_SPECIAL_SCALAR_MULTIPLE_PLUGIN
#endif
return static_cast<const special_scalar_op_base&>(matrix).operator*(scalar);
}
const CwiseUnaryOp<scalar_quotient2_op<Scalar,OtherScalar>, Derived>
operator/(const OtherScalar& scalar) const
{
#ifdef EIGEN_SPECIAL_SCALAR_MULTIPLE_PLUGIN
EIGEN_SPECIAL_SCALAR_MULTIPLE_PLUGIN
#endif
return CwiseUnaryOp<scalar_quotient2_op<Scalar,OtherScalar>, Derived>
(*static_cast<const Derived*>(this), scalar_quotient2_op<Scalar,OtherScalar>(scalar));
}
};
template<typename XprType, typename CastType> struct cast_return_type
{
typedef typename XprType::Scalar CurrentScalarType;
typedef typename remove_all<CastType>::type _CastType;
typedef typename _CastType::Scalar NewScalarType;
typedef typename conditional<is_same<CurrentScalarType,NewScalarType>::value,
const XprType&,CastType>::type type;
};
template <typename A, typename B> struct promote_storage_type;
template <typename A> struct promote_storage_type<A,A>
{
typedef A ret;
};
template <typename A> struct promote_storage_type<A, const A>
{
typedef A ret;
};
template <typename A> struct promote_storage_type<const A, A>
{
typedef A ret;
};
/** \internal Specify the "storage kind" of applying a coefficient-wise
* binary operations between two expressions of kinds A and B respectively.
* The template parameter Functor permits to specialize the resulting storage kind wrt to
* the functor.
* The default rules are as follows:
* \code
* A op A -> A
* A op dense -> dense
* dense op B -> dense
* A * dense -> A
* dense * B -> B
* \endcode
*/
template <typename A, typename B, typename Functor> struct cwise_promote_storage_type;
template <typename A, typename Functor> struct cwise_promote_storage_type<A,A,Functor> { typedef A ret; };
template <typename Functor> struct cwise_promote_storage_type<Dense,Dense,Functor> { typedef Dense ret; };
template <typename ScalarA, typename ScalarB> struct cwise_promote_storage_type<Dense,Dense,scalar_product_op<ScalarA,ScalarB> > { typedef Dense ret; };
template <typename A, typename Functor> struct cwise_promote_storage_type<A,Dense,Functor> { typedef Dense ret; };
template <typename B, typename Functor> struct cwise_promote_storage_type<Dense,B,Functor> { typedef Dense ret; };
template <typename A, typename ScalarA, typename ScalarB> struct cwise_promote_storage_type<A,Dense,scalar_product_op<ScalarA,ScalarB> > { typedef A ret; };
template <typename B, typename ScalarA, typename ScalarB> struct cwise_promote_storage_type<Dense,B,scalar_product_op<ScalarA,ScalarB> > { typedef B ret; };
/** \internal Specify the "storage kind" of multiplying an expression of kind A with kind B.
* The template parameter ProductTag permits to specialize the resulting storage kind wrt to
* some compile-time properties of the product: GemmProduct, GemvProduct, OuterProduct, InnerProduct.
* The default rules are as follows:
* \code
* K * K -> K
* dense * K -> dense
* K * dense -> dense
* diag * K -> K
* K * diag -> K
* Perm * K -> K
* K * Perm -> K
* \endcode
*/
template <typename A, typename B, int ProductTag> struct product_promote_storage_type;
template <typename A, int ProductTag> struct product_promote_storage_type<A, A, ProductTag> { typedef A ret;};
template <int ProductTag> struct product_promote_storage_type<Dense, Dense, ProductTag> { typedef Dense ret;};
template <typename A, int ProductTag> struct product_promote_storage_type<A, Dense, ProductTag> { typedef Dense ret; };
template <typename B, int ProductTag> struct product_promote_storage_type<Dense, B, ProductTag> { typedef Dense ret; };
template <typename A, int ProductTag> struct product_promote_storage_type<A, DiagonalShape, ProductTag> { typedef A ret; };
template <typename B, int ProductTag> struct product_promote_storage_type<DiagonalShape, B, ProductTag> { typedef B ret; };
template <int ProductTag> struct product_promote_storage_type<Dense, DiagonalShape, ProductTag> { typedef Dense ret; };
template <int ProductTag> struct product_promote_storage_type<DiagonalShape, Dense, ProductTag> { typedef Dense ret; };
template <typename A, int ProductTag> struct product_promote_storage_type<A, PermutationStorage, ProductTag> { typedef A ret; };
template <typename B, int ProductTag> struct product_promote_storage_type<PermutationStorage, B, ProductTag> { typedef B ret; };
template <int ProductTag> struct product_promote_storage_type<Dense, PermutationStorage, ProductTag> { typedef Dense ret; };
template <int ProductTag> struct product_promote_storage_type<PermutationStorage, Dense, ProductTag> { typedef Dense ret; };
/** \internal gives the plain matrix or array type to store a row/column/diagonal of a matrix type.
* \param Scalar optional parameter allowing to pass a different scalar type than the one of the MatrixType.
*/
template<typename ExpressionType, typename Scalar = typename ExpressionType::Scalar>
struct plain_row_type
{
typedef Matrix<Scalar, 1, ExpressionType::ColsAtCompileTime,
ExpressionType::PlainObject::Options | RowMajor, 1, ExpressionType::MaxColsAtCompileTime> MatrixRowType;
typedef Array<Scalar, 1, ExpressionType::ColsAtCompileTime,
ExpressionType::PlainObject::Options | RowMajor, 1, ExpressionType::MaxColsAtCompileTime> ArrayRowType;
typedef typename conditional<
is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value,
MatrixRowType,
ArrayRowType
>::type type;
};
template<typename ExpressionType, typename Scalar = typename ExpressionType::Scalar>
struct plain_col_type
{
typedef Matrix<Scalar, ExpressionType::RowsAtCompileTime, 1,
ExpressionType::PlainObject::Options & ~RowMajor, ExpressionType::MaxRowsAtCompileTime, 1> MatrixColType;
typedef Array<Scalar, ExpressionType::RowsAtCompileTime, 1,
ExpressionType::PlainObject::Options & ~RowMajor, ExpressionType::MaxRowsAtCompileTime, 1> ArrayColType;
typedef typename conditional<
is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value,
MatrixColType,
ArrayColType
>::type type;
};
template<typename ExpressionType, typename Scalar = typename ExpressionType::Scalar>
struct plain_diag_type
{
enum { diag_size = EIGEN_SIZE_MIN_PREFER_DYNAMIC(ExpressionType::RowsAtCompileTime, ExpressionType::ColsAtCompileTime),
max_diag_size = EIGEN_SIZE_MIN_PREFER_FIXED(ExpressionType::MaxRowsAtCompileTime, ExpressionType::MaxColsAtCompileTime)
};
typedef Matrix<Scalar, diag_size, 1, ExpressionType::PlainObject::Options & ~RowMajor, max_diag_size, 1> MatrixDiagType;
typedef Array<Scalar, diag_size, 1, ExpressionType::PlainObject::Options & ~RowMajor, max_diag_size, 1> ArrayDiagType;
typedef typename conditional<
is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value,
MatrixDiagType,
ArrayDiagType
>::type type;
};
template<typename ExpressionType>
struct is_lvalue
{
enum { value = !bool(is_const<ExpressionType>::value) &&
bool(traits<ExpressionType>::Flags & LvalueBit) };
};
template<typename T> struct is_diagonal
{ enum { ret = false }; };
template<typename T> struct is_diagonal<DiagonalBase<T> >
{ enum { ret = true }; };
template<typename T> struct is_diagonal<DiagonalWrapper<T> >
{ enum { ret = true }; };
template<typename T, int S> struct is_diagonal<DiagonalMatrix<T,S> >
{ enum { ret = true }; };
template<typename S1, typename S2> struct glue_shapes;
template<> struct glue_shapes<DenseShape,TriangularShape> { typedef TriangularShape type; };
template<typename T1, typename T2>
bool is_same_dense(const T1 &mat1, const T2 &mat2, typename enable_if<has_direct_access<T1>::ret&&has_direct_access<T2>::ret, T1>::type * = 0)
{
return (mat1.data()==mat2.data()) && (mat1.innerStride()==mat2.innerStride()) && (mat1.outerStride()==mat2.outerStride());
}
template<typename T1, typename T2>
bool is_same_dense(const T1 &, const T2 &, typename enable_if<!(has_direct_access<T1>::ret&&has_direct_access<T2>::ret), T1>::type * = 0)
{
return false;
}
template<typename T, typename U> struct is_same_or_void { enum { value = is_same<T,U>::value }; };
template<typename T> struct is_same_or_void<void,T> { enum { value = 1 }; };
template<typename T> struct is_same_or_void<T,void> { enum { value = 1 }; };
template<> struct is_same_or_void<void,void> { enum { value = 1 }; };
#ifdef EIGEN_DEBUG_ASSIGN
std::string demangle_traversal(int t)
{
if(t==DefaultTraversal) return "DefaultTraversal";
if(t==LinearTraversal) return "LinearTraversal";
if(t==InnerVectorizedTraversal) return "InnerVectorizedTraversal";
if(t==LinearVectorizedTraversal) return "LinearVectorizedTraversal";
if(t==SliceVectorizedTraversal) return "SliceVectorizedTraversal";
return "?";
}
std::string demangle_unrolling(int t)
{
if(t==NoUnrolling) return "NoUnrolling";
if(t==InnerUnrolling) return "InnerUnrolling";
if(t==CompleteUnrolling) return "CompleteUnrolling";
return "?";
}
std::string demangle_flags(int f)
{
std::string res;
if(f&RowMajorBit) res += " | RowMajor";
if(f&PacketAccessBit) res += " | Packet";
if(f&LinearAccessBit) res += " | Linear";
if(f&LvalueBit) res += " | Lvalue";
if(f&DirectAccessBit) res += " | Direct";
if(f&NestByRefBit) res += " | NestByRef";
if(f&NoPreferredStorageOrderBit) res += " | NoPreferredStorageOrderBit";
return res;
}
#endif
} // end namespace internal
// we require Lhs and Rhs to have the same scalar type. Currently there is no example of a binary functor
// that would take two operands of different types. If there were such an example, then this check should be
// moved to the BinaryOp functors, on a per-case basis. This would however require a change in the BinaryOp functors, as
// currently they take only one typename Scalar template parameter.
// It is tempting to always allow mixing different types but remember that this is often impossible in the vectorized paths.
// So allowing mixing different types gives very unexpected errors when enabling vectorization, when the user tries to
// add together a float matrix and a double matrix.
#define EIGEN_CHECK_BINARY_COMPATIBILIY(BINOP,LHS,RHS) \
EIGEN_STATIC_ASSERT((internal::functor_is_product_like<BINOP>::ret \
? int(internal::scalar_product_traits<LHS, RHS>::Defined) \
: int(internal::is_same_or_void<LHS, RHS>::value)), \
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
} // end namespace Eigen
#endif // EIGEN_XPRHELPER_H
// Copyright (c) 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ---
// Author: Ray Sidney
// Revamped and reorganized by Craig Silverstein
//
// This file contains the implementation of all our command line flags
// stuff. Here's how everything fits together
//
// * FlagRegistry owns CommandLineFlags owns FlagValue.
// * FlagSaver holds a FlagRegistry (saves it at construct time,
// restores it at destroy time).
// * CommandLineFlagParser lives outside that hierarchy, but works on
// CommandLineFlags (modifying the FlagValues).
// * Free functions like SetCommandLineOption() work via one of the
// above (such as CommandLineFlagParser).
//
// In more detail:
//
// -- The main classes that hold flag data:
//
// FlagValue holds the current value of a flag. It's
// pseudo-templatized: every operation on a FlagValue is typed. It
// also deals with storage-lifetime issues (so flag values don't go
// away in a destructor), which is why we need a whole class to hold a
// variable's value.
//
// CommandLineFlag is all the information about a single command-line
// flag. It has a FlagValue for the flag's current value, but also
// the flag's name, type, etc.
//
// FlagRegistry is a collection of CommandLineFlags. There's the
// global registry, which is where flags defined via DEFINE_foo()
// live. But it's possible to define your own flag, manually, in a
// different registry you create. (In practice, multiple registries
// are used only by FlagSaver).
//
// A given FlagValue is owned by exactly one CommandLineFlag. A given
// CommandLineFlag is owned by exactly one FlagRegistry. FlagRegistry
// has a lock; any operation that writes to a FlagValue or
// CommandLineFlag owned by that registry must acquire the
// FlagRegistry lock before doing so.
//
// --- Some other classes and free functions:
//
// CommandLineFlagInfo is a client-exposed version of CommandLineFlag.
// Once it's instantiated, it has no dependencies or relationships
// with any other part of this file.
//
// FlagRegisterer is the helper class used by the DEFINE_* macros to
// allow work to be done at global initialization time.
//
// CommandLineFlagParser is the class that reads from the commandline
// and instantiates flag values based on that. It needs to poke into
// the innards of the FlagValue->CommandLineFlag->FlagRegistry class
// hierarchy to do that. It's careful to acquire the FlagRegistry
// lock before doing any writing or other non-const actions.
//
// GetCommandLineOption is just a hook into registry routines to
// retrieve a flag based on its name. SetCommandLineOption, on the
// other hand, hooks into CommandLineFlagParser. Other API functions
// are, similarly, mostly hooks into the functionality described above.
#define PRIx64 "llx"
#define PRIX64 "llX"
#define PRIu64 "llu"
#define PRId64 "lld"
#define PRIo64 "llo"
#define PRIx32 "x"
#define PRIX32 "X"
#define PRIu32 "u"
#define PRId32 "d"
#define PRIx16 "hx"
#define PRIX16 "hX"
#define PRIu16 "hu"
#define PRIu8 "hhu"
#define PRIx8 "hhx"
#include "config.h"
// This comes first to ensure we define __STDC_FORMAT_MACROS in time.
#ifdef HAVE_INTTYPES_H
#ifndef __STDC_FORMAT_MACROS
# define __STDC_FORMAT_MACROS 1 // gcc requires this to get PRId64, etc.
#endif
#include <inttypes.h>
#endif // HAVE_INTTYPES_H
#include <stdio.h> // for snprintf
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdarg.h> // For va_list and related operations
#include <string.h>
#include <assert.h>
#ifdef HAVE_FNMATCH_H
#include <fnmatch.h>
#endif // HAVE_FNMATCH_H
#include <string>
#include <map>
#include <vector>
#include <utility> // for pair<>
#include <algorithm>
#include "gflags.h"
#include "mutex.h"
#ifndef PATH_SEPARATOR
#define PATH_SEPARATOR '/'
#endif
// Work properly if either strtoll or strtoq is on this system
#ifdef HAVE_STRTOLL
# define strtoint64 strtoll
# define strtouint64 strtoull
#elif HAVE_STRTOQ
# define strtoint64 strtoq
# define strtouint64 strtouq
#else
// Neither strtoll nor strtoq are defined. I hope strtol works!
# define strtoint64 strtol
# define strtouint64 strtoul
#endif
// If we have inttypes.h, it will have defined PRId32/etc for us. If
// not, take our best guess.
#ifndef PRId32
# define PRId32 "d"
#endif
#ifndef PRId64
# define PRId64 "lld"
#endif
#ifndef PRIu64
# define PRIu64 "llu"
#endif
// Windows is missing random bits like strcasecmp, strtoll, strtoull, and
// snprintf in the usual locations. Put them somewhere sensible.
//
// TODO(keir): Get the upstream Windows port and use that instead.
#ifdef _MSC_VER
# define snprintf _snprintf
# undef strtoint64
# define strtoint64 _strtoi64
# undef strtouint64
# define strtouint64 _strtoui64
# define strcasecmp _stricmp
#endif
typedef signed char int8;
typedef unsigned char uint8;
// Special flags, type 1: the 'recursive' flags. They set another flag's val.
DEFINE_string(flagfile, "",
"load flags from file");
DEFINE_string(fromenv, "",
"set flags from the environment"
" [use 'export FLAGS_flag1=value']");
DEFINE_string(tryfromenv, "",
"set flags from the environment if present");
// Special flags, type 2: the 'parsing' flags. They modify how we parse.
DEFINE_string(undefok, "",
"comma-separated list of flag names that it is okay to specify "
"on the command line even if the program does not define a flag "
"with that name. IMPORTANT: flags in this list that have "
"arguments MUST use the flag=value format");
_START_GOOGLE_NAMESPACE_
using std::map;
using std::pair;
using std::sort;
using std::string;
using std::vector;
// The help message indicating that the commandline flag has been
// 'stripped'. It will not show up when doing "-help" and its
// variants. The flag is stripped if STRIP_FLAG_HELP is set to 1
// before including gflags/gflags.h.
// This is used by this file, and also in commandlineflags_reporting.cc
const char kStrippedFlagHelp[] = "\001\002\003\004 (unknown) \004\003\002\001";
// This is used by the unittest to test error-exit code
void GFLAGS_DLL_DECL (*commandlineflags_exitfunc)(int) = &exit; // from stdlib.h
namespace {
// There are also 'reporting' flags, in commandlineflags_reporting.cc.
static const char kError[] = "ERROR: ";
// Indicates that undefined options are to be ignored.
// Enables deferred processing of flags in dynamically loaded libraries.
static bool allow_command_line_reparsing = false;
static bool logging_is_probably_set_up = false;
// This is a 'prototype' validate-function. 'Real' validate
// functions, take a flag-value as an argument: ValidateFn(bool) or
// ValidateFn(uint64). However, for easier storage, we strip off this
// argument and then restore it when actually calling the function on
// a flag value.
typedef bool (*ValidateFnProto)();
// Whether we should die when reporting an error.
enum DieWhenReporting { DIE, DO_NOT_DIE };
// Report Error and exit if requested.
static void ReportError(DieWhenReporting should_die, const char* format, ...) {
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
if (should_die == DIE)
commandlineflags_exitfunc(1); // almost certainly exit()
}
// --------------------------------------------------------------------
// FlagValue
// This represent the value a single flag might have. The major
// functionality is to convert from a string to an object of a
// given type, and back. Thread-compatible.
// --------------------------------------------------------------------
class CommandLineFlag;
class FlagValue {
public:
FlagValue(void* valbuf, const char* type, bool transfer_ownership_of_value);
~FlagValue();
bool ParseFrom(const char* spec);
string ToString() const;
private:
friend class CommandLineFlag; // for many things, including Validate()
friend class GOOGLE_NAMESPACE::FlagSaverImpl; // calls New()
friend class FlagRegistry; // checks value_buffer_ for flags_by_ptr_ map
template <typename T> friend T GetFromEnv(const char*, const char*, T);
friend bool TryParseLocked(const CommandLineFlag*, FlagValue*,
const char*, string*); // for New(), CopyFrom()
enum ValueType {
FV_BOOL = 0,
FV_INT32 = 1,
FV_INT64 = 2,
FV_UINT64 = 3,
FV_DOUBLE = 4,
FV_STRING = 5,
FV_MAX_INDEX = 5,
};
const char* TypeName() const;
bool Equal(const FlagValue& x) const;
FlagValue* New() const; // creates a new one with default value
void CopyFrom(const FlagValue& x);
int ValueSize() const;
// Calls the given validate-fn on value_buffer_, and returns
// whatever it returns. But first casts validate_fn_proto to a
// function that takes our value as an argument (eg void
// (*validate_fn)(bool) for a bool flag).
bool Validate(const char* flagname, ValidateFnProto validate_fn_proto) const;
void* value_buffer_; // points to the buffer holding our data
int8 type_; // how to interpret value_
bool owns_value_; // whether to free value on destruct
FlagValue(const FlagValue&); // no copying!
void operator=(const FlagValue&);
};
// This could be a templated method of FlagValue, but doing so adds to the
// size of the .o. Since there's no type-safety here anyway, macro is ok.
#define VALUE_AS(type) *reinterpret_cast<type*>(value_buffer_)
#define OTHER_VALUE_AS(fv, type) *reinterpret_cast<type*>(fv.value_buffer_)
#define SET_VALUE_AS(type, value) VALUE_AS(type) = (value)
FlagValue::FlagValue(void* valbuf, const char* type,
bool transfer_ownership_of_value)
: value_buffer_(valbuf),
owns_value_(transfer_ownership_of_value) {
for (type_ = 0; type_ <= FV_MAX_INDEX; ++type_) {
if (!strcmp(type, TypeName())) {
break;
}
}
assert(type_ <= FV_MAX_INDEX); // Unknown typename
}
FlagValue::~FlagValue() {
if (!owns_value_) {
return;
}
switch (type_) {
case FV_BOOL: delete reinterpret_cast<bool*>(value_buffer_); break;
case FV_INT32: delete reinterpret_cast<int32*>(value_buffer_); break;
case FV_INT64: delete reinterpret_cast<int64*>(value_buffer_); break;
case FV_UINT64: delete reinterpret_cast<uint64*>(value_buffer_); break;
case FV_DOUBLE: delete reinterpret_cast<double*>(value_buffer_); break;
case FV_STRING: delete reinterpret_cast<string*>(value_buffer_); break;
}
}
bool FlagValue::ParseFrom(const char* value) {
if (type_ == FV_BOOL) {
const char* kTrue[] = { "1", "t", "true", "y", "yes" };
const char* kFalse[] = { "0", "f", "false", "n", "no" };
for (size_t i = 0; i < sizeof(kTrue)/sizeof(*kTrue); ++i) {
if (strcasecmp(value, kTrue[i]) == 0) {
SET_VALUE_AS(bool, true);
return true;
} else if (strcasecmp(value, kFalse[i]) == 0) {
SET_VALUE_AS(bool, false);
return true;
}
}
return false; // didn't match a legal input
} else if (type_ == FV_STRING) {
SET_VALUE_AS(string, value);
return true;
}
// OK, it's likely to be numeric, and we'll be using a strtoXXX method.
if (value[0] == '\0') // empty-string is only allowed for string type.
return false;
char* end;
// Leading 0x puts us in base 16. But leading 0 does not put us in base 8!
// It caused too many bugs when we had that behavior.
int base = 10; // by default
if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X'))
base = 16;
errno = 0;
switch (type_) {
case FV_INT32: {
const int64 r = strtoint64(value, &end, base);
if (errno || end != value + strlen(value)) return false; // bad parse
if (static_cast<int32>(r) != r) // worked, but number out of range
return false;
SET_VALUE_AS(int32, static_cast<int32>(r));
return true;
}
case FV_INT64: {
const int64 r = strtoint64(value, &end, base);
if (errno || end != value + strlen(value)) return false; // bad parse
SET_VALUE_AS(int64, r);
return true;
}
case FV_UINT64: {
while (*value == ' ') value++;
if (*value == '-') return false; // negative number
const uint64 r = strtouint64(value, &end, base);
if (errno || end != value + strlen(value)) return false; // bad parse
SET_VALUE_AS(uint64, r);
return true;
}
case FV_DOUBLE: {
const double r = strtod(value, &end);
if (errno || end != value + strlen(value)) return false; // bad parse
SET_VALUE_AS(double, r);
return true;
}
default: {
assert(false); // unknown type
return false;
}
}
}
string FlagValue::ToString() const {
char intbuf[64]; // enough to hold even the biggest number
switch (type_) {
case FV_BOOL:
return VALUE_AS(bool) ? "true" : "false";
case FV_INT32:
snprintf(intbuf, sizeof(intbuf), "%d", VALUE_AS(int32));
return intbuf;
case FV_INT64:
snprintf(intbuf, sizeof(intbuf), "%llu", VALUE_AS(int64));
return intbuf;
case FV_UINT64:
snprintf(intbuf, sizeof(intbuf), "%llu", VALUE_AS(uint64));
return intbuf;
case FV_DOUBLE:
snprintf(intbuf, sizeof(intbuf), "%.17g", VALUE_AS(double));
return intbuf;
case FV_STRING:
return VALUE_AS(string);
default:
assert(false);
return ""; // unknown type
}
}
bool FlagValue::Validate(const char* flagname,
ValidateFnProto validate_fn_proto) const {
switch (type_) {
case FV_BOOL:
return reinterpret_cast<bool (*)(const char*, bool)>(
validate_fn_proto)(flagname, VALUE_AS(bool));
case FV_INT32:
return reinterpret_cast<bool (*)(const char*, int32)>(
validate_fn_proto)(flagname, VALUE_AS(int32));
case FV_INT64:
return reinterpret_cast<bool (*)(const char*, int64)>(
validate_fn_proto)(flagname, VALUE_AS(int64));
case FV_UINT64:
return reinterpret_cast<bool (*)(const char*, uint64)>(
validate_fn_proto)(flagname, VALUE_AS(uint64));
case FV_DOUBLE:
return reinterpret_cast<bool (*)(const char*, double)>(
validate_fn_proto)(flagname, VALUE_AS(double));
case FV_STRING:
return reinterpret_cast<bool (*)(const char*, const string&)>(
validate_fn_proto)(flagname, VALUE_AS(string));
default:
assert(false); // unknown type
return false;
}
}
const char* FlagValue::TypeName() const {
static const char types[] =
"bool\0xx"
"int32\0x"
"int64\0x"
"uint64\0"
"double\0"
"string";
if (type_ > FV_MAX_INDEX) {
assert(false);
return "";
}
// Directly indexing the strigns in the 'types' string, each of them
// is 7 bytes long.
return &types[type_ * 7];
}
bool FlagValue::Equal(const FlagValue& x) const {
if (type_ != x.type_)
return false;
switch (type_) {
case FV_BOOL: return VALUE_AS(bool) == OTHER_VALUE_AS(x, bool);
case FV_INT32: return VALUE_AS(int32) == OTHER_VALUE_AS(x, int32);
case FV_INT64: return VALUE_AS(int64) == OTHER_VALUE_AS(x, int64);
case FV_UINT64: return VALUE_AS(uint64) == OTHER_VALUE_AS(x, uint64);
case FV_DOUBLE: return VALUE_AS(double) == OTHER_VALUE_AS(x, double);
case FV_STRING: return VALUE_AS(string) == OTHER_VALUE_AS(x, string);
default: assert(false); return false; // unknown type
}
}
FlagValue* FlagValue::New() const {
const char *type = TypeName();
switch (type_) {
case FV_BOOL: return new FlagValue(new bool(false), type, true);
case FV_INT32: return new FlagValue(new int32(0), type, true);
case FV_INT64: return new FlagValue(new int64(0), type, true);
case FV_UINT64: return new FlagValue(new uint64(0), type, true);
case FV_DOUBLE: return new FlagValue(new double(0.0), type, true);
case FV_STRING: return new FlagValue(new string, type, true);
default: assert(false); return NULL; // unknown type
}
}
void FlagValue::CopyFrom(const FlagValue& x) {
assert(type_ == x.type_);
switch (type_) {
case FV_BOOL: SET_VALUE_AS(bool, OTHER_VALUE_AS(x, bool)); break;
case FV_INT32: SET_VALUE_AS(int32, OTHER_VALUE_AS(x, int32)); break;
case FV_INT64: SET_VALUE_AS(int64, OTHER_VALUE_AS(x, int64)); break;
case FV_UINT64: SET_VALUE_AS(uint64, OTHER_VALUE_AS(x, uint64)); break;
case FV_DOUBLE: SET_VALUE_AS(double, OTHER_VALUE_AS(x, double)); break;
case FV_STRING: SET_VALUE_AS(string, OTHER_VALUE_AS(x, string)); break;
default: assert(false); // unknown type
}
}
int FlagValue::ValueSize() const {
if (type_ > FV_MAX_INDEX) {
assert(false); // unknown type
return 0;
}
static const uint8 valuesize[] = {
sizeof(bool),
sizeof(int32),
sizeof(int64),
sizeof(uint64),
sizeof(double),
sizeof(string),
};
return valuesize[type_];
}
// --------------------------------------------------------------------
// CommandLineFlag
// This represents a single flag, including its name, description,
// default value, and current value. Mostly this serves as a
// struct, though it also knows how to register itself.
// All CommandLineFlags are owned by a (exactly one)
// FlagRegistry. If you wish to modify fields in this class, you
// should acquire the FlagRegistry lock for the registry that owns
// this flag.
// --------------------------------------------------------------------
class CommandLineFlag {
public:
// Note: we take over memory-ownership of current_val and default_val.
CommandLineFlag(const char* name, const char* help, const char* filename,
FlagValue* current_val, FlagValue* default_val);
~CommandLineFlag();
const char* name() const { return name_; }
const char* help() const { return help_; }
const char* filename() const { return file_; }
const char* CleanFileName() const; // nixes irrelevant prefix such as homedir
string current_value() const { return current_->ToString(); }
string default_value() const { return defvalue_->ToString(); }
const char* type_name() const { return defvalue_->TypeName(); }
ValidateFnProto validate_function() const { return validate_fn_proto_; }
void FillCommandLineFlagInfo(struct CommandLineFlagInfo* result);
// If validate_fn_proto_ is non-NULL, calls it on value, returns result.
bool Validate(const FlagValue& value) const;
bool ValidateCurrent() const { return Validate(*current_); }
private:
// for SetFlagLocked() and setting flags_by_ptr_
friend class FlagRegistry;
friend class GOOGLE_NAMESPACE::FlagSaverImpl; // for cloning the values
// set validate_fn
friend bool AddFlagValidator(const void*, ValidateFnProto);
// This copies all the non-const members: modified, processed, defvalue, etc.
void CopyFrom(const CommandLineFlag& src);
void UpdateModifiedBit();
const char* const name_; // Flag name
const char* const help_; // Help message
const char* const file_; // Which file did this come from?
bool modified_; // Set after default assignment?
FlagValue* defvalue_; // Default value for flag
FlagValue* current_; // Current value for flag
// This is a casted, 'generic' version of validate_fn, which actually
// takes a flag-value as an arg (void (*validate_fn)(bool), say).
// When we pass this to current_->Validate(), it will cast it back to
// the proper type. This may be NULL to mean we have no validate_fn.
ValidateFnProto validate_fn_proto_;
CommandLineFlag(const CommandLineFlag&); // no copying!
void operator=(const CommandLineFlag&);
};
CommandLineFlag::CommandLineFlag(const char* name, const char* help,
const char* filename,
FlagValue* current_val, FlagValue* default_val)
: name_(name), help_(help), file_(filename), modified_(false),
defvalue_(default_val), current_(current_val), validate_fn_proto_(NULL) {
}
CommandLineFlag::~CommandLineFlag() {
delete current_;
delete defvalue_;
}
const char* CommandLineFlag::CleanFileName() const {
// Compute top-level directory & file that this appears in
// search full path backwards.
// Stop going backwards at kRootDir; and skip by the first slash.
static const char kRootDir[] = ""; // can set this to root directory,
// e.g. "myproject"
if (sizeof(kRootDir)-1 == 0) // no prefix to strip
return filename();
const char* clean_name = filename() + strlen(filename()) - 1;
while ( clean_name > filename() ) {
if (*clean_name == PATH_SEPARATOR) {
if (strncmp(clean_name, kRootDir, sizeof(kRootDir)-1) == 0) {
// ".../myproject/base/logging.cc" ==> "base/logging.cc"
clean_name += sizeof(kRootDir)-1; // past "/myproject/"
break;
}
}
--clean_name;
}
while ( *clean_name == PATH_SEPARATOR ) ++clean_name; // Skip any slashes
return clean_name;
}
void CommandLineFlag::FillCommandLineFlagInfo(
CommandLineFlagInfo* result) {
result->name = name();
result->type = type_name();
result->description = help();
result->current_value = current_value();
result->default_value = default_value();
result->filename = CleanFileName();
UpdateModifiedBit();
result->is_default = !modified_;
result->has_validator_fn = validate_function() != NULL;
}
void CommandLineFlag::UpdateModifiedBit() {
// Update the "modified" bit in case somebody bypassed the
// Flags API and wrote directly through the FLAGS_name variable.
if (!modified_ && !current_->Equal(*defvalue_)) {
modified_ = true;
}
}
void CommandLineFlag::CopyFrom(const CommandLineFlag& src) {
// Note we only copy the non-const members; others are fixed at construct time
if (modified_ != src.modified_) modified_ = src.modified_;
if (!current_->Equal(*src.current_)) current_->CopyFrom(*src.current_);
if (!defvalue_->Equal(*src.defvalue_)) defvalue_->CopyFrom(*src.defvalue_);
if (validate_fn_proto_ != src.validate_fn_proto_)
validate_fn_proto_ = src.validate_fn_proto_;
}
bool CommandLineFlag::Validate(const FlagValue& value) const {
if (validate_function() == NULL)
return true;
else
return value.Validate(name(), validate_function());
}
// --------------------------------------------------------------------
// FlagRegistry
// A FlagRegistry singleton object holds all flag objects indexed
// by their names so that if you know a flag's name (as a C
// string), you can access or set it. If the function is named
// FooLocked(), you must own the registry lock before calling
// the function; otherwise, you should *not* hold the lock, and
// the function will acquire it itself if needed.
// --------------------------------------------------------------------
struct StringCmp { // Used by the FlagRegistry map class to compare char*'s
bool operator() (const char* s1, const char* s2) const {
return (strcmp(s1, s2) < 0);
}
};
class FlagRegistry {
public:
FlagRegistry() { }
~FlagRegistry() {
for (FlagMap::iterator p = flags_.begin(), e = flags_.end(); p != e; ++p) {
CommandLineFlag* flag = p->second;
delete flag;
}
}
static void DeleteGlobalRegistry() {
delete global_registry_;
global_registry_ = NULL;
}
void Lock() { lock_.Lock(); }
void Unlock() { lock_.Unlock(); }
// Store a flag in this registry. Takes ownership of the given pointer.
void RegisterFlag(CommandLineFlag* flag);
// Returns the flag object for the specified name, or NULL if not found.
CommandLineFlag* FindFlagLocked(const char* name);
// Returns the flag object whose current-value is stored at flag_ptr.
// That is, for whom current_->value_buffer_ == flag_ptr
CommandLineFlag* FindFlagViaPtrLocked(const void* flag_ptr);
// A fancier form of FindFlag that works correctly if name is of the
// form flag=value. In that case, we set key to point to flag, and
// modify v to point to the value (if present), and return the flag
// with the given name. If the flag does not exist, returns NULL
// and sets error_message.
CommandLineFlag* SplitArgumentLocked(const char* argument,
string* key, const char** v,
string* error_message);
// Set the value of a flag. If the flag was successfully set to
// value, set msg to indicate the new flag-value, and return true.
// Otherwise, set msg to indicate the error, leave flag unchanged,
// and return false. msg can be NULL.
bool SetFlagLocked(CommandLineFlag* flag, const char* value,
FlagSettingMode set_mode, string* msg);
static FlagRegistry* GlobalRegistry(); // returns a singleton registry
private:
friend class GOOGLE_NAMESPACE::FlagSaverImpl; // reads all the flags in order to copy them
friend class CommandLineFlagParser; // for ValidateAllFlags
friend void GOOGLE_NAMESPACE::GetAllFlags(vector<CommandLineFlagInfo>*);
// The map from name to flag, for FindFlagLocked().
typedef map<const char*, CommandLineFlag*, StringCmp> FlagMap;
typedef FlagMap::iterator FlagIterator;
typedef FlagMap::const_iterator FlagConstIterator;
FlagMap flags_;
// The map from current-value pointer to flag, fo FindFlagViaPtrLocked().
typedef map<const void*, CommandLineFlag*> FlagPtrMap;
FlagPtrMap flags_by_ptr_;
Mutex lock_;
static FlagRegistry* global_registry_; // a singleton registry
static Mutex global_registry_lock_; // guards creation of global_registry_
// Disallow
FlagRegistry(const FlagRegistry&);
FlagRegistry& operator=(const FlagRegistry&);
};
FlagRegistry* FlagRegistry::global_registry_ = NULL;
Mutex FlagRegistry::global_registry_lock_(Mutex::LINKER_INITIALIZED);
FlagRegistry* FlagRegistry::GlobalRegistry() {
MutexLock acquire_lock(&global_registry_lock_);
if (!global_registry_) {
global_registry_ = new FlagRegistry;
}
return global_registry_;
}
void FlagRegistry::RegisterFlag(CommandLineFlag* flag) {
Lock();
pair<FlagIterator, bool> ins =
flags_.insert(pair<const char*, CommandLineFlag*>(flag->name(), flag));
if (ins.second == false) { // means the name was already in the map
if (strcmp(ins.first->second->filename(), flag->filename()) != 0) {
ReportError(DIE, "ERROR: flag '%s' was defined more than once "
"(in files '%s' and '%s').\n",
flag->name(),
ins.first->second->filename(),
flag->filename());
} else {
ReportError(DIE, "ERROR: something wrong with flag '%s' in file '%s'. "
"One possibility: file '%s' is being linked both statically "
"and dynamically into this executable.\n",
flag->name(),
flag->filename(), flag->filename());
}
}
// Also add to the flags_by_ptr_ map.
flags_by_ptr_[flag->current_->value_buffer_] = flag;
Unlock();
}
CommandLineFlag* FlagRegistry::FindFlagLocked(const char* name) {
FlagConstIterator i = flags_.find(name);
if (i == flags_.end()) {
return NULL;
} else {
return i->second;
}
}
CommandLineFlag* FlagRegistry::FindFlagViaPtrLocked(const void* flag_ptr) {
FlagPtrMap::const_iterator i = flags_by_ptr_.find(flag_ptr);
if (i == flags_by_ptr_.end()) {
return NULL;
} else {
return i->second;
}
}
CommandLineFlag* FlagRegistry::SplitArgumentLocked(const char* arg,
string* key,
const char** v,
string* error_message) {
// Find the flag object for this option
const char* flag_name;
const char* value = strchr(arg, '=');
if (value == NULL) {
key->assign(arg);
*v = NULL;
} else {
// Strip out the "=value" portion from arg
key->assign(arg, value-arg);
*v = ++value; // advance past the '='
}
flag_name = key->c_str();
CommandLineFlag* flag = FindFlagLocked(flag_name);
if (flag == NULL) {
// If we can't find the flag-name, then we should return an error.
// The one exception is if 1) the flag-name is 'nox', 2) there
// exists a flag named 'x', and 3) 'x' is a boolean flag.
// In that case, we want to return flag 'x'.
if (!(flag_name[0] == 'n' && flag_name[1] == 'o')) {
// flag-name is not 'nox', so we're not in the exception case.
*error_message = (string(kError) +
"unknown command line flag '" + *key + "'\n");
return NULL;
}
flag = FindFlagLocked(flag_name+2);
if (flag == NULL) {
// No flag named 'x' exists, so we're not in the exception case.
*error_message = (string(kError) +
"unknown command line flag '" + *key + "'\n");
return NULL;
}
if (strcmp(flag->type_name(), "bool") != 0) {
// 'x' exists but is not boolean, so we're not in the exception case.
*error_message = (string(kError) +
"boolean value (" + *key + ") specified for " +
flag->type_name() + " command line flag\n");
return NULL;
}
// We're in the exception case!
// Make up a fake value to replace the "no" we stripped out
key->assign(flag_name+2); // the name without the "no"
*v = "0";
}
// Assign a value if this is a boolean flag
if (*v == NULL && strcmp(flag->type_name(), "bool") == 0) {
*v = "1"; // the --nox case was already handled, so this is the --x case
}
return flag;
}
bool TryParseLocked(const CommandLineFlag* flag, FlagValue* flag_value,
const char* value, string* msg) {
// Use tenative_value, not flag_value, until we know value is valid.
FlagValue* tentative_value = flag_value->New();
if (!tentative_value->ParseFrom(value)) {
if (msg) {
*msg += (string(kError) + "illegal value '" + value +
+ "' specified for " + flag->type_name() + " flag '"
+ flag->name() + "'\n");
}
delete tentative_value;
return false;
} else if (!flag->Validate(*tentative_value)) {
if (msg) {
*msg += (string(kError) + "failed validation of new value "
+ "'" + tentative_value->ToString() + "' for flag '" +
+ flag->name() + "'\n");
}
delete tentative_value;
return false;
} else {
flag_value->CopyFrom(*tentative_value);
if (msg) {
*msg += (string(flag->name()) + " set to " + flag_value->ToString()
+ "\n");
}
delete tentative_value;
return true;
}
}
bool FlagRegistry::SetFlagLocked(CommandLineFlag* flag,
const char* value,
FlagSettingMode set_mode,
string* msg) {
flag->UpdateModifiedBit();
switch (set_mode) {
case SET_FLAGS_VALUE: {
// set or modify the flag's value
if (!TryParseLocked(flag, flag->current_, value, msg))
return false;
flag->modified_ = true;
break;
}
case SET_FLAG_IF_DEFAULT: {
// set the flag's value, but only if it hasn't been set by someone else
if (!flag->modified_) {
if (!TryParseLocked(flag, flag->current_, value, msg))
return false;
flag->modified_ = true;
} else {
*msg = string(flag->name()) + " set to " + flag->current_value();
}
break;
}
case SET_FLAGS_DEFAULT: {
// modify the flag's default-value
if (!TryParseLocked(flag, flag->defvalue_, value, msg))
return false;
if (!flag->modified_) {
// Need to set both defvalue *and* current, in this case
TryParseLocked(flag, flag->current_, value, NULL);
}
break;
}
default: {
// unknown set_mode
assert(false);
return false;
}
}
return true;
}
class FlagRegistryLock {
public:
explicit FlagRegistryLock(FlagRegistry* fr) : fr_(fr) { fr_->Lock(); }
~FlagRegistryLock() { fr_->Unlock(); }
private:
FlagRegistry *const fr_;
};
// --------------------------------------------------------------------
// CommandLineFlagParser
// Parsing is done in two stages. In the first, we go through
// argv. For every flag-like arg we can make sense of, we parse
// it and set the appropriate FLAGS_* variable. For every flag-
// like arg we can't make sense of, we store it in a vector,
// along with an explanation of the trouble. In stage 2, we
// handle the 'reporting' flags like --help and --mpm_version.
// (This is via a call to HandleCommandLineHelpFlags(), in
// gflags_reporting.cc.)
// An optional stage 3 prints out the error messages.
// This is a bit of a simplification. For instance, --flagfile
// is handled as soon as it's seen in stage 1, not in stage 2.
// --------------------------------------------------------------------
class CommandLineFlagParser {
public:
// The argument is the flag-registry to register the parsed flags in
explicit CommandLineFlagParser(FlagRegistry* reg) : registry_(reg) {}
~CommandLineFlagParser() {}
// Stage 1: Every time this is called, it reads all flags in argv.
// However, it ignores all flags that have been successfully set
// before. Typically this is only called once, so this 'reparsing'
// behavior isn't important. It can be useful when trying to
// reparse after loading a dll, though.
uint32 ParseNewCommandLineFlags(int* argc, char*** argv, bool remove_flags);
// Stage 2: print reporting info and exit, if requested.
// In gflags_reporting.cc:HandleCommandLineHelpFlags().
// Stage 3: validate all the commandline flags that have validators
// registered.
void ValidateAllFlags();
// Stage 4: report any errors and return true if any were found.
bool ReportErrors();
// Set a particular command line option. "newval" is a string
// describing the new value that the option has been set to. If
// option_name does not specify a valid option name, or value is not
// a valid value for option_name, newval is empty. Does recursive
// processing for --flagfile and --fromenv. Returns the new value
// if everything went ok, or empty-string if not. (Actually, the
// return-string could hold many flag/value pairs due to --flagfile.)
// NB: Must have called registry_->Lock() before calling this function.
string ProcessSingleOptionLocked(CommandLineFlag* flag,
const char* value,
FlagSettingMode set_mode);
// Set a whole batch of command line options as specified by contentdata,
// which is in flagfile format (and probably has been read from a flagfile).
// Returns the new value if everything went ok, or empty-string if
// not. (Actually, the return-string could hold many flag/value
// pairs due to --flagfile.)
// NB: Must have called registry_->Lock() before calling this function.
string ProcessOptionsFromStringLocked(const string& contentdata,
FlagSettingMode set_mode);
// These are the 'recursive' flags, defined at the top of this file.
// Whenever we see these flags on the commandline, we must take action.
// These are called by ProcessSingleOptionLocked and, similarly, return
// new values if everything went ok, or the empty-string if not.
string ProcessFlagfileLocked(const string& flagval, FlagSettingMode set_mode);
// diff fromenv/tryfromenv
string ProcessFromenvLocked(const string& flagval, FlagSettingMode set_mode,
bool errors_are_fatal);
private:
FlagRegistry* const registry_;
map<string, string> error_flags_; // map from name to error message
// This could be a set<string>, but we reuse the map to minimize the .o size
map<string, string> undefined_names_; // --[flag] name was not registered
};
// Parse a list of (comma-separated) flags.
static void ParseFlagList(const char* value, vector<string>* flags) {
for (const char *p = value; p && *p; value = p) {
p = strchr(value, ',');
int len;
if (p) {
len = static_cast<int>(p - value);
p++;
} else {
len = static_cast<int>(strlen(value));
}
if (len == 0)
ReportError(DIE, "ERROR: empty flaglist entry\n");
if (value[0] == '-')
ReportError(DIE, "ERROR: flag \"%*s\" begins with '-'\n", len, value);
flags->push_back(string(value, len));
}
}
// Snarf an entire file into a C++ string. This is just so that we
// can do all the I/O in one place and not worry about it everywhere.
// Plus, it's convenient to have the whole file contents at hand.
// Adds a newline at the end of the file.
#define PFATAL(s) do { perror(s); commandlineflags_exitfunc(1); } while (0)
static string ReadFileIntoString(const char* filename) {
const int kBufSize = 8092;
char buffer[kBufSize];
string s;
FILE* fp = fopen(filename, "r");
if (!fp) PFATAL(filename);
size_t n;
while ( (n=fread(buffer, 1, kBufSize, fp)) > 0 ) {
if (ferror(fp)) PFATAL(filename);
s.append(buffer, n);
}
fclose(fp);
return s;
}
uint32 CommandLineFlagParser::ParseNewCommandLineFlags(int* argc, char*** argv,
bool remove_flags) {
const char *program_name = strrchr((*argv)[0], PATH_SEPARATOR); // nix path
program_name = (program_name == NULL ? (*argv)[0] : program_name+1);
int first_nonopt = *argc; // for non-options moved to the end
registry_->Lock();
for (int i = 1; i < first_nonopt; i++) {
char* arg = (*argv)[i];
// Like getopt(), we permute non-option flags to be at the end.
if (arg[0] != '-' || // must be a program argument
(arg[0] == '-' && arg[1] == '\0')) { // "-" is an argument, not a flag
memmove((*argv) + i, (*argv) + i+1, (*argc - (i+1)) * sizeof((*argv)[i]));
(*argv)[*argc-1] = arg; // we go last
first_nonopt--; // we've been pushed onto the stack
i--; // to undo the i++ in the loop
continue;
}
if (arg[0] == '-') arg++; // allow leading '-'
if (arg[0] == '-') arg++; // or leading '--'
// -- alone means what it does for GNU: stop options parsing
if (*arg == '\0') {
first_nonopt = i+1;
break;
}
// Find the flag object for this option
string key;
const char* value;
string error_message;
CommandLineFlag* flag = registry_->SplitArgumentLocked(arg, &key, &value,
&error_message);
if (flag == NULL) {
undefined_names_[key] = ""; // value isn't actually used
error_flags_[key] = error_message;
continue;
}
if (value == NULL) {
// Boolean options are always assigned a value by SplitArgumentLocked()
assert(strcmp(flag->type_name(), "bool") != 0);
if (i+1 >= first_nonopt) {
// This flag needs a value, but there is nothing available
error_flags_[key] = (string(kError) + "flag '" + (*argv)[i] + "'"
+ " is missing its argument");
if (flag->help() && flag->help()[0] > '\001') {
// Be useful in case we have a non-stripped description.
error_flags_[key] += string("; flag description: ") + flag->help();
}
error_flags_[key] += "\n";
break; // we treat this as an unrecoverable error
} else {
value = (*argv)[++i]; // read next arg for value
// Heuristic to detect the case where someone treats a string arg
// like a bool:
// --my_string_var --foo=bar
// We look for a flag of string type, whose value begins with a
// dash, and where the flag-name and value are separated by a
// space rather than an '='.
// To avoid false positives, we also require the word "true"
// or "false" in the help string. Without this, a valid usage
// "-lat -30.5" would trigger the warning. The common cases we
// want to solve talk about true and false as values.
if (value[0] == '-'
&& strcmp(flag->type_name(), "string") == 0
&& (strstr(flag->help(), "true")
|| strstr(flag->help(), "false"))) {
fprintf(stderr, "Did you really mean to set flag '%s'"
" to the value '%s'?\n",
flag->name(), value);
}
}
}
// TODO(csilvers): only set a flag if we hadn't set it before here
ProcessSingleOptionLocked(flag, value, SET_FLAGS_VALUE);
}
registry_->Unlock();
if (remove_flags) { // Fix up argc and argv by removing command line flags
(*argv)[first_nonopt-1] = (*argv)[0];
(*argv) += (first_nonopt-1);
(*argc) -= (first_nonopt-1);
first_nonopt = 1; // because we still don't count argv[0]
}
logging_is_probably_set_up = true; // because we've parsed --logdir, etc.
return first_nonopt;
}
string CommandLineFlagParser::ProcessFlagfileLocked(const string& flagval,
FlagSettingMode set_mode) {
if (flagval.empty())
return "";
string msg;
vector<string> filename_list;
ParseFlagList(flagval.c_str(), &filename_list); // take a list of filenames
for (size_t i = 0; i < filename_list.size(); ++i) {
const char* file = filename_list[i].c_str();
msg += ProcessOptionsFromStringLocked(ReadFileIntoString(file), set_mode);
}
return msg;
}
string CommandLineFlagParser::ProcessFromenvLocked(const string& flagval,
FlagSettingMode set_mode,
bool errors_are_fatal) {
if (flagval.empty())
return "";
string msg;
vector<string> flaglist;
ParseFlagList(flagval.c_str(), &flaglist);
for (size_t i = 0; i < flaglist.size(); ++i) {
const char* flagname = flaglist[i].c_str();
CommandLineFlag* flag = registry_->FindFlagLocked(flagname);
if (flag == NULL) {
error_flags_[flagname] = (string(kError) + "unknown command line flag"
+ " '" + flagname + "'"
+ " (via --fromenv or --tryfromenv)\n");
undefined_names_[flagname] = "";
continue;
}
const string envname = string("FLAGS_") + string(flagname);
const char* envval = getenv(envname.c_str());
if (!envval) {
if (errors_are_fatal) {
error_flags_[flagname] = (string(kError) + envname +
" not found in environment\n");
}
continue;
}
// Avoid infinite recursion.
if ((strcmp(envval, "fromenv") == 0) ||
(strcmp(envval, "tryfromenv") == 0)) {
error_flags_[flagname] = (string(kError) + "infinite recursion on " +
"environment flag '" + envval + "'\n");
continue;
}
msg += ProcessSingleOptionLocked(flag, envval, set_mode);
}
return msg;
}
string CommandLineFlagParser::ProcessSingleOptionLocked(
CommandLineFlag* flag, const char* value, FlagSettingMode set_mode) {
string msg;
if (value && !registry_->SetFlagLocked(flag, value, set_mode, &msg)) {
error_flags_[flag->name()] = msg;
return "";
}
// The recursive flags, --flagfile and --fromenv and --tryfromenv,
// must be dealt with as soon as they're seen. They will emit
// messages of their own.
if (strcmp(flag->name(), "flagfile") == 0) {
msg += ProcessFlagfileLocked(FLAGS_flagfile, set_mode);
} else if (strcmp(flag->name(), "fromenv") == 0) {
// last arg indicates envval-not-found is fatal (unlike in --tryfromenv)
msg += ProcessFromenvLocked(FLAGS_fromenv, set_mode, true);
} else if (strcmp(flag->name(), "tryfromenv") == 0) {
msg += ProcessFromenvLocked(FLAGS_tryfromenv, set_mode, false);
}
return msg;
}
void CommandLineFlagParser::ValidateAllFlags() {
FlagRegistryLock frl(registry_);
for (FlagRegistry::FlagConstIterator i = registry_->flags_.begin();
i != registry_->flags_.end(); ++i) {
if (!i->second->ValidateCurrent()) {
// only set a message if one isn't already there. (If there's
// an error message, our job is done, even if it's not exactly
// the same error.)
if (error_flags_[i->second->name()].empty())
error_flags_[i->second->name()] =
string(kError) + "--" + i->second->name() +
" must be set on the commandline"
" (default value fails validation)\n";
}
}
}
bool CommandLineFlagParser::ReportErrors() {
// error_flags_ indicates errors we saw while parsing.
// But we ignore undefined-names if ok'ed by --undef_ok
if (!FLAGS_undefok.empty()) {
vector<string> flaglist;
ParseFlagList(FLAGS_undefok.c_str(), &flaglist);
for (size_t i = 0; i < flaglist.size(); ++i) {
// We also deal with --no<flag>, in case the flagname was boolean
const string no_version = string("no") + flaglist[i];
if (undefined_names_.find(flaglist[i]) != undefined_names_.end()) {
error_flags_[flaglist[i]] = ""; // clear the error message
} else if (undefined_names_.find(no_version) != undefined_names_.end()) {
error_flags_[no_version] = "";
}
}
}
// Likewise, if they decided to allow reparsing, all undefined-names
// are ok; we just silently ignore them now, and hope that a future
// parse will pick them up somehow.
if (allow_command_line_reparsing) {
for (map<string, string>::const_iterator it = undefined_names_.begin();
it != undefined_names_.end(); ++it)
error_flags_[it->first] = ""; // clear the error message
}
bool found_error = false;
string error_message;
for (map<string, string>::const_iterator it = error_flags_.begin();
it != error_flags_.end(); ++it) {
if (!it->second.empty()) {
error_message.append(it->second.data(), it->second.size());
found_error = true;
}
}
if (found_error)
ReportError(DO_NOT_DIE, "%s", error_message.c_str());
return found_error;
}
string CommandLineFlagParser::ProcessOptionsFromStringLocked(
const string& contentdata, FlagSettingMode set_mode) {
string retval;
const char* flagfile_contents = contentdata.c_str();
bool flags_are_relevant = true; // set to false when filenames don't match
bool in_filename_section = false;
const char* line_end = flagfile_contents;
// We read this file a line at a time.
for (; line_end; flagfile_contents = line_end + 1) {
while (*flagfile_contents && isspace(*flagfile_contents))
++flagfile_contents;
line_end = strchr(flagfile_contents, '\n');
size_t len = line_end ? static_cast<size_t>(line_end - flagfile_contents)
: strlen(flagfile_contents);
string line(flagfile_contents, len);
// Each line can be one of four things:
// 1) A comment line -- we skip it
// 2) An empty line -- we skip it
// 3) A list of filenames -- starts a new filenames+flags section
// 4) A --flag=value line -- apply if previous filenames match
if (line.empty() || line[0] == '#') {
// comment or empty line; just ignore
} else if (line[0] == '-') { // flag
in_filename_section = false; // instead, it was a flag-line
if (!flags_are_relevant) // skip this flag; applies to someone else
continue;
const char* name_and_val = line.c_str() + 1; // skip the leading -
if (*name_and_val == '-')
name_and_val++; // skip second - too
string key;
const char* value;
string error_message;
CommandLineFlag* flag = registry_->SplitArgumentLocked(name_and_val,
&key, &value,
&error_message);
// By API, errors parsing flagfile lines are silently ignored.
if (flag == NULL) {
// "WARNING: flagname '" + key + "' not found\n"
} else if (value == NULL) {
// "WARNING: flagname '" + key + "' missing a value\n"
} else {
retval += ProcessSingleOptionLocked(flag, value, set_mode);
}
} else { // a filename!
if (!in_filename_section) { // start over: assume filenames don't match
in_filename_section = true;
flags_are_relevant = false;
}
// Split the line up at spaces into glob-patterns
const char* space = line.c_str(); // just has to be non-NULL
for (const char* word = line.c_str(); *space; word = space+1) {
if (flags_are_relevant) // we can stop as soon as we match
break;
space = strchr(word, ' ');
if (space == NULL)
space = word + strlen(word);
const string glob(word, space - word);
// We try matching both against the full argv0 and basename(argv0)
#ifdef HAVE_FNMATCH_H
if (fnmatch(glob.c_str(),
ProgramInvocationName(),
FNM_PATHNAME) == 0 ||
fnmatch(glob.c_str(),
ProgramInvocationShortName(),
FNM_PATHNAME) == 0) {
#else // !HAVE_FNMATCH_H
if ((glob == ProgramInvocationName()) ||
(glob == ProgramInvocationShortName())) {
#endif // HAVE_FNMATCH_H
flags_are_relevant = true;
}
}
}
}
return retval;
}
// --------------------------------------------------------------------
// GetFromEnv()
// AddFlagValidator()
// These are helper functions for routines like BoolFromEnv() and
// RegisterFlagValidator, defined below. They're defined here so
// they can live in the unnamed namespace (which makes friendship
// declarations for these classes possible).
// --------------------------------------------------------------------
template<typename T>
T GetFromEnv(const char *varname, const char* type, T dflt) {
const char* const valstr = getenv(varname);
if (!valstr)
return dflt;
FlagValue ifv(new T, type, true);
if (!ifv.ParseFrom(valstr))
ReportError(DIE, "ERROR: error parsing env variable '%s' with value '%s'\n",
varname, valstr);
return OTHER_VALUE_AS(ifv, T);
}
bool AddFlagValidator(const void* flag_ptr, ValidateFnProto validate_fn_proto) {
// We want a lock around this routine, in case two threads try to
// add a validator (hopefully the same one!) at once. We could use
// our own thread, but we need to loook at the registry anyway, so
// we just steal that one.
FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
FlagRegistryLock frl(registry);
// First, find the flag whose current-flag storage is 'flag'.
// This is the CommandLineFlag whose current_->value_buffer_ == flag
CommandLineFlag* flag = registry->FindFlagViaPtrLocked(flag_ptr);
if (!flag) {
// WARNING << "Ignoring RegisterValidateFunction() for flag pointer "
// << flag_ptr << ": no flag found at that address";
return false;
} else if (validate_fn_proto == flag->validate_function()) {
return true; // ok to register the same function over and over again
} else if (validate_fn_proto != NULL && flag->validate_function() != NULL) {
// WARNING << "Ignoring RegisterValidateFunction() for flag '"
// << flag->name() << "': validate-fn already registered";
return false;
} else {
flag->validate_fn_proto_ = validate_fn_proto;
return true;
}
}
} // end unnamed namespaces
// Now define the functions that are exported via the .h file
// --------------------------------------------------------------------
// FlagRegisterer
// This class exists merely to have a global constructor (the
// kind that runs before main(), that goes an initializes each
// flag that's been declared. Note that it's very important we
// don't have a destructor that deletes flag_, because that would
// cause us to delete current_storage/defvalue_storage as well,
// which can cause a crash if anything tries to access the flag
// values in a global destructor.
// --------------------------------------------------------------------
FlagRegisterer::FlagRegisterer(const char* name, const char* type,
const char* help, const char* filename,
void* current_storage, void* defvalue_storage) {
if (help == NULL)
help = "";
// FlagValue expects the type-name to not include any namespace
// components, so we get rid of those, if any.
if (strchr(type, ':'))
type = strrchr(type, ':') + 1;
FlagValue* current = new FlagValue(current_storage, type, false);
FlagValue* defvalue = new FlagValue(defvalue_storage, type, false);
// Importantly, flag_ will never be deleted, so storage is always good.
CommandLineFlag* flag = new CommandLineFlag(name, help, filename,
current, defvalue);
FlagRegistry::GlobalRegistry()->RegisterFlag(flag); // default registry
}
// --------------------------------------------------------------------
// GetAllFlags()
// The main way the FlagRegistry class exposes its data. This
// returns, as strings, all the info about all the flags in
// the main registry, sorted first by filename they are defined
// in, and then by flagname.
// --------------------------------------------------------------------
struct FilenameFlagnameCmp {
bool operator()(const CommandLineFlagInfo& a,
const CommandLineFlagInfo& b) const {
int cmp = strcmp(a.filename.c_str(), b.filename.c_str());
if (cmp == 0)
cmp = strcmp(a.name.c_str(), b.name.c_str()); // secondary sort key
return cmp < 0;
}
};
void GetAllFlags(vector<CommandLineFlagInfo>* OUTPUT) {
FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
registry->Lock();
for (FlagRegistry::FlagConstIterator i = registry->flags_.begin();
i != registry->flags_.end(); ++i) {
CommandLineFlagInfo fi;
i->second->FillCommandLineFlagInfo(&fi);
OUTPUT->push_back(fi);
}
registry->Unlock();
// Now sort the flags, first by filename they occur in, then alphabetically
sort(OUTPUT->begin(), OUTPUT->end(), FilenameFlagnameCmp());
}
// --------------------------------------------------------------------
// SetArgv()
// GetArgvs()
// GetArgv()
// GetArgv0()
// ProgramInvocationName()
// ProgramInvocationShortName()
// SetUsageMessage()
// ProgramUsage()
// Functions to set and get argv. Typically the setter is called
// by ParseCommandLineFlags. Also can get the ProgramUsage string,
// set by SetUsageMessage.
// --------------------------------------------------------------------
// These values are not protected by a Mutex because they are normally
// set only once during program startup.
static const char* argv0 = "UNKNOWN"; // just the program name
static const char* cmdline = ""; // the entire command-line
static vector<string> argvs;
static uint32 argv_sum = 0;
static const char* program_usage = NULL;
void SetArgv(int argc, const char** argv) {
static bool called_set_argv = false;
if (called_set_argv) // we already have an argv for you
return;
called_set_argv = true;
assert(argc > 0); // every program has at least a progname
argv0 = strdup(argv[0]); // small memory leak, but fn only called once
assert(argv0);
string cmdline_string; // easier than doing strcats
for (int i = 0; i < argc; i++) {
if (i != 0) {
cmdline_string += " ";
}
cmdline_string += argv[i];
argvs.push_back(argv[i]);
}
cmdline = strdup(cmdline_string.c_str()); // another small memory leak
assert(cmdline);
// Compute a simple sum of all the chars in argv
for (const char* c = cmdline; *c; c++)
argv_sum += *c;
}
const vector<string>& GetArgvs() { return argvs; }
const char* GetArgv() { return cmdline; }
const char* GetArgv0() { return argv0; }
uint32 GetArgvSum() { return argv_sum; }
const char* ProgramInvocationName() { // like the GNU libc fn
return GetArgv0();
}
const char* ProgramInvocationShortName() { // like the GNU libc fn
const char* slash = strrchr(argv0, '/');
#ifdef OS_WINDOWS
if (!slash) slash = strrchr(argv0, '\\');
#endif
return slash ? slash + 1 : argv0;
}
void SetUsageMessage(const string& usage) {
if (program_usage != NULL)
ReportError(DIE, "ERROR: SetUsageMessage() called twice\n");
program_usage = strdup(usage.c_str()); // small memory leak
}
const char* ProgramUsage() {
if (program_usage) {
return program_usage;
}
return "Warning: SetUsageMessage() never called";
}
// --------------------------------------------------------------------
// GetCommandLineOption()
// GetCommandLineFlagInfo()
// GetCommandLineFlagInfoOrDie()
// SetCommandLineOption()
// SetCommandLineOptionWithMode()
// The programmatic way to set a flag's value, using a string
// for its name rather than the variable itself (that is,
// SetCommandLineOption("foo", x) rather than FLAGS_foo = x).
// There's also a bit more flexibility here due to the various
// set-modes, but typically these are used when you only have
// that flag's name as a string, perhaps at runtime.
// All of these work on the default, global registry.
// For GetCommandLineOption, return false if no such flag
// is known, true otherwise. We clear "value" if a suitable
// flag is found.
// --------------------------------------------------------------------
bool GetCommandLineOption(const char* name, string* value) {
if (NULL == name)
return false;
assert(value);
FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
FlagRegistryLock frl(registry);
CommandLineFlag* flag = registry->FindFlagLocked(name);
if (flag == NULL) {
return false;
} else {
*value = flag->current_value();
return true;
}
}
bool GetCommandLineFlagInfo(const char* name, CommandLineFlagInfo* OUTPUT) {
if (NULL == name) return false;
FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
FlagRegistryLock frl(registry);
CommandLineFlag* flag = registry->FindFlagLocked(name);
if (flag == NULL) {
return false;
} else {
assert(OUTPUT);
flag->FillCommandLineFlagInfo(OUTPUT);
return true;
}
}
CommandLineFlagInfo GetCommandLineFlagInfoOrDie(const char* name) {
CommandLineFlagInfo info;
if (!GetCommandLineFlagInfo(name, &info)) {
fprintf(stderr, "FATAL ERROR: flag name '%s' doesn't exist\n", name);
commandlineflags_exitfunc(1); // almost certainly exit()
}
return info;
}
string SetCommandLineOptionWithMode(const char* name, const char* value,
FlagSettingMode set_mode) {
string result;
FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
FlagRegistryLock frl(registry);
CommandLineFlag* flag = registry->FindFlagLocked(name);
if (flag) {
CommandLineFlagParser parser(registry);
result = parser.ProcessSingleOptionLocked(flag, value, set_mode);
if (!result.empty()) { // in the error case, we've already logged
// You could consider logging this change, if you wanted to know it:
//fprintf(stderr, "%sFLAGS_%s\n",
// (set_mode == SET_FLAGS_DEFAULT ? "default value of " : ""),
// result);
}
}
// The API of this function is that we return empty string on error
return result;
}
string SetCommandLineOption(const char* name, const char* value) {
return SetCommandLineOptionWithMode(name, value, SET_FLAGS_VALUE);
}
// --------------------------------------------------------------------
// FlagSaver
// FlagSaverImpl
// This class stores the states of all flags at construct time,
// and restores all flags to that state at destruct time.
// Its major implementation challenge is that it never modifies
// pointers in the 'main' registry, so global FLAG_* vars always
// point to the right place.
// --------------------------------------------------------------------
class FlagSaverImpl {
public:
// Constructs an empty FlagSaverImpl object.
explicit FlagSaverImpl(FlagRegistry* main_registry)
: main_registry_(main_registry) { }
~FlagSaverImpl() {
// reclaim memory from each of our CommandLineFlags
vector<CommandLineFlag*>::const_iterator it;
for (it = backup_registry_.begin(); it != backup_registry_.end(); ++it)
delete *it;
}
// Saves the flag states from the flag registry into this object.
// It's an error to call this more than once.
// Must be called when the registry mutex is not held.
void SaveFromRegistry() {
FlagRegistryLock frl(main_registry_);
assert(backup_registry_.empty()); // call only once!
for (FlagRegistry::FlagConstIterator it = main_registry_->flags_.begin();
it != main_registry_->flags_.end();
++it) {
const CommandLineFlag* main = it->second;
// Sets up all the const variables in backup correctly
CommandLineFlag* backup = new CommandLineFlag(
main->name(), main->help(), main->filename(),
main->current_->New(), main->defvalue_->New());
// Sets up all the non-const variables in backup correctly
backup->CopyFrom(*main);
backup_registry_.push_back(backup); // add it to a convenient list
}
}
// Restores the saved flag states into the flag registry. We
// assume no flags were added or deleted from the registry since
// the SaveFromRegistry; if they were, that's trouble! Must be
// called when the registry mutex is not held.
void RestoreToRegistry() {
FlagRegistryLock frl(main_registry_);
vector<CommandLineFlag*>::const_iterator it;
for (it = backup_registry_.begin(); it != backup_registry_.end(); ++it) {
CommandLineFlag* main = main_registry_->FindFlagLocked((*it)->name());
if (main != NULL) { // if NULL, flag got deleted from registry(!)
main->CopyFrom(**it);
}
}
}
private:
FlagRegistry* const main_registry_;
vector<CommandLineFlag*> backup_registry_;
FlagSaverImpl(const FlagSaverImpl&); // no copying!
void operator=(const FlagSaverImpl&);
};
FlagSaver::FlagSaver()
: impl_(new FlagSaverImpl(FlagRegistry::GlobalRegistry())) {
impl_->SaveFromRegistry();
}
FlagSaver::~FlagSaver() {
impl_->RestoreToRegistry();
delete impl_;
}
// --------------------------------------------------------------------
// CommandlineFlagsIntoString()
// ReadFlagsFromString()
// AppendFlagsIntoFile()
// ReadFromFlagsFile()
// These are mostly-deprecated routines that stick the
// commandline flags into a file/string and read them back
// out again. I can see a use for CommandlineFlagsIntoString,
// for creating a flagfile, but the rest don't seem that useful
// -- some, I think, are a poor-man's attempt at FlagSaver --
// and are included only until we can delete them from callers.
// Note they don't save --flagfile flags (though they do save
// the result of having called the flagfile, of course).
// --------------------------------------------------------------------
static string TheseCommandlineFlagsIntoString(
const vector<CommandLineFlagInfo>& flags) {
vector<CommandLineFlagInfo>::const_iterator i;
size_t retval_space = 0;
for (i = flags.begin(); i != flags.end(); ++i) {
// An (over)estimate of how much space it will take to print this flag
retval_space += i->name.length() + i->current_value.length() + 5;
}
string retval;
retval.reserve(retval_space);
for (i = flags.begin(); i != flags.end(); ++i) {
retval += "--";
retval += i->name;
retval += "=";
retval += i->current_value;
retval += "\n";
}
return retval;
}
string CommandlineFlagsIntoString() {
vector<CommandLineFlagInfo> sorted_flags;
GetAllFlags(&sorted_flags);
return TheseCommandlineFlagsIntoString(sorted_flags);
}
bool ReadFlagsFromString(const string& flagfilecontents,
const char* /*prog_name*/, // TODO(csilvers): nix this
bool errors_are_fatal) {
FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
FlagSaverImpl saved_states(registry);
saved_states.SaveFromRegistry();
CommandLineFlagParser parser(registry);
registry->Lock();
parser.ProcessOptionsFromStringLocked(flagfilecontents, SET_FLAGS_VALUE);
registry->Unlock();
// Should we handle --help and such when reading flags from a string? Sure.
HandleCommandLineHelpFlags();
if (parser.ReportErrors()) {
// Error. Restore all global flags to their previous values.
if (errors_are_fatal)
commandlineflags_exitfunc(1); // almost certainly exit()
saved_states.RestoreToRegistry();
return false;
}
return true;
}
// TODO(csilvers): nix prog_name in favor of ProgramInvocationShortName()
bool AppendFlagsIntoFile(const string& filename, const char *prog_name) {
FILE *fp = fopen(filename.c_str(), "a");
if (!fp) {
return false;
}
if (prog_name)
fprintf(fp, "%s\n", prog_name);
vector<CommandLineFlagInfo> flags;
GetAllFlags(&flags);
// But we don't want --flagfile, which leads to weird recursion issues
vector<CommandLineFlagInfo>::iterator i;
for (i = flags.begin(); i != flags.end(); ++i) {
if (strcmp(i->name.c_str(), "flagfile") == 0) {
flags.erase(i);
break;
}
}
fprintf(fp, "%s", TheseCommandlineFlagsIntoString(flags).c_str());
fclose(fp);
return true;
}
bool ReadFromFlagsFile(const string& filename, const char* prog_name,
bool errors_are_fatal) {
return ReadFlagsFromString(ReadFileIntoString(filename.c_str()),
prog_name, errors_are_fatal);
}
// --------------------------------------------------------------------
// BoolFromEnv()
// Int32FromEnv()
// Int64FromEnv()
// Uint64FromEnv()
// DoubleFromEnv()
// StringFromEnv()
// Reads the value from the environment and returns it.
// We use an FlagValue to make the parsing easy.
// Example usage:
// DEFINE_bool(myflag, BoolFromEnv("MYFLAG_DEFAULT", false), "whatever");
// --------------------------------------------------------------------
bool BoolFromEnv(const char *v, bool dflt) {
return GetFromEnv(v, "bool", dflt);
}
int32 Int32FromEnv(const char *v, int32 dflt) {
return GetFromEnv(v, "int32", dflt);
}
int64 Int64FromEnv(const char *v, int64 dflt) {
return GetFromEnv(v, "int64", dflt);
}
uint64 Uint64FromEnv(const char *v, uint64 dflt) {
return GetFromEnv(v, "uint64", dflt);
}
double DoubleFromEnv(const char *v, double dflt) {
return GetFromEnv(v, "double", dflt);
}
const char *StringFromEnv(const char *varname, const char *dflt) {
const char* const val = getenv(varname);
return val ? val : dflt;
}
// --------------------------------------------------------------------
// RegisterFlagValidator()
// RegisterFlagValidator() is the function that clients use to
// 'decorate' a flag with a validation function. Once this is
// done, every time the flag is set (including when the flag
// is parsed from argv), the validator-function is called.
// These functions return true if the validator was added
// successfully, or false if not: the flag already has a validator,
// (only one allowed per flag), the 1st arg isn't a flag, etc.
// This function is not thread-safe.
// --------------------------------------------------------------------
bool RegisterFlagValidator(const bool* flag,
bool (*validate_fn)(const char*, bool)) {
return AddFlagValidator(flag, reinterpret_cast<ValidateFnProto>(validate_fn));
}
bool RegisterFlagValidator(const int32* flag,
bool (*validate_fn)(const char*, int32)) {
return AddFlagValidator(flag, reinterpret_cast<ValidateFnProto>(validate_fn));
}
bool RegisterFlagValidator(const int64* flag,
bool (*validate_fn)(const char*, int64)) {
return AddFlagValidator(flag, reinterpret_cast<ValidateFnProto>(validate_fn));
}
bool RegisterFlagValidator(const uint64* flag,
bool (*validate_fn)(const char*, uint64)) {
return AddFlagValidator(flag, reinterpret_cast<ValidateFnProto>(validate_fn));
}
bool RegisterFlagValidator(const double* flag,
bool (*validate_fn)(const char*, double)) {
return AddFlagValidator(flag, reinterpret_cast<ValidateFnProto>(validate_fn));
}
bool RegisterFlagValidator(const string* flag,
bool (*validate_fn)(const char*, const string&)) {
return AddFlagValidator(flag, reinterpret_cast<ValidateFnProto>(validate_fn));
}
// --------------------------------------------------------------------
// ParseCommandLineFlags()
// ParseCommandLineNonHelpFlags()
// HandleCommandLineHelpFlags()
// This is the main function called from main(), to actually
// parse the commandline. It modifies argc and argv as described
// at the top of gflags.h. You can also divide this
// function into two parts, if you want to do work between
// the parsing of the flags and the printing of any help output.
// --------------------------------------------------------------------
static uint32 ParseCommandLineFlagsInternal(int* argc, char*** argv,
bool remove_flags, bool do_report) {
SetArgv(*argc, const_cast<const char**>(*argv)); // save it for later
FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
CommandLineFlagParser parser(registry);
// When we parse the commandline flags, we'll handle --flagfile,
// --tryfromenv, etc. as we see them (since flag-evaluation order
// may be important). But sometimes apps set FLAGS_tryfromenv/etc.
// manually before calling ParseCommandLineFlags. We want to evaluate
// those too, as if they were the first flags on the commandline.
registry->Lock();
parser.ProcessFlagfileLocked(FLAGS_flagfile, SET_FLAGS_VALUE);
// Last arg here indicates whether flag-not-found is a fatal error or not
parser.ProcessFromenvLocked(FLAGS_fromenv, SET_FLAGS_VALUE, true);
parser.ProcessFromenvLocked(FLAGS_tryfromenv, SET_FLAGS_VALUE, false);
registry->Unlock();
// Now get the flags specified on the commandline
const int r = parser.ParseNewCommandLineFlags(argc, argv, remove_flags);
if (do_report)
HandleCommandLineHelpFlags(); // may cause us to exit on --help, etc.
// See if any of the unset flags fail their validation checks
parser.ValidateAllFlags();
if (parser.ReportErrors()) // may cause us to exit on illegal flags
commandlineflags_exitfunc(1); // almost certainly exit()
return r;
}
uint32 ParseCommandLineFlags(int* argc, char*** argv, bool remove_flags) {
return ParseCommandLineFlagsInternal(argc, argv, remove_flags, true);
}
uint32 ParseCommandLineNonHelpFlags(int* argc, char*** argv,
bool remove_flags) {
return ParseCommandLineFlagsInternal(argc, argv, remove_flags, false);
}
// --------------------------------------------------------------------
// AllowCommandLineReparsing()
// ReparseCommandLineNonHelpFlags()
// This is most useful for shared libraries. The idea is if
// a flag is defined in a shared library that is dlopen'ed
// sometime after main(), you can ParseCommandLineFlags before
// the dlopen, then ReparseCommandLineNonHelpFlags() after the
// dlopen, to get the new flags. But you have to explicitly
// Allow() it; otherwise, you get the normal default behavior
// of unrecognized flags calling a fatal error.
// TODO(csilvers): this isn't used. Just delete it?
// --------------------------------------------------------------------
void AllowCommandLineReparsing() {
allow_command_line_reparsing = true;
}
uint32 ReparseCommandLineNonHelpFlags() {
// We make a copy of argc and argv to pass in
const vector<string>& argvs = GetArgvs();
int tmp_argc = static_cast<int>(argvs.size());
char** tmp_argv = new char* [tmp_argc + 1];
for (int i = 0; i < tmp_argc; ++i)
tmp_argv[i] = strdup(argvs[i].c_str()); // TODO(csilvers): don't dup
const int retval = ParseCommandLineNonHelpFlags(&tmp_argc, &tmp_argv, false);
for (int i = 0; i < tmp_argc; ++i)
free(tmp_argv[i]);
delete[] tmp_argv;
return retval;
}
void ShutDownCommandLineFlags() {
FlagRegistry::DeleteGlobalRegistry();
}
_END_GOOGLE_NAMESPACE_
// Copyright (c) 1999, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define _GNU_SOURCE 1 // needed for O_NOFOLLOW and pread()/pwrite()
#include "utilities.h"
#include <assert.h>
#include <iomanip>
#include <string>
#ifdef HAVE_UNISTD_H
# include <unistd.h> // For _exit.
#endif
#include <climits>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_SYS_UTSNAME_H
# include <sys/utsname.h> // For uname.
#endif
#include <fcntl.h>
#include <cstdio>
#include <iostream>
#include <stdarg.h>
#include <stdlib.h>
#ifdef HAVE_PWD_H
# include <pwd.h>
#endif
#ifdef HAVE_SYSLOG_H
# include <syslog.h>
#endif
#include <vector>
#include <errno.h> // for errno
#include <sstream>
#include "base/commandlineflags.h" // to get the program name
#include "glog/logging.h"
#include "glog/raw_logging.h"
#include "base/googleinit.h"
#ifdef HAVE_STACKTRACE
# include "stacktrace.h"
#endif
using std::string;
using std::vector;
using std::ostrstream;
using std::setw;
using std::setfill;
using std::hex;
using std::dec;
using std::min;
using std::ostream;
using std::ostringstream;
using std::strstream;
// There is no thread annotation support.
#define EXCLUSIVE_LOCKS_REQUIRED(mu)
static bool BoolFromEnv(const char *varname, bool defval) {
const char* const valstr = getenv(varname);
if (!valstr) {
return defval;
}
return memchr("tTyY1\0", valstr[0], 6) != NULL;
}
GLOG_DEFINE_bool(logtostderr, BoolFromEnv("GOOGLE_LOGTOSTDERR", false),
"log messages go to stderr instead of logfiles");
GLOG_DEFINE_bool(alsologtostderr, BoolFromEnv("GOOGLE_ALSOLOGTOSTDERR", false),
"log messages go to stderr in addition to logfiles");
#ifdef OS_LINUX
GLOG_DEFINE_bool(drop_log_memory, true, "Drop in-memory buffers of log contents. "
"Logs can grow very quickly and they are rarely read before they "
"need to be evicted from memory. Instead, drop them from memory "
"as soon as they are flushed to disk.");
_START_GOOGLE_NAMESPACE_
namespace logging {
static const int64 kPageSize = getpagesize();
}
_END_GOOGLE_NAMESPACE_
#endif
// By default, errors (including fatal errors) get logged to stderr as
// well as the file.
//
// The default is ERROR instead of FATAL so that users can see problems
// when they run a program without having to look in another file.
DEFINE_int32(stderrthreshold,
GOOGLE_NAMESPACE::ERROR,
"log messages at or above this level are copied to stderr in "
"addition to logfiles. This flag obsoletes --alsologtostderr.");
GLOG_DEFINE_string(alsologtoemail, "",
"log messages go to these email addresses "
"in addition to logfiles");
GLOG_DEFINE_bool(log_prefix, true,
"Prepend the log prefix to the start of each log line");
GLOG_DEFINE_int32(minloglevel, 0, "Messages logged at a lower level than this don't "
"actually get logged anywhere");
GLOG_DEFINE_int32(logbuflevel, 0,
"Buffer log messages logged at this level or lower"
" (-1 means don't buffer; 0 means buffer INFO only;"
" ...)");
GLOG_DEFINE_int32(logbufsecs, 30,
"Buffer log messages for at most this many seconds");
GLOG_DEFINE_int32(logemaillevel, 999,
"Email log messages logged at this level or higher"
" (0 means email all; 3 means email FATAL only;"
" ...)");
GLOG_DEFINE_string(logmailer, "/bin/mail",
"Mailer used to send logging email");
// Compute the default value for --log_dir
static const char* DefaultLogDir() {
const char* env;
env = getenv("GOOGLE_LOG_DIR");
if (env != NULL && env[0] != '\0') {
return env;
}
env = getenv("TEST_TMPDIR");
if (env != NULL && env[0] != '\0') {
return env;
}
return "";
}
GLOG_DEFINE_string(log_dir, DefaultLogDir(),
"If specified, logfiles are written into this directory instead "
"of the default logging directory.");
GLOG_DEFINE_string(log_link, "", "Put additional links to the log "
"files in this directory");
GLOG_DEFINE_int32(max_log_size, 1800,
"approx. maximum log file size (in MB). A value of 0 will "
"be silently overridden to 1.");
GLOG_DEFINE_bool(stop_logging_if_full_disk, false,
"Stop attempting to log to disk if the disk is full.");
GLOG_DEFINE_string(log_backtrace_at, "",
"Emit a backtrace when logging at file:linenum.");
// TODO(hamaji): consider windows
#define PATH_SEPARATOR '/'
static void GetHostName(string* hostname) {
#if defined(HAVE_SYS_UTSNAME_H)
struct utsname buf;
if (0 != uname(&buf)) {
// ensure null termination on failure
*buf.nodename = '\0';
}
*hostname = buf.nodename;
#elif defined(OS_WINDOWS)
char buf[MAX_COMPUTERNAME_LENGTH + 1];
DWORD len = MAX_COMPUTERNAME_LENGTH + 1;
if (GetComputerNameA(buf, &len)) {
*hostname = buf;
} else {
hostname->clear();
}
#else
# warning There is no way to retrieve the host name.
*hostname = "(unknown)";
#endif
}
_START_GOOGLE_NAMESPACE_
// Safely get max_log_size, overriding to 1 if it somehow gets defined as 0
static int32 MaxLogSize() {
return (FLAGS_max_log_size > 0 ? FLAGS_max_log_size : 1);
}
// A mutex that allows only one thread to log at a time, to keep things from
// getting jumbled. Some other very uncommon logging operations (like
// changing the destination file for log messages of a given severity) also
// lock this mutex. Please be sure that anybody who might possibly need to
// lock it does so.
static Mutex log_mutex;
// Number of messages sent at each severity. Under log_mutex.
int64 LogMessage::num_messages_[NUM_SEVERITIES] = {0, 0, 0, 0};
// Globally disable log writing (if disk is full)
static bool stop_writing = false;
const char*const LogSeverityNames[NUM_SEVERITIES] = {
"INFO", "WARNING", "ERROR", "FATAL"
};
// Has the user called SetExitOnDFatal(true)?
static bool exit_on_dfatal = true;
const char* GetLogSeverityName(LogSeverity severity) {
return LogSeverityNames[severity];
}
static bool SendEmailInternal(const char*dest, const char *subject,
const char*body, bool use_logging);
base::Logger::~Logger() {
}
namespace {
// Encapsulates all file-system related state
class LogFileObject : public base::Logger {
public:
LogFileObject(LogSeverity severity, const char* base_filename);
~LogFileObject();
virtual void Write(bool force_flush, // Should we force a flush here?
time_t timestamp, // Timestamp for this entry
const char* message,
int message_len);
// Configuration options
void SetBasename(const char* basename);
void SetExtension(const char* ext);
void SetSymlinkBasename(const char* symlink_basename);
// Normal flushing routine
virtual void Flush();
// It is the actual file length for the system loggers,
// i.e., INFO, ERROR, etc.
virtual uint32 LogSize() {
MutexLock l(&lock_);
return file_length_;
}
// Internal flush routine. Exposed so that FlushLogFilesUnsafe()
// can avoid grabbing a lock. Usually Flush() calls it after
// acquiring lock_.
void FlushUnlocked();
private:
static const uint32 kRolloverAttemptFrequency = 0x20;
Mutex lock_;
bool base_filename_selected_;
string base_filename_;
string symlink_basename_;
string filename_extension_; // option users can specify (eg to add port#)
FILE* file_;
LogSeverity severity_;
uint32 bytes_since_flush_;
uint32 file_length_;
unsigned int rollover_attempt_;
int64 next_flush_time_; // cycle count at which to flush log
// Actually create a logfile using the value of base_filename_ and the
// supplied argument time_pid_string
// REQUIRES: lock_ is held
bool CreateLogfile(const char* time_pid_string);
};
} // namespace
class LogDestination {
public:
friend class LogMessage;
friend void ReprintFatalMessage();
friend base::Logger* base::GetLogger(LogSeverity);
friend void base::SetLogger(LogSeverity, base::Logger*);
// These methods are just forwarded to by their global versions.
static void SetLogDestination(LogSeverity severity,
const char* base_filename);
static void SetLogSymlink(LogSeverity severity,
const char* symlink_basename);
static void AddLogSink(LogSink *destination);
static void RemoveLogSink(LogSink *destination);
static void SetLogFilenameExtension(const char* filename_extension);
static void SetStderrLogging(LogSeverity min_severity);
static void SetEmailLogging(LogSeverity min_severity, const char* addresses);
static void LogToStderr();
// Flush all log files that are at least at the given severity level
static void FlushLogFiles(int min_severity);
static void FlushLogFilesUnsafe(int min_severity);
// we set the maximum size of our packet to be 1400, the logic being
// to prevent fragmentation.
// Really this number is arbitrary.
static const int kNetworkBytes = 1400;
static const string& hostname();
private:
LogDestination(LogSeverity severity, const char* base_filename);
~LogDestination() { }
// Take a log message of a particular severity and log it to stderr
// iff it's of a high enough severity to deserve it.
static void MaybeLogToStderr(LogSeverity severity, const char* message,
size_t len);
// Take a log message of a particular severity and log it to email
// iff it's of a high enough severity to deserve it.
static void MaybeLogToEmail(LogSeverity severity, const char* message,
size_t len);
// Take a log message of a particular severity and log it to a file
// iff the base filename is not "" (which means "don't log to me")
static void MaybeLogToLogfile(LogSeverity severity,
time_t timestamp,
const char* message, size_t len);
// Take a log message of a particular severity and log it to the file
// for that severity and also for all files with severity less than
// this severity.
static void LogToAllLogfiles(LogSeverity severity,
time_t timestamp,
const char* message, size_t len);
// Send logging info to all registered sinks.
static void LogToSinks(LogSeverity severity,
const char *full_filename,
const char *base_filename,
int line,
const struct ::tm* tm_time,
const char* message,
size_t message_len);
// Wait for all registered sinks via WaitTillSent
// including the optional one in "data".
static void WaitForSinks(LogMessage::LogMessageData* data);
static LogDestination* log_destination(LogSeverity severity);
LogFileObject fileobject_;
base::Logger* logger_; // Either &fileobject_, or wrapper around it
static LogDestination* log_destinations_[NUM_SEVERITIES];
static LogSeverity email_logging_severity_;
static string addresses_;
static string hostname_;
// arbitrary global logging destinations.
static vector<LogSink*>* sinks_;
// Protects the vector sinks_,
// but not the LogSink objects its elements reference.
static Mutex sink_mutex_;
// Disallow
LogDestination(const LogDestination&);
LogDestination& operator=(const LogDestination&);
};
// Errors do not get logged to email by default.
LogSeverity LogDestination::email_logging_severity_ = 99999;
string LogDestination::addresses_;
string LogDestination::hostname_;
vector<LogSink*>* LogDestination::sinks_ = NULL;
Mutex LogDestination::sink_mutex_;
/* static */
const string& LogDestination::hostname() {
if (hostname_.empty()) {
GetHostName(&hostname_);
if (hostname_.empty()) {
hostname_ = "(unknown)";
}
}
return hostname_;
}
LogDestination::LogDestination(LogSeverity severity,
const char* base_filename)
: fileobject_(severity, base_filename),
logger_(&fileobject_) {
}
inline void LogDestination::FlushLogFilesUnsafe(int min_severity) {
// assume we have the log_mutex or we simply don't care
// about it
for (int i = min_severity; i < NUM_SEVERITIES; i++) {
LogDestination* log = log_destination(i);
if (log != NULL) {
// Flush the base fileobject_ logger directly instead of going
// through any wrappers to reduce chance of deadlock.
log->fileobject_.FlushUnlocked();
}
}
}
inline void LogDestination::FlushLogFiles(int min_severity) {
// Prevent any subtle race conditions by wrapping a mutex lock around
// all this stuff.
MutexLock l(&log_mutex);
for (int i = min_severity; i < NUM_SEVERITIES; i++) {
LogDestination* log = log_destination(i);
if (log != NULL) {
log->logger_->Flush();
}
}
}
inline void LogDestination::SetLogDestination(LogSeverity severity,
const char* base_filename) {
assert(severity >= 0 && severity < NUM_SEVERITIES);
// Prevent any subtle race conditions by wrapping a mutex lock around
// all this stuff.
MutexLock l(&log_mutex);
log_destination(severity)->fileobject_.SetBasename(base_filename);
}
inline void LogDestination::SetLogSymlink(LogSeverity severity,
const char* symlink_basename) {
CHECK_GE(severity, 0);
CHECK_LT(severity, NUM_SEVERITIES);
MutexLock l(&log_mutex);
log_destination(severity)->fileobject_.SetSymlinkBasename(symlink_basename);
}
inline void LogDestination::AddLogSink(LogSink *destination) {
// Prevent any subtle race conditions by wrapping a mutex lock around
// all this stuff.
MutexLock l(&sink_mutex_);
if (!sinks_) sinks_ = new vector<LogSink*>;
sinks_->push_back(destination);
}
inline void LogDestination::RemoveLogSink(LogSink *destination) {
// Prevent any subtle race conditions by wrapping a mutex lock around
// all this stuff.
MutexLock l(&sink_mutex_);
// This doesn't keep the sinks in order, but who cares?
if (sinks_) {
for (int i = sinks_->size() - 1; i >= 0; i--) {
if ((*sinks_)[i] == destination) {
(*sinks_)[i] = (*sinks_)[sinks_->size() - 1];
sinks_->pop_back();
break;
}
}
}
}
inline void LogDestination::SetLogFilenameExtension(const char* ext) {
// Prevent any subtle race conditions by wrapping a mutex lock around
// all this stuff.
MutexLock l(&log_mutex);
for ( int severity = 0; severity < NUM_SEVERITIES; ++severity ) {
log_destination(severity)->fileobject_.SetExtension(ext);
}
}
inline void LogDestination::SetStderrLogging(LogSeverity min_severity) {
assert(min_severity >= 0 && min_severity < NUM_SEVERITIES);
// Prevent any subtle race conditions by wrapping a mutex lock around
// all this stuff.
MutexLock l(&log_mutex);
FLAGS_stderrthreshold = min_severity;
}
inline void LogDestination::LogToStderr() {
// *Don't* put this stuff in a mutex lock, since SetStderrLogging &
// SetLogDestination already do the locking!
SetStderrLogging(0); // thus everything is "also" logged to stderr
for ( int i = 0; i < NUM_SEVERITIES; ++i ) {
SetLogDestination(i, ""); // "" turns off logging to a logfile
}
}
inline void LogDestination::SetEmailLogging(LogSeverity min_severity,
const char* addresses) {
assert(min_severity >= 0 && min_severity < NUM_SEVERITIES);
// Prevent any subtle race conditions by wrapping a mutex lock around
// all this stuff.
MutexLock l(&log_mutex);
LogDestination::email_logging_severity_ = min_severity;
LogDestination::addresses_ = addresses;
}
static void WriteToStderr(const char* message, size_t len) {
// Avoid using cerr from this module since we may get called during
// exit code, and cerr may be partially or fully destroyed by then.
write(STDERR_FILENO, message, len);
}
inline void LogDestination::MaybeLogToStderr(LogSeverity severity,
const char* message, size_t len) {
if ((severity >= FLAGS_stderrthreshold) || FLAGS_alsologtostderr) {
WriteToStderr(message, len);
#ifdef OS_WINDOWS
// On Windows, also output to the debugger
::OutputDebugStringA(string(message,len).c_str());
#endif
}
}
inline void LogDestination::MaybeLogToEmail(LogSeverity severity,
const char* message, size_t len) {
if (severity >= email_logging_severity_ ||
severity >= FLAGS_logemaillevel) {
string to(FLAGS_alsologtoemail);
if (!addresses_.empty()) {
if (!to.empty()) {
to += ",";
}
to += addresses_;
}
const string subject(string("[LOG] ") + LogSeverityNames[severity] + ": " +
glog_internal_namespace_::ProgramInvocationShortName());
string body(hostname());
body += "\n\n";
body.append(message, len);
// should NOT use SendEmail(). The caller of this function holds the
// log_mutex and SendEmail() calls LOG/VLOG which will block trying to
// acquire the log_mutex object. Use SendEmailInternal() and set
// use_logging to false.
SendEmailInternal(to.c_str(), subject.c_str(), body.c_str(), false);
}
}
inline void LogDestination::MaybeLogToLogfile(LogSeverity severity,
time_t timestamp,
const char* message,
size_t len) {
const bool should_flush = severity > FLAGS_logbuflevel;
LogDestination* destination = log_destination(severity);
destination->logger_->Write(should_flush, timestamp, message, len);
}
inline void LogDestination::LogToAllLogfiles(LogSeverity severity,
time_t timestamp,
const char* message,
size_t len) {
if ( FLAGS_logtostderr ) // global flag: never log to file
WriteToStderr(message, len);
else
for (int i = severity; i >= 0; --i)
LogDestination::MaybeLogToLogfile(i, timestamp, message, len);
}
inline void LogDestination::LogToSinks(LogSeverity severity,
const char *full_filename,
const char *base_filename,
int line,
const struct ::tm* tm_time,
const char* message,
size_t message_len) {
ReaderMutexLock l(&sink_mutex_);
if (sinks_) {
for (int i = sinks_->size() - 1; i >= 0; i--) {
(*sinks_)[i]->send(severity, full_filename, base_filename,
line, tm_time, message, message_len);
}
}
}
inline void LogDestination::WaitForSinks(LogMessage::LogMessageData* data) {
ReaderMutexLock l(&sink_mutex_);
if (sinks_) {
for (int i = sinks_->size() - 1; i >= 0; i--) {
(*sinks_)[i]->WaitTillSent();
}
}
const bool send_to_sink =
(data->send_method_ == &LogMessage::SendToSink) ||
(data->send_method_ == &LogMessage::SendToSinkAndLog);
if (send_to_sink && data->sink_ != NULL) {
data->sink_->WaitTillSent();
}
}
LogDestination* LogDestination::log_destinations_[NUM_SEVERITIES];
inline LogDestination* LogDestination::log_destination(LogSeverity severity) {
assert(severity >=0 && severity < NUM_SEVERITIES);
if (!log_destinations_[severity]) {
log_destinations_[severity] = new LogDestination(severity, NULL);
}
return log_destinations_[severity];
}
namespace {
LogFileObject::LogFileObject(LogSeverity severity,
const char* base_filename)
: base_filename_selected_(base_filename != NULL),
base_filename_((base_filename != NULL) ? base_filename : ""),
symlink_basename_(glog_internal_namespace_::ProgramInvocationShortName()),
filename_extension_(),
file_(NULL),
severity_(severity),
bytes_since_flush_(0),
file_length_(0),
rollover_attempt_(kRolloverAttemptFrequency-1),
next_flush_time_(0) {
assert(severity >= 0);
assert(severity < NUM_SEVERITIES);
}
LogFileObject::~LogFileObject() {
MutexLock l(&lock_);
if (file_ != NULL) {
fclose(file_);
file_ = NULL;
}
}
void LogFileObject::SetBasename(const char* basename) {
MutexLock l(&lock_);
base_filename_selected_ = true;
if (base_filename_ != basename) {
// Get rid of old log file since we are changing names
if (file_ != NULL) {
fclose(file_);
file_ = NULL;
rollover_attempt_ = kRolloverAttemptFrequency-1;
}
base_filename_ = basename;
}
}
void LogFileObject::SetExtension(const char* ext) {
MutexLock l(&lock_);
if (filename_extension_ != ext) {
// Get rid of old log file since we are changing names
if (file_ != NULL) {
fclose(file_);
file_ = NULL;
rollover_attempt_ = kRolloverAttemptFrequency-1;
}
filename_extension_ = ext;
}
}
void LogFileObject::SetSymlinkBasename(const char* symlink_basename) {
MutexLock l(&lock_);
symlink_basename_ = symlink_basename;
}
void LogFileObject::Flush() {
MutexLock l(&lock_);
FlushUnlocked();
}
void LogFileObject::FlushUnlocked(){
if (file_ != NULL) {
fflush(file_);
bytes_since_flush_ = 0;
}
// Figure out when we are due for another flush.
const int64 next = (FLAGS_logbufsecs
* static_cast<int64>(1000000)); // in usec
next_flush_time_ = CycleClock_Now() + UsecToCycles(next);
}
bool LogFileObject::CreateLogfile(const char* time_pid_string) {
string string_filename = base_filename_+filename_extension_+
time_pid_string;
const char* filename = string_filename.c_str();
int fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0664);
if (fd == -1) return false;
#ifdef HAVE_FCNTL
// Mark the file close-on-exec. We don't really care if this fails
fcntl(fd, F_SETFD, FD_CLOEXEC);
#endif
file_ = fdopen(fd, "a"); // Make a FILE*.
if (file_ == NULL) { // Man, we're screwed!
close(fd);
unlink(filename); // Erase the half-baked evidence: an unusable log file
return false;
}
// We try to create a symlink called <program_name>.<severity>,
// which is easier to use. (Every time we create a new logfile,
// we destroy the old symlink and create a new one, so it always
// points to the latest logfile.) If it fails, we're sad but it's
// no error.
if (!symlink_basename_.empty()) {
// take directory from filename
const char* slash = strrchr(filename, PATH_SEPARATOR);
const string linkname =
symlink_basename_ + '.' + LogSeverityNames[severity_];
string linkpath;
if ( slash ) linkpath = string(filename, slash-filename+1); // get dirname
linkpath += linkname;
unlink(linkpath.c_str()); // delete old one if it exists
// We must have unistd.h.
#ifdef HAVE_UNISTD_H
// Make the symlink be relative (in the same dir) so that if the
// entire log directory gets relocated the link is still valid.
const char *linkdest = slash ? (slash + 1) : filename;
symlink(linkdest, linkpath.c_str()); // silently ignore failures
// Make an additional link to the log file in a place specified by
// FLAGS_log_link, if indicated
if (!FLAGS_log_link.empty()) {
linkpath = FLAGS_log_link + "/" + linkname;
unlink(linkpath.c_str()); // delete old one if it exists
symlink(filename, linkpath.c_str()); // silently ignore failures
}
#endif
}
return true; // Everything worked
}
void LogFileObject::Write(bool force_flush,
time_t timestamp,
const char* message,
int message_len) {
MutexLock l(&lock_);
// We don't log if the base_name_ is "" (which means "don't write")
if (base_filename_selected_ && base_filename_.empty()) {
return;
}
if (static_cast<int>(file_length_ >> 20) >= MaxLogSize()) {
if (file_ != NULL) fclose(file_);
file_ = NULL;
file_length_ = bytes_since_flush_ = 0;
rollover_attempt_ = kRolloverAttemptFrequency-1;
}
// If there's no destination file, make one before outputting
if (file_ == NULL) {
// Try to rollover the log file every 32 log messages. The only time
// this could matter would be when we have trouble creating the log
// file. If that happens, we'll lose lots of log messages, of course!
if (++rollover_attempt_ != kRolloverAttemptFrequency) return;
rollover_attempt_ = 0;
struct ::tm tm_time;
localtime_r(×tamp, &tm_time);
// The logfile's filename will have the date/time & pid in it
char time_pid_string[256]; // More than enough chars for time, pid, \0
ostrstream time_pid_stream(time_pid_string, sizeof(time_pid_string));
time_pid_stream.fill('0');
time_pid_stream << 1900+tm_time.tm_year
<< setw(2) << 1+tm_time.tm_mon
<< setw(2) << tm_time.tm_mday
<< '-'
<< setw(2) << tm_time.tm_hour
<< setw(2) << tm_time.tm_min
<< setw(2) << tm_time.tm_sec
<< '.'
<< GetMainThreadPid()
<< '\0';
if (base_filename_selected_) {
if (!CreateLogfile(time_pid_string)) {
perror("Could not create log file");
fprintf(stderr, "COULD NOT CREATE LOGFILE '%s'!\n", time_pid_string);
return;
}
} else {
// If no base filename for logs of this severity has been set, use a
// default base filename of
// "<program name>.<hostname>.<user name>.log.<severity level>.". So
// logfiles will have names like
// webserver.examplehost.root.log.INFO.19990817-150000.4354, where
// 19990817 is a date (1999 August 17), 150000 is a time (15:00:00),
// and 4354 is the pid of the logging process. The date & time reflect
// when the file was created for output.
//
// Where does the file get put? Successively try the directories
// "/tmp", and "."
string stripped_filename(
glog_internal_namespace_::ProgramInvocationShortName());
string hostname;
GetHostName(&hostname);
string uidname = MyUserName();
// We should not call CHECK() here because this function can be
// called after holding on to log_mutex. We don't want to
// attempt to hold on to the same mutex, and get into a
// deadlock. Simply use a name like invalid-user.
if (uidname.empty()) uidname = "invalid-user";
stripped_filename = stripped_filename+'.'+hostname+'.'
+uidname+".log."
+LogSeverityNames[severity_]+'.';
// We're going to (potentially) try to put logs in several different dirs
const vector<string> & log_dirs = GetLoggingDirectories();
// Go through the list of dirs, and try to create the log file in each
// until we succeed or run out of options
bool success = false;
for (vector<string>::const_iterator dir = log_dirs.begin();
dir != log_dirs.end();
++dir) {
base_filename_ = *dir + "/" + stripped_filename;
if ( CreateLogfile(time_pid_string) ) {
success = true;
break;
}
}
// If we never succeeded, we have to give up
if ( success == false ) {
perror("Could not create logging file");
fprintf(stderr, "COULD NOT CREATE A LOGGINGFILE %s!", time_pid_string);
return;
}
}
// Write a header message into the log file
char file_header_string[512]; // Enough chars for time and binary info
ostrstream file_header_stream(file_header_string,
sizeof(file_header_string));
file_header_stream.fill('0');
file_header_stream << "Log file created at: "
<< 1900+tm_time.tm_year << '/'
<< setw(2) << 1+tm_time.tm_mon << '/'
<< setw(2) << tm_time.tm_mday
<< ' '
<< setw(2) << tm_time.tm_hour << ':'
<< setw(2) << tm_time.tm_min << ':'
<< setw(2) << tm_time.tm_sec << '\n'
<< "Running on machine: "
<< LogDestination::hostname() << '\n'
<< "Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu "
<< "threadid file:line] msg" << '\n'
<< '\0';
int header_len = strlen(file_header_string);
fwrite(file_header_string, 1, header_len, file_);
file_length_ += header_len;
bytes_since_flush_ += header_len;
}
// Write to LOG file
if ( !stop_writing ) {
// fwrite() doesn't return an error when the disk is full, for
// messages that are less than 4096 bytes. When the disk is full,
// it returns the message length for messages that are less than
// 4096 bytes. fwrite() returns 4096 for message lengths that are
// greater than 4096, thereby indicating an error.
errno = 0;
fwrite(message, 1, message_len, file_);
if ( FLAGS_stop_logging_if_full_disk &&
errno == ENOSPC ) { // disk full, stop writing to disk
stop_writing = true; // until the disk is
return;
} else {
file_length_ += message_len;
bytes_since_flush_ += message_len;
}
} else {
if ( CycleClock_Now() >= next_flush_time_ )
stop_writing = false; // check to see if disk has free space.
return; // no need to flush
}
// See important msgs *now*. Also, flush logs at least every 10^6 chars,
// or every "FLAGS_logbufsecs" seconds.
if ( force_flush ||
(bytes_since_flush_ >= 1000000) ||
(CycleClock_Now() >= next_flush_time_) ) {
FlushUnlocked();
#ifdef OS_LINUX
if (FLAGS_drop_log_memory) {
if (file_length_ >= logging::kPageSize) {
// don't evict the most recent page
uint32 len = file_length_ & ~(logging::kPageSize - 1);
posix_fadvise(fileno(file_), 0, len, POSIX_FADV_DONTNEED);
}
}
#endif
}
}
} // namespace
// An arbitrary limit on the length of a single log message. This
// is so that streaming can be done more efficiently.
const size_t LogMessage::kMaxLogMessageLen = 30000;
// Static log data space to avoid alloc failures in a LOG(FATAL)
//
// Since multiple threads may call LOG(FATAL), and we want to preserve
// the data from the first call, we allocate two sets of space. One
// for exclusive use by the first thread, and one for shared use by
// all other threads.
static Mutex fatal_msg_lock;
static CrashReason crash_reason;
static bool fatal_msg_exclusive = true;
static char fatal_msg_buf_exclusive[LogMessage::kMaxLogMessageLen+1];
static char fatal_msg_buf_shared[LogMessage::kMaxLogMessageLen+1];
static LogMessage::LogStream fatal_msg_stream_exclusive(
fatal_msg_buf_exclusive, LogMessage::kMaxLogMessageLen, 0);
static LogMessage::LogStream fatal_msg_stream_shared(
fatal_msg_buf_shared, LogMessage::kMaxLogMessageLen, 0);
LogMessage::LogMessageData LogMessage::fatal_msg_data_exclusive_;
LogMessage::LogMessageData LogMessage::fatal_msg_data_shared_;
LogMessage::LogMessageData::~LogMessageData() {
delete[] buf_;
delete stream_alloc_;
}
LogMessage::LogMessage(const char* file, int line, LogSeverity severity,
int ctr, void (LogMessage::*send_method)()) {
Init(file, line, severity, send_method);
data_->stream_->set_ctr(ctr);
}
LogMessage::LogMessage(const char* file, int line,
const CheckOpString& result) {
Init(file, line, FATAL, &LogMessage::SendToLog);
stream() << "Check failed: " << (*result.str_) << " ";
}
LogMessage::LogMessage(const char* file, int line) {
Init(file, line, INFO, &LogMessage::SendToLog);
}
LogMessage::LogMessage(const char* file, int line, LogSeverity severity) {
Init(file, line, severity, &LogMessage::SendToLog);
}
LogMessage::LogMessage(const char* file, int line, LogSeverity severity,
LogSink* sink, bool also_send_to_log) {
Init(file, line, severity, also_send_to_log ? &LogMessage::SendToSinkAndLog :
&LogMessage::SendToSink);
data_->sink_ = sink; // override Init()'s setting to NULL
}
LogMessage::LogMessage(const char* file, int line, LogSeverity severity,
vector<string> *outvec) {
Init(file, line, severity, &LogMessage::SaveOrSendToLog);
data_->outvec_ = outvec; // override Init()'s setting to NULL
}
LogMessage::LogMessage(const char* file, int line, LogSeverity severity,
string *message) {
Init(file, line, severity, &LogMessage::WriteToStringAndLog);
data_->message_ = message; // override Init()'s setting to NULL
}
void LogMessage::Init(const char* file,
int line,
LogSeverity severity,
void (LogMessage::*send_method)()) {
allocated_ = NULL;
if (severity != FATAL || !exit_on_dfatal) {
allocated_ = new LogMessageData();
data_ = allocated_;
data_->buf_ = new char[kMaxLogMessageLen+1];
data_->message_text_ = data_->buf_;
data_->stream_alloc_ =
new LogStream(data_->message_text_, kMaxLogMessageLen, 0);
data_->stream_ = data_->stream_alloc_;
data_->first_fatal_ = false;
} else {
MutexLock l(&fatal_msg_lock);
if (fatal_msg_exclusive) {
fatal_msg_exclusive = false;
data_ = &fatal_msg_data_exclusive_;
data_->message_text_ = fatal_msg_buf_exclusive;
data_->stream_ = &fatal_msg_stream_exclusive;
data_->first_fatal_ = true;
} else {
data_ = &fatal_msg_data_shared_;
data_->message_text_ = fatal_msg_buf_shared;
data_->stream_ = &fatal_msg_stream_shared;
data_->first_fatal_ = false;
}
data_->stream_alloc_ = NULL;
}
stream().fill('0');
data_->preserved_errno_ = errno;
data_->severity_ = severity;
data_->line_ = line;
data_->send_method_ = send_method;
data_->sink_ = NULL;
data_->outvec_ = NULL;
WallTime now = WallTime_Now();
data_->timestamp_ = static_cast<time_t>(now);
localtime_r(&data_->timestamp_, &data_->tm_time_);
int usecs = static_cast<int>((now - data_->timestamp_) * 1000000);
RawLog__SetLastTime(data_->tm_time_, usecs);
data_->num_chars_to_log_ = 0;
data_->num_chars_to_syslog_ = 0;
data_->basename_ = const_basename(file);
data_->fullname_ = file;
data_->has_been_flushed_ = false;
// If specified, prepend a prefix to each line. For example:
// I1018 160715 f5d4fbb0 logging.cc:1153]
// (log level, GMT month, date, time, thread_id, file basename, line)
// We exclude the thread_id for the default thread.
if (FLAGS_log_prefix && (line != kNoLogPrefix)) {
stream() << LogSeverityNames[severity][0]
<< setw(2) << 1+data_->tm_time_.tm_mon
<< setw(2) << data_->tm_time_.tm_mday
<< ' '
<< setw(2) << data_->tm_time_.tm_hour << ':'
<< setw(2) << data_->tm_time_.tm_min << ':'
<< setw(2) << data_->tm_time_.tm_sec << "."
<< setw(6) << usecs
<< ' '
<< setfill(' ') << setw(5)
<< static_cast<unsigned int>(GetTID()) << setfill('0')
<< ' '
<< data_->basename_ << ':' << data_->line_ << "] ";
}
data_->num_prefix_chars_ = data_->stream_->pcount();
if (!FLAGS_log_backtrace_at.empty()) {
char fileline[128];
snprintf(fileline, sizeof(fileline), "%s:%d", data_->basename_, line);
#ifdef HAVE_STACKTRACE
if (!strcmp(FLAGS_log_backtrace_at.c_str(), fileline)) {
string stacktrace;
DumpStackTraceToString(&stacktrace);
stream() << " (stacktrace:\n" << stacktrace << ") ";
}
#endif
}
}
LogMessage::~LogMessage() {
Flush();
delete allocated_;
}
// Flush buffered message, called by the destructor, or any other function
// that needs to synchronize the log.
void LogMessage::Flush() {
if (data_->has_been_flushed_ || data_->severity_ < FLAGS_minloglevel)
return;
data_->num_chars_to_log_ = data_->stream_->pcount();
data_->num_chars_to_syslog_ =
data_->num_chars_to_log_ - data_->num_prefix_chars_;
// Do we need to add a \n to the end of this message?
bool append_newline =
(data_->message_text_[data_->num_chars_to_log_-1] != '\n');
char original_final_char = '\0';
// If we do need to add a \n, we'll do it by violating the memory of the
// ostrstream buffer. This is quick, and we'll make sure to undo our
// modification before anything else is done with the ostrstream. It
// would be preferable not to do things this way, but it seems to be
// the best way to deal with this.
if (append_newline) {
original_final_char = data_->message_text_[data_->num_chars_to_log_];
data_->message_text_[data_->num_chars_to_log_++] = '\n';
}
// Prevent any subtle race conditions by wrapping a mutex lock around
// the actual logging action per se.
{
MutexLock l(&log_mutex);
(this->*(data_->send_method_))();
++num_messages_[static_cast<int>(data_->severity_)];
}
LogDestination::WaitForSinks(data_);
if (append_newline) {
// Fix the ostrstream back how it was before we screwed with it.
// It's 99.44% certain that we don't need to worry about doing this.
data_->message_text_[data_->num_chars_to_log_-1] = original_final_char;
}
// If errno was already set before we enter the logging call, we'll
// set it back to that value when we return from the logging call.
// It happens often that we log an error message after a syscall
// failure, which can potentially set the errno to some other
// values. We would like to preserve the original errno.
if (data_->preserved_errno_ != 0) {
errno = data_->preserved_errno_;
}
// Note that this message is now safely logged. If we're asked to flush
// again, as a result of destruction, say, we'll do nothing on future calls.
data_->has_been_flushed_ = true;
}
// Copy of first FATAL log message so that we can print it out again
// after all the stack traces. To preserve legacy behavior, we don't
// use fatal_msg_buf_exclusive.
static time_t fatal_time;
static char fatal_message[256];
void ReprintFatalMessage() {
if (fatal_message[0]) {
const int n = strlen(fatal_message);
if (!FLAGS_logtostderr) {
// Also write to stderr
WriteToStderr(fatal_message, n);
}
LogDestination::LogToAllLogfiles(ERROR, fatal_time, fatal_message, n);
}
}
// L >= log_mutex (callers must hold the log_mutex).
void LogMessage::SendToLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
static bool already_warned_before_initgoogle = false;
log_mutex.AssertHeld();
RAW_DCHECK(data_->num_chars_to_log_ > 0 &&
data_->message_text_[data_->num_chars_to_log_-1] == '\n', "");
// Messages of a given severity get logged to lower severity logs, too
if (!already_warned_before_initgoogle && !IsGoogleLoggingInitialized()) {
const char w[] = "WARNING: Logging before InitGoogleLogging() is "
"written to STDERR\n";
WriteToStderr(w, strlen(w));
already_warned_before_initgoogle = true;
}
// global flag: never log to file if set. Also -- don't log to a
// file if we haven't parsed the command line flags to get the
// program name.
if (FLAGS_logtostderr || !IsGoogleLoggingInitialized()) {
WriteToStderr(data_->message_text_, data_->num_chars_to_log_);
// this could be protected by a flag if necessary.
LogDestination::LogToSinks(data_->severity_,
data_->fullname_, data_->basename_,
data_->line_, &data_->tm_time_,
data_->message_text_ + data_->num_prefix_chars_,
(data_->num_chars_to_log_ -
data_->num_prefix_chars_ - 1));
} else {
// log this message to all log files of severity <= severity_
LogDestination::LogToAllLogfiles(data_->severity_, data_->timestamp_,
data_->message_text_,
data_->num_chars_to_log_);
LogDestination::MaybeLogToStderr(data_->severity_, data_->message_text_,
data_->num_chars_to_log_);
LogDestination::MaybeLogToEmail(data_->severity_, data_->message_text_,
data_->num_chars_to_log_);
LogDestination::LogToSinks(data_->severity_,
data_->fullname_, data_->basename_,
data_->line_, &data_->tm_time_,
data_->message_text_ + data_->num_prefix_chars_,
(data_->num_chars_to_log_
- data_->num_prefix_chars_ - 1));
// NOTE: -1 removes trailing \n
}
// If we log a FATAL message, flush all the log destinations, then toss
// a signal for others to catch. We leave the logs in a state that
// someone else can use them (as long as they flush afterwards)
if (data_->severity_ == FATAL && exit_on_dfatal) {
if (data_->first_fatal_) {
// Store crash information so that it is accessible from within signal
// handlers that may be invoked later.
RecordCrashReason(&crash_reason);
SetCrashReason(&crash_reason);
// Store shortened fatal message for other logs and GWQ status
const int copy = min<int>(data_->num_chars_to_log_,
sizeof(fatal_message)-1);
memcpy(fatal_message, data_->message_text_, copy);
fatal_message[copy] = '\0';
fatal_time = data_->timestamp_;
}
if (!FLAGS_logtostderr) {
for (int i = 0; i < NUM_SEVERITIES; ++i) {
if ( LogDestination::log_destinations_[i] )
LogDestination::log_destinations_[i]->logger_->Write(true, 0, "", 0);
}
}
// release the lock that our caller (directly or indirectly)
// LogMessage::~LogMessage() grabbed so that signal handlers
// can use the logging facility. Alternately, we could add
// an entire unsafe logging interface to bypass locking
// for signal handlers but this seems simpler.
log_mutex.Unlock();
LogDestination::WaitForSinks(data_);
const char* message = "*** Check failure stack trace: ***\n";
write(STDERR_FILENO, message, strlen(message));
Fail();
}
}
void LogMessage::RecordCrashReason(
glog_internal_namespace_::CrashReason* reason) {
reason->filename = fatal_msg_data_exclusive_.fullname_;
reason->line_number = fatal_msg_data_exclusive_.line_;
reason->message = fatal_msg_buf_exclusive +
fatal_msg_data_exclusive_.num_prefix_chars_;
#ifdef HAVE_STACKTRACE
// Retrieve the stack trace, omitting the logging frames that got us here.
reason->depth = GetStackTrace(reason->stack, ARRAYSIZE(reason->stack), 4);
#else
reason->depth = 0;
#endif
}
static void logging_fail() {
#if defined(_DEBUG) && defined(_MSC_VER)
// When debugging on windows, avoid the obnoxious dialog and make
// it possible to continue past a LOG(FATAL) in the debugger
_asm int 3
#else
abort();
#endif
}
#ifdef HAVE___ATTRIBUTE__
GOOGLE_GLOG_DLL_DECL
void (*g_logging_fail_func)() __attribute__((noreturn)) = &logging_fail;
#else
GOOGLE_GLOG_DLL_DECL void (*g_logging_fail_func)() = &logging_fail;
#endif
void InstallFailureFunction(void (*fail_func)()) {
g_logging_fail_func = fail_func;
}
void LogMessage::Fail() {
g_logging_fail_func();
}
// L >= log_mutex (callers must hold the log_mutex).
void LogMessage::SendToSink() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
if (data_->sink_ != NULL) {
RAW_DCHECK(data_->num_chars_to_log_ > 0 &&
data_->message_text_[data_->num_chars_to_log_-1] == '\n', "");
data_->sink_->send(data_->severity_, data_->fullname_, data_->basename_,
data_->line_, &data_->tm_time_,
data_->message_text_ + data_->num_prefix_chars_,
(data_->num_chars_to_log_ -
data_->num_prefix_chars_ - 1));
}
}
// L >= log_mutex (callers must hold the log_mutex).
void LogMessage::SendToSinkAndLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
SendToSink();
SendToLog();
}
// L >= log_mutex (callers must hold the log_mutex).
void LogMessage::SaveOrSendToLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
if (data_->outvec_ != NULL) {
RAW_DCHECK(data_->num_chars_to_log_ > 0 &&
data_->message_text_[data_->num_chars_to_log_-1] == '\n', "");
// Omit prefix of message and trailing newline when recording in outvec_.
const char *start = data_->message_text_ + data_->num_prefix_chars_;
int len = data_->num_chars_to_log_ - data_->num_prefix_chars_ - 1;
data_->outvec_->push_back(string(start, len));
} else {
SendToLog();
}
}
void LogMessage::WriteToStringAndLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
if (data_->message_ != NULL) {
RAW_DCHECK(data_->num_chars_to_log_ > 0 &&
data_->message_text_[data_->num_chars_to_log_-1] == '\n', "");
// Omit prefix of message and trailing newline when writing to message_.
const char *start = data_->message_text_ + data_->num_prefix_chars_;
int len = data_->num_chars_to_log_ - data_->num_prefix_chars_ - 1;
data_->message_->assign(start, len);
}
SendToLog();
}
// L >= log_mutex (callers must hold the log_mutex).
void LogMessage::SendToSyslogAndLog() {
#ifdef HAVE_SYSLOG_H
// Before any calls to syslog(), make a single call to openlog()
static bool openlog_already_called = false;
if (!openlog_already_called) {
openlog(glog_internal_namespace_::ProgramInvocationShortName(),
LOG_CONS | LOG_NDELAY | LOG_PID,
LOG_USER);
openlog_already_called = true;
}
// This array maps Google severity levels to syslog levels
const int SEVERITY_TO_LEVEL[] = { LOG_INFO, LOG_WARNING, LOG_ERR, LOG_EMERG };
syslog(LOG_USER | SEVERITY_TO_LEVEL[static_cast<int>(data_->severity_)], "%.*s",
int(data_->num_chars_to_syslog_),
data_->message_text_ + data_->num_prefix_chars_);
SendToLog();
#else
LOG(ERROR) << "No syslog support: message=" << data_->message_text_;
#endif
}
base::Logger* base::GetLogger(LogSeverity severity) {
MutexLock l(&log_mutex);
return LogDestination::log_destination(severity)->logger_;
}
void base::SetLogger(LogSeverity severity, base::Logger* logger) {
MutexLock l(&log_mutex);
LogDestination::log_destination(severity)->logger_ = logger;
}
// L < log_mutex. Acquires and releases mutex_.
int64 LogMessage::num_messages(int severity) {
MutexLock l(&log_mutex);
return num_messages_[severity];
}
// Output the COUNTER value. This is only valid if ostream is a
// LogStream.
ostream& operator<<(ostream &os, const PRIVATE_Counter&) {
LogMessage::LogStream *log = dynamic_cast<LogMessage::LogStream*>(&os);
CHECK(log == log->self());
os << log->ctr();
return os;
}
ErrnoLogMessage::ErrnoLogMessage(const char* file, int line,
LogSeverity severity, int ctr,
void (LogMessage::*send_method)())
: LogMessage(file, line, severity, ctr, send_method) {
}
ErrnoLogMessage::~ErrnoLogMessage() {
// Don't access errno directly because it may have been altered
// while streaming the message.
char buf[100];
posix_strerror_r(preserved_errno(), buf, sizeof(buf));
stream() << ": " << buf << " [" << preserved_errno() << "]";
}
void FlushLogFiles(LogSeverity min_severity) {
LogDestination::FlushLogFiles(min_severity);
}
void FlushLogFilesUnsafe(LogSeverity min_severity) {
LogDestination::FlushLogFilesUnsafe(min_severity);
}
void SetLogDestination(LogSeverity severity, const char* base_filename) {
LogDestination::SetLogDestination(severity, base_filename);
}
void SetLogSymlink(LogSeverity severity, const char* symlink_basename) {
LogDestination::SetLogSymlink(severity, symlink_basename);
}
LogSink::~LogSink() {
}
void LogSink::WaitTillSent() {
// noop default
}
string LogSink::ToString(LogSeverity severity, const char* file, int line,
const struct ::tm* tm_time,
const char* message, size_t message_len) {
ostringstream stream(string(message, message_len));
stream.fill('0');
// FIXME(jrvb): Updating this to use the correct value for usecs
// requires changing the signature for both this method and
// LogSink::send(). This change needs to be done in a separate CL
// so subclasses of LogSink can be updated at the same time.
int usecs = 0;
stream << LogSeverityNames[severity][0]
<< setw(2) << 1+tm_time->tm_mon
<< setw(2) << tm_time->tm_mday
<< ' '
<< setw(2) << tm_time->tm_hour << ':'
<< setw(2) << tm_time->tm_min << ':'
<< setw(2) << tm_time->tm_sec << '.'
<< setw(6) << usecs
<< ' '
<< setfill(' ') << setw(5) << GetTID() << setfill('0')
<< ' '
<< file << ':' << line << "] ";
stream << string(message, message_len);
return stream.str();
}
void AddLogSink(LogSink *destination) {
LogDestination::AddLogSink(destination);
}
void RemoveLogSink(LogSink *destination) {
LogDestination::RemoveLogSink(destination);
}
void SetLogFilenameExtension(const char* ext) {
LogDestination::SetLogFilenameExtension(ext);
}
void SetStderrLogging(LogSeverity min_severity) {
LogDestination::SetStderrLogging(min_severity);
}
void SetEmailLogging(LogSeverity min_severity, const char* addresses) {
LogDestination::SetEmailLogging(min_severity, addresses);
}
void LogToStderr() {
LogDestination::LogToStderr();
}
namespace base {
namespace internal {
bool GetExitOnDFatal() {
MutexLock l(&log_mutex);
return exit_on_dfatal;
}
// Determines whether we exit the program for a LOG(DFATAL) message in
// debug mode. It does this by skipping the call to Fail/FailQuietly.
// This is intended for testing only.
//
// This can have some effects on LOG(FATAL) as well. Failure messages
// are always allocated (rather than sharing a buffer), the crash
// reason is not recorded, the "gwq" status message is not updated,
// and the stack trace is not recorded. The LOG(FATAL) *will* still
// exit the program. Since this function is used only in testing,
// these differences are acceptable.
void SetExitOnDFatal(bool value) {
MutexLock l(&log_mutex);
exit_on_dfatal = value;
}
} // namespace internal
} // namespace base
// use_logging controls whether the logging functions LOG/VLOG are used
// to log errors. It should be set to false when the caller holds the
// log_mutex.
static bool SendEmailInternal(const char*dest, const char *subject,
const char*body, bool use_logging) {
if (dest && *dest) {
if ( use_logging ) {
VLOG(1) << "Trying to send TITLE:" << subject
<< " BODY:" << body << " to " << dest;
} else {
fprintf(stderr, "Trying to send TITLE: %s BODY: %s to %s\n",
subject, body, dest);
}
string cmd =
FLAGS_logmailer + " -s\"" + subject + "\" " + dest;
FILE* pipe = popen(cmd.c_str(), "w");
if (pipe != NULL) {
// Add the body if we have one
if (body)
fwrite(body, sizeof(char), strlen(body), pipe);
bool ok = pclose(pipe) != -1;
if ( !ok ) {
if ( use_logging ) {
char buf[100];
posix_strerror_r(errno, buf, sizeof(buf));
LOG(ERROR) << "Problems sending mail to " << dest << ": " << buf;
} else {
char buf[100];
posix_strerror_r(errno, buf, sizeof(buf));
fprintf(stderr, "Problems sending mail to %s: %s\n", dest, buf);
}
}
return ok;
} else {
if ( use_logging ) {
LOG(ERROR) << "Unable to send mail to " << dest;
} else {
fprintf(stderr, "Unable to send mail to %s\n", dest);
}
}
}
return false;
}
bool SendEmail(const char*dest, const char *subject, const char*body){
return SendEmailInternal(dest, subject, body, true);
}
static void GetTempDirectories(vector<string>* list) {
list->clear();
#ifdef OS_WINDOWS
// On windows we'll try to find a directory in this order:
// C:/Documents & Settings/whomever/TEMP (or whatever GetTempPath() is)
// C:/TMP/
// C:/TEMP/
// C:/WINDOWS/ or C:/WINNT/
// .
char tmp[MAX_PATH];
if (GetTempPathA(MAX_PATH, tmp))
list->push_back(tmp);
list->push_back("C:\\tmp\\");
list->push_back("C:\\temp\\");
#else
// Directories, in order of preference. If we find a dir that
// exists, we stop adding other less-preferred dirs
const char * candidates[] = {
// Non-null only during unittest/regtest
getenv("TEST_TMPDIR"),
// Explicitly-supplied temp dirs
getenv("TMPDIR"), getenv("TMP"),
// If all else fails
"/tmp",
};
for (int i = 0; i < ARRAYSIZE(candidates); i++) {
const char *d = candidates[i];
if (!d) continue; // Empty env var
// Make sure we don't surprise anyone who's expecting a '/'
string dstr = d;
if (dstr[dstr.size() - 1] != '/') {
dstr += "/";
}
list->push_back(dstr);
struct stat statbuf;
if (!stat(d, &statbuf) && S_ISDIR(statbuf.st_mode)) {
// We found a dir that exists - we're done.
return;
}
}
#endif
}
static vector<string>* logging_directories_list;
const vector<string>& GetLoggingDirectories() {
// Not strictly thread-safe but we're called early in InitGoogle().
if (logging_directories_list == NULL) {
logging_directories_list = new vector<string>;
if ( !FLAGS_log_dir.empty() ) {
// A dir was specified, we should use it
logging_directories_list->push_back(FLAGS_log_dir.c_str());
} else {
GetTempDirectories(logging_directories_list);
#ifdef OS_WINDOWS
char tmp[MAX_PATH];
if (GetWindowsDirectoryA(tmp, MAX_PATH))
logging_directories_list->push_back(tmp);
logging_directories_list->push_back(".\\");
#else
logging_directories_list->push_back("./");
#endif
}
}
return *logging_directories_list;
}
void TestOnly_ClearLoggingDirectoriesList() {
fprintf(stderr, "TestOnly_ClearLoggingDirectoriesList should only be "
"called from test code.\n");
delete logging_directories_list;
logging_directories_list = NULL;
}
void GetExistingTempDirectories(vector<string>* list) {
GetTempDirectories(list);
vector<string>::iterator i_dir = list->begin();
while( i_dir != list->end() ) {
// zero arg to access means test for existence; no constant
// defined on windows
if ( access(i_dir->c_str(), 0) ) {
i_dir = list->erase(i_dir);
} else {
++i_dir;
}
}
}
void TruncateLogFile(const char *path, int64 limit, int64 keep) {
#ifdef HAVE_UNISTD_H
struct stat statbuf;
const int kCopyBlockSize = 8 << 10;
char copybuf[kCopyBlockSize];
int64 read_offset, write_offset;
// Don't follow symlinks unless they're our own fd symlinks in /proc
int flags = O_RDWR;
const char *procfd_prefix = "/proc/self/fd/";
if (strncmp(procfd_prefix, path, strlen(procfd_prefix))) flags |= O_NOFOLLOW;
int fd = open(path, flags);
if (fd == -1) {
if (errno == EFBIG) {
// The log file in question has got too big for us to open. The
// real fix for this would be to compile logging.cc (or probably
// all of base/...) with -D_FILE_OFFSET_BITS=64 but that's
// rather scary.
// Instead just truncate the file to something we can manage
if (truncate(path, 0) == -1) {
PLOG(ERROR) << "Unable to truncate " << path;
} else {
LOG(ERROR) << "Truncated " << path << " due to EFBIG error";
}
} else {
PLOG(ERROR) << "Unable to open " << path;
}
return;
}
if (fstat(fd, &statbuf) == -1) {
PLOG(ERROR) << "Unable to fstat()";
goto out_close_fd;
}
// See if the path refers to a regular file bigger than the
// specified limit
if (!S_ISREG(statbuf.st_mode)) goto out_close_fd;
if (statbuf.st_size <= limit) goto out_close_fd;
if (statbuf.st_size <= keep) goto out_close_fd;
// This log file is too large - we need to truncate it
LOG(INFO) << "Truncating " << path << " to " << keep << " bytes";
// Copy the last "keep" bytes of the file to the beginning of the file
read_offset = statbuf.st_size - keep;
write_offset = 0;
int bytesin, bytesout;
while ((bytesin = pread(fd, copybuf, sizeof(copybuf), read_offset)) > 0) {
bytesout = pwrite(fd, copybuf, bytesin, write_offset);
if (bytesout == -1) {
PLOG(ERROR) << "Unable to write to " << path;
break;
} else if (bytesout != bytesin) {
LOG(ERROR) << "Expected to write " << bytesin << ", wrote " << bytesout;
}
read_offset += bytesin;
write_offset += bytesout;
}
if (bytesin == -1) PLOG(ERROR) << "Unable to read from " << path;
// Truncate the remainder of the file. If someone else writes to the
// end of the file after our last read() above, we lose their latest
// data. Too bad ...
if (ftruncate(fd, write_offset) == -1) {
PLOG(ERROR) << "Unable to truncate " << path;
}
out_close_fd:
close(fd);
#else
LOG(ERROR) << "No log truncation support.";
#endif
}
void TruncateStdoutStderr() {
#ifdef HAVE_UNISTD_H
int64 limit = MaxLogSize() << 20;
int64 keep = 1 << 20;
TruncateLogFile("/proc/self/fd/1", limit, keep);
TruncateLogFile("/proc/self/fd/2", limit, keep);
#else
LOG(ERROR) << "No log truncation support.";
#endif
}
// Helper functions for string comparisons.
#define DEFINE_CHECK_STROP_IMPL(name, func, expected) \
string* Check##func##expected##Impl(const char* s1, const char* s2, \
const char* names) { \
bool equal = s1 == s2 || (s1 && s2 && !func(s1, s2)); \
if (equal == expected) return NULL; \
else { \
strstream ss; \
if (!s1) s1 = ""; \
if (!s2) s2 = ""; \
ss << #name " failed: " << names << " (" << s1 << " vs. " << s2 << ")"; \
return new string(ss.str(), ss.pcount()); \
} \
}
DEFINE_CHECK_STROP_IMPL(CHECK_STREQ, strcmp, true)
DEFINE_CHECK_STROP_IMPL(CHECK_STRNE, strcmp, false)
DEFINE_CHECK_STROP_IMPL(CHECK_STRCASEEQ, strcasecmp, true)
DEFINE_CHECK_STROP_IMPL(CHECK_STRCASENE, strcasecmp, false)
#undef DEFINE_CHECK_STROP_IMPL
int posix_strerror_r(int err, char *buf, size_t len) {
// Sanity check input parameters
if (buf == NULL || len <= 0) {
errno = EINVAL;
return -1;
}
// Reset buf and errno, and try calling whatever version of strerror_r()
// is implemented by glibc
buf[0] = '\000';
int old_errno = errno;
errno = 0;
char *rc = reinterpret_cast<char *>(strerror_r(err, buf, len));
// Both versions set errno on failure
if (errno) {
// Should already be there, but better safe than sorry
buf[0] = '\000';
return -1;
}
errno = old_errno;
// POSIX is vague about whether the string will be terminated, although
// is indirectly implies that typically ERANGE will be returned, instead
// of truncating the string. This is different from the GNU implementation.
// We play it safe by always terminating the string explicitly.
buf[len-1] = '\000';
// If the function succeeded, we can use its exit code to determine the
// semantics implemented by glibc
if (!rc) {
return 0;
} else {
// GNU semantics detected
if (rc == buf) {
return 0;
} else {
buf[0] = '\000';
#if defined(OS_MACOSX) || defined(OS_FREEBSD) || defined(OS_OPENBSD)
if (reinterpret_cast<intptr_t>(rc) < sys_nerr) {
// This means an error on MacOSX or FreeBSD.
return -1;
}
#endif
strncat(buf, rc, len-1);
return 0;
}
}
}
LogMessageFatal::LogMessageFatal(const char* file, int line) :
LogMessage(file, line, FATAL) {}
LogMessageFatal::LogMessageFatal(const char* file, int line,
const CheckOpString& result) :
LogMessage(file, line, result) {}
LogMessageFatal::~LogMessageFatal() {
Flush();
LogMessage::Fail();
}
_END_GOOGLE_NAMESPACE_
// This file is automatically generated from src/glog/logging.h.in
// using src/windows/preprocess.sh.
// DO NOT EDIT!
// Copyright (c) 1999, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Ray Sidney
//
// This file contains #include information about logging-related stuff.
// Pretty much everybody needs to #include this file so that they can
// log various happenings.
//
#ifndef _LOGGING_H_
#define _LOGGING_H_
#include <errno.h>
#include <string.h>
#include <time.h>
#include <iosfwd>
#include <ostream>
#include <sstream>
#include <string>
#if 0
# include <unistd.h>
#endif
#include <vector>
// Annoying stuff for windows -- makes sure clients can import these functions
#ifndef GOOGLE_GLOG_DLL_DECL
# if defined(_WIN32) && !defined(__CYGWIN__)
# define GOOGLE_GLOG_DLL_DECL __declspec(dllimport)
# else
# define GOOGLE_GLOG_DLL_DECL
# endif
#endif
#if defined(_MSC_VER)
#define GLOG_MSVC_PUSH_DISABLE_WARNING(n) __pragma(warning(push)) \
__pragma(warning(disable:n))
#define GLOG_MSVC_POP_WARNING() __pragma(warning(pop))
#else
#define GLOG_MSVC_PUSH_DISABLE_WARNING(n)
#define GLOG_MSVC_POP_WARNING()
#endif
// We care a lot about number of bits things take up. Unfortunately,
// systems define their bit-specific ints in a lot of different ways.
// We use our own way, and have a typedef to get there.
// Note: these commands below may look like "#if 1" or "#if 0", but
// that's because they were constructed that way at ./configure time.
// Look at logging.h.in to see how they're calculated (based on your config).
#if 0
#include <stdint.h> // the normal place uint16_t is defined
#endif
#if 0
#include <sys/types.h> // the normal place u_int16_t is defined
#endif
#if 0
#include <inttypes.h> // a third place for uint16_t or u_int16_t
#endif
#if 0
#include <gflags/gflags.h>
#endif
namespace google {
#if 0 // the C99 format
typedef int32_t int32;
typedef uint32_t uint32;
typedef int64_t int64;
typedef uint64_t uint64;
#elif 0 // the BSD format
typedef int32_t int32;
typedef u_int32_t uint32;
typedef int64_t int64;
typedef u_int64_t uint64;
#elif 1 // the windows (vc7) format
typedef __int32 int32;
typedef unsigned __int32 uint32;
typedef __int64 int64;
typedef unsigned __int64 uint64;
#else
#error Do not know how to define a 32-bit integer quantity on your system
#endif
}
// The global value of GOOGLE_STRIP_LOG. All the messages logged to
// LOG(XXX) with severity less than GOOGLE_STRIP_LOG will not be displayed.
// If it can be determined at compile time that the message will not be
// printed, the statement will be compiled out.
//
// Example: to strip out all INFO and WARNING messages, use the value
// of 2 below. To make an exception for WARNING messages from a single
// file, add "#define GOOGLE_STRIP_LOG 1" to that file _before_ including
// base/logging.h
#ifndef GOOGLE_STRIP_LOG
#define GOOGLE_STRIP_LOG 0
#endif
// GCC can be told that a certain branch is not likely to be taken (for
// instance, a CHECK failure), and use that information in static analysis.
// Giving it this information can help it optimize for the common case in
// the absence of better information (ie. -fprofile-arcs).
//
#ifndef GOOGLE_PREDICT_BRANCH_NOT_TAKEN
#if 0
#define GOOGLE_PREDICT_BRANCH_NOT_TAKEN(x) (__builtin_expect(x, 0))
#define GOOGLE_PREDICT_FALSE(x) (__builtin_expect(x, 0))
#define GOOGLE_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
#else
#define GOOGLE_PREDICT_BRANCH_NOT_TAKEN(x) x
#define GOOGLE_PREDICT_FALSE(x) x
#define GOOGLE_PREDICT_TRUE(x) x
#endif
#endif
// Make a bunch of macros for logging. The way to log things is to stream
// things to LOG(<a particular severity level>). E.g.,
//
// LOG(INFO) << "Found " << num_cookies << " cookies";
//
// You can capture log messages in a string, rather than reporting them
// immediately:
//
// vector<string> errors;
// LOG_STRING(ERROR, &errors) << "Couldn't parse cookie #" << cookie_num;
//
// This pushes back the new error onto 'errors'; if given a NULL pointer,
// it reports the error via LOG(ERROR).
//
// You can also do conditional logging:
//
// LOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
//
// You can also do occasional logging (log every n'th occurrence of an
// event):
//
// LOG_EVERY_N(INFO, 10) << "Got the " << google::COUNTER << "th cookie";
//
// The above will cause log messages to be output on the 1st, 11th, 21st, ...
// times it is executed. Note that the special google::COUNTER value is used
// to identify which repetition is happening.
//
// You can also do occasional conditional logging (log every n'th
// occurrence of an event, when condition is satisfied):
//
// LOG_IF_EVERY_N(INFO, (size > 1024), 10) << "Got the " << google::COUNTER
// << "th big cookie";
//
// You can log messages the first N times your code executes a line. E.g.
//
// LOG_FIRST_N(INFO, 20) << "Got the " << google::COUNTER << "th cookie";
//
// Outputs log messages for the first 20 times it is executed.
//
// Analogous SYSLOG, SYSLOG_IF, and SYSLOG_EVERY_N macros are available.
// These log to syslog as well as to the normal logs. If you use these at
// all, you need to be aware that syslog can drastically reduce performance,
// especially if it is configured for remote logging! Don't use these
// unless you fully understand this and have a concrete need to use them.
// Even then, try to minimize your use of them.
//
// There are also "debug mode" logging macros like the ones above:
//
// DLOG(INFO) << "Found cookies";
//
// DLOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
//
// DLOG_EVERY_N(INFO, 10) << "Got the " << google::COUNTER << "th cookie";
//
// All "debug mode" logging is compiled away to nothing for non-debug mode
// compiles.
//
// We also have
//
// LOG_ASSERT(assertion);
// DLOG_ASSERT(assertion);
//
// which is syntactic sugar for {,D}LOG_IF(FATAL, assert fails) << assertion;
//
// There are "verbose level" logging macros. They look like
//
// VLOG(1) << "I'm printed when you run the program with --v=1 or more";
// VLOG(2) << "I'm printed when you run the program with --v=2 or more";
//
// These always log at the INFO log level (when they log at all).
// The verbose logging can also be turned on module-by-module. For instance,
// --vmodule=mapreduce=2,file=1,gfs*=3 --v=0
// will cause:
// a. VLOG(2) and lower messages to be printed from mapreduce.{h,cc}
// b. VLOG(1) and lower messages to be printed from file.{h,cc}
// c. VLOG(3) and lower messages to be printed from files prefixed with "gfs"
// d. VLOG(0) and lower messages to be printed from elsewhere
//
// The wildcarding functionality shown by (c) supports both '*' (match
// 0 or more characters) and '?' (match any single character) wildcards.
//
// There's also VLOG_IS_ON(n) "verbose level" condition macro. To be used as
//
// if (VLOG_IS_ON(2)) {
// // do some logging preparation and logging
// // that can't be accomplished with just VLOG(2) << ...;
// }
//
// There are also VLOG_IF, VLOG_EVERY_N and VLOG_IF_EVERY_N "verbose level"
// condition macros for sample cases, when some extra computation and
// preparation for logs is not needed.
// VLOG_IF(1, (size > 1024))
// << "I'm printed when size is more than 1024 and when you run the "
// "program with --v=1 or more";
// VLOG_EVERY_N(1, 10)
// << "I'm printed every 10th occurrence, and when you run the program "
// "with --v=1 or more. Present occurence is " << google::COUNTER;
// VLOG_IF_EVERY_N(1, (size > 1024), 10)
// << "I'm printed on every 10th occurence of case when size is more "
// " than 1024, when you run the program with --v=1 or more. ";
// "Present occurence is " << google::COUNTER;
//
// The supported severity levels for macros that allow you to specify one
// are (in increasing order of severity) INFO, WARNING, ERROR, and FATAL.
// Note that messages of a given severity are logged not only in the
// logfile for that severity, but also in all logfiles of lower severity.
// E.g., a message of severity FATAL will be logged to the logfiles of
// severity FATAL, ERROR, WARNING, and INFO.
//
// There is also the special severity of DFATAL, which logs FATAL in
// debug mode, ERROR in normal mode.
//
// Very important: logging a message at the FATAL severity level causes
// the program to terminate (after the message is logged).
//
// Unless otherwise specified, logs will be written to the filename
// "<program name>.<hostname>.<user name>.log.<severity level>.", followed
// by the date, time, and pid (you can't prevent the date, time, and pid
// from being in the filename).
//
// The logging code takes two flags:
// --v=# set the verbose level
// --logtostderr log all the messages to stderr instead of to logfiles
// LOG LINE PREFIX FORMAT
//
// Log lines have this form:
//
// Lmmdd hh:mm:ss.uuuuuu threadid file:line] msg...
//
// where the fields are defined as follows:
//
// L A single character, representing the log level
// (eg 'I' for INFO)
// mm The month (zero padded; ie May is '05')
// dd The day (zero padded)
// hh:mm:ss.uuuuuu Time in hours, minutes and fractional seconds
// threadid The space-padded thread ID as returned by GetTID()
// (this matches the PID on Linux)
// file The file name
// line The line number
// msg The user-supplied message
//
// Example:
//
// I1103 11:57:31.739339 24395 google.cc:2341] Command line: ./some_prog
// I1103 11:57:31.739403 24395 google.cc:2342] Process id 24395
//
// NOTE: although the microseconds are useful for comparing events on
// a single machine, clocks on different machines may not be well
// synchronized. Hence, use caution when comparing the low bits of
// timestamps from different machines.
#ifndef DECLARE_VARIABLE
#define MUST_UNDEF_GFLAGS_DECLARE_MACROS
#define DECLARE_VARIABLE(type, shorttype, name, tn) \
namespace fL##shorttype { \
extern GOOGLE_GLOG_DLL_DECL type FLAGS_##name; \
} \
using fL##shorttype::FLAGS_##name
// bool specialization
#define DECLARE_bool(name) \
DECLARE_VARIABLE(bool, B, name, bool)
// int32 specialization
#define DECLARE_int32(name) \
DECLARE_VARIABLE(google::int32, I, name, int32)
// Special case for string, because we have to specify the namespace
// std::string, which doesn't play nicely with our FLAG__namespace hackery.
#define DECLARE_string(name) \
namespace fLS { \
extern GOOGLE_GLOG_DLL_DECL std::string& FLAGS_##name; \
} \
using fLS::FLAGS_##name
#endif
// Set whether log messages go to stderr instead of logfiles
DECLARE_bool(logtostderr);
// Set whether log messages go to stderr in addition to logfiles.
DECLARE_bool(alsologtostderr);
// Set color messages logged to stderr (if supported by terminal).
DECLARE_bool(colorlogtostderr);
// Log messages at a level >= this flag are automatically sent to
// stderr in addition to log files.
DECLARE_int32(stderrthreshold);
// Set whether the log prefix should be prepended to each line of output.
DECLARE_bool(log_prefix);
// Log messages at a level <= this flag are buffered.
// Log messages at a higher level are flushed immediately.
DECLARE_int32(logbuflevel);
// Sets the maximum number of seconds which logs may be buffered for.
DECLARE_int32(logbufsecs);
// Log suppression level: messages logged at a lower level than this
// are suppressed.
DECLARE_int32(minloglevel);
// If specified, logfiles are written into this directory instead of the
// default logging directory.
DECLARE_string(log_dir);
// Sets the path of the directory into which to put additional links
// to the log files.
DECLARE_string(log_link);
DECLARE_int32(v); // in vlog_is_on.cc
// Sets the maximum log file size (in MB).
DECLARE_int32(max_log_size);
// Sets whether to avoid logging to the disk if the disk is full.
DECLARE_bool(stop_logging_if_full_disk);
#ifdef MUST_UNDEF_GFLAGS_DECLARE_MACROS
#undef MUST_UNDEF_GFLAGS_DECLARE_MACROS
#undef DECLARE_VARIABLE
#undef DECLARE_bool
#undef DECLARE_int32
#undef DECLARE_string
#endif
// Log messages below the GOOGLE_STRIP_LOG level will be compiled away for
// security reasons. See LOG(severtiy) below.
// A few definitions of macros that don't generate much code. Since
// LOG(INFO) and its ilk are used all over our code, it's
// better to have compact code for these operations.
#if GOOGLE_STRIP_LOG == 0
#define COMPACT_GOOGLE_LOG_INFO google::LogMessage( \
__FILE__, __LINE__)
#define LOG_TO_STRING_INFO(message) google::LogMessage( \
__FILE__, __LINE__, google::GLOG_INFO, message)
#else
#define COMPACT_GOOGLE_LOG_INFO google::NullStream()
#define LOG_TO_STRING_INFO(message) google::NullStream()
#endif
#if GOOGLE_STRIP_LOG <= 1
#define COMPACT_GOOGLE_LOG_WARNING google::LogMessage( \
__FILE__, __LINE__, google::GLOG_WARNING)
#define LOG_TO_STRING_WARNING(message) google::LogMessage( \
__FILE__, __LINE__, google::GLOG_WARNING, message)
#else
#define COMPACT_GOOGLE_LOG_WARNING google::NullStream()
#define LOG_TO_STRING_WARNING(message) google::NullStream()
#endif
#if GOOGLE_STRIP_LOG <= 2
#define COMPACT_GOOGLE_LOG_ERROR google::LogMessage( \
__FILE__, __LINE__, google::GLOG_ERROR)
#define LOG_TO_STRING_ERROR(message) google::LogMessage( \
__FILE__, __LINE__, google::GLOG_ERROR, message)
#else
#define COMPACT_GOOGLE_LOG_ERROR google::NullStream()
#define LOG_TO_STRING_ERROR(message) google::NullStream()
#endif
#if GOOGLE_STRIP_LOG <= 3
#define COMPACT_GOOGLE_LOG_FATAL google::LogMessageFatal( \
__FILE__, __LINE__)
#define LOG_TO_STRING_FATAL(message) google::LogMessage( \
__FILE__, __LINE__, google::GLOG_FATAL, message)
#else
#define COMPACT_GOOGLE_LOG_FATAL google::NullStreamFatal()
#define LOG_TO_STRING_FATAL(message) google::NullStreamFatal()
#endif
// For DFATAL, we want to use LogMessage (as opposed to
// LogMessageFatal), to be consistent with the original behavior.
#ifdef NDEBUG
#define COMPACT_GOOGLE_LOG_DFATAL COMPACT_GOOGLE_LOG_ERROR
#elif GOOGLE_STRIP_LOG <= 3
#define COMPACT_GOOGLE_LOG_DFATAL google::LogMessage( \
__FILE__, __LINE__, google::GLOG_FATAL)
#else
#define COMPACT_GOOGLE_LOG_DFATAL google::NullStreamFatal()
#endif
#define GOOGLE_LOG_INFO(counter) google::LogMessage(__FILE__, __LINE__, google::GLOG_INFO, counter, &google::LogMessage::SendToLog)
#define SYSLOG_INFO(counter) \
google::LogMessage(__FILE__, __LINE__, google::GLOG_INFO, counter, \
&google::LogMessage::SendToSyslogAndLog)
#define GOOGLE_LOG_WARNING(counter) \
google::LogMessage(__FILE__, __LINE__, google::GLOG_WARNING, counter, \
&google::LogMessage::SendToLog)
#define SYSLOG_WARNING(counter) \
google::LogMessage(__FILE__, __LINE__, google::GLOG_WARNING, counter, \
&google::LogMessage::SendToSyslogAndLog)
#define GOOGLE_LOG_ERROR(counter) \
google::LogMessage(__FILE__, __LINE__, google::GLOG_ERROR, counter, \
&google::LogMessage::SendToLog)
#define SYSLOG_ERROR(counter) \
google::LogMessage(__FILE__, __LINE__, google::GLOG_ERROR, counter, \
&google::LogMessage::SendToSyslogAndLog)
#define GOOGLE_LOG_FATAL(counter) \
google::LogMessage(__FILE__, __LINE__, google::GLOG_FATAL, counter, \
&google::LogMessage::SendToLog)
#define SYSLOG_FATAL(counter) \
google::LogMessage(__FILE__, __LINE__, google::GLOG_FATAL, counter, \
&google::LogMessage::SendToSyslogAndLog)
#define GOOGLE_LOG_DFATAL(counter) \
google::LogMessage(__FILE__, __LINE__, google::DFATAL_LEVEL, counter, \
&google::LogMessage::SendToLog)
#define SYSLOG_DFATAL(counter) \
google::LogMessage(__FILE__, __LINE__, google::DFATAL_LEVEL, counter, \
&google::LogMessage::SendToSyslogAndLog)
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) || defined(__CYGWIN32__)
// A very useful logging macro to log windows errors:
#define LOG_SYSRESULT(result) \
if (FAILED(HRESULT_FROM_WIN32(result))) { \
LPSTR message = NULL; \
LPSTR msg = reinterpret_cast<LPSTR>(&message); \
DWORD message_length = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | \
FORMAT_MESSAGE_FROM_SYSTEM, \
0, result, 0, msg, 100, NULL); \
if (message_length > 0) { \
google::LogMessage(__FILE__, __LINE__, google::GLOG_ERROR, 0, \
&google::LogMessage::SendToLog).stream() \
<< reinterpret_cast<const char*>(message); \
LocalFree(message); \
} \
}
#endif
// We use the preprocessor's merging operator, "##", so that, e.g.,
// LOG(INFO) becomes the token GOOGLE_LOG_INFO. There's some funny
// subtle difference between ostream member streaming functions (e.g.,
// ostream::operator<<(int) and ostream non-member streaming functions
// (e.g., ::operator<<(ostream&, string&): it turns out that it's
// impossible to stream something like a string directly to an unnamed
// ostream. We employ a neat hack by calling the stream() member
// function of LogMessage which seems to avoid the problem.
#define LOG(severity) COMPACT_GOOGLE_LOG_ ## severity.stream()
#define SYSLOG(severity) SYSLOG_ ## severity(0).stream()
namespace google {
// They need the definitions of integer types.
#include "glog/log_severity.h"
#include "glog/vlog_is_on.h"
// Initialize google's logging library. You will see the program name
// specified by argv0 in log outputs.
GOOGLE_GLOG_DLL_DECL void InitGoogleLogging(const char* argv0);
// Shutdown google's logging library.
GOOGLE_GLOG_DLL_DECL void ShutdownGoogleLogging();
// Install a function which will be called after LOG(FATAL).
GOOGLE_GLOG_DLL_DECL void InstallFailureFunction(void(*fail_func)());
class LogSink; // defined below
// If a non-NULL sink pointer is given, we push this message to that sink.
// For LOG_TO_SINK we then do normal LOG(severity) logging as well.
// This is useful for capturing messages and passing/storing them
// somewhere more specific than the global log of the process.
// Argument types:
// LogSink* sink;
// LogSeverity severity;
// The cast is to disambiguate NULL arguments.
#define LOG_TO_SINK(sink, severity) \
google::LogMessage( \
__FILE__, __LINE__, \
google::GLOG_ ## severity, \
static_cast<google::LogSink*>(sink), true).stream()
#define LOG_TO_SINK_BUT_NOT_TO_LOGFILE(sink, severity) \
google::LogMessage( \
__FILE__, __LINE__, \
google::GLOG_ ## severity, \
static_cast<google::LogSink*>(sink), false).stream()
// If a non-NULL string pointer is given, we write this message to that string.
// We then do normal LOG(severity) logging as well.
// This is useful for capturing messages and storing them somewhere more
// specific than the global log of the process.
// Argument types:
// string* message;
// LogSeverity severity;
// The cast is to disambiguate NULL arguments.
// NOTE: LOG(severity) expands to LogMessage().stream() for the specified
// severity.
#define LOG_TO_STRING(severity, message) \
LOG_TO_STRING_##severity(static_cast<string*>(message)).stream()
// If a non-NULL pointer is given, we push the message onto the end
// of a vector of strings; otherwise, we report it with LOG(severity).
// This is handy for capturing messages and perhaps passing them back
// to the caller, rather than reporting them immediately.
// Argument types:
// LogSeverity severity;
// vector<string> *outvec;
// The cast is to disambiguate NULL arguments.
#define LOG_STRING(severity, outvec) \
LOG_TO_STRING_##severity(static_cast<vector<string>*>(outvec)).stream()
#define LOG_IF(severity, condition) \
!(condition) ? (void) 0 : google::LogMessageVoidify() & LOG(severity)
#define SYSLOG_IF(severity, condition) \
!(condition) ? (void) 0 : google::LogMessageVoidify() & SYSLOG(severity)
#define LOG_ASSERT(condition) \
LOG_IF(FATAL, !(condition)) << "Assert failed: " #condition
#define SYSLOG_ASSERT(condition) \
SYSLOG_IF(FATAL, !(condition)) << "Assert failed: " #condition
// CHECK dies with a fatal error if condition is not true. It is *not*
// controlled by NDEBUG, so the check will be executed regardless of
// compilation mode. Therefore, it is safe to do things like:
// CHECK(fp->Write(x) == 4)
#define CHECK(condition) \
LOG_IF(FATAL, GOOGLE_PREDICT_BRANCH_NOT_TAKEN(!(condition))) \
<< "Check failed: " #condition " "
// A container for a string pointer which can be evaluated to a bool -
// true iff the pointer is NULL.
struct CheckOpString {
CheckOpString(std::string* str) : str_(str) { }
// No destructor: if str_ is non-NULL, we're about to LOG(FATAL),
// so there's no point in cleaning up str_.
operator bool() const {
return GOOGLE_PREDICT_BRANCH_NOT_TAKEN(str_ != NULL);
}
std::string* str_;
};
// Function is overloaded for integral types to allow static const
// integrals declared in classes and not defined to be used as arguments to
// CHECK* macros. It's not encouraged though.
template <class T>
inline const T& GetReferenceableValue(const T& t) { return t; }
inline char GetReferenceableValue(char t) { return t; }
inline unsigned char GetReferenceableValue(unsigned char t) { return t; }
inline signed char GetReferenceableValue(signed char t) { return t; }
inline short GetReferenceableValue(short t) { return t; }
inline unsigned short GetReferenceableValue(unsigned short t) { return t; }
inline int GetReferenceableValue(int t) { return t; }
inline unsigned int GetReferenceableValue(unsigned int t) { return t; }
inline long GetReferenceableValue(long t) { return t; }
inline unsigned long GetReferenceableValue(unsigned long t) { return t; }
inline long long GetReferenceableValue(long long t) { return t; }
inline unsigned long long GetReferenceableValue(unsigned long long t) {
return t;
}
// This is a dummy class to define the following operator.
struct DummyClassToDefineOperator {};
}
// Define global operator<< to declare using ::operator<<.
// This declaration will allow use to use CHECK macros for user
// defined classes which have operator<< (e.g., stl_logging.h).
inline std::ostream& operator<<(
std::ostream& out, const google::DummyClassToDefineOperator&) {
return out;
}
namespace google {
// This formats a value for a failing CHECK_XX statement. Ordinarily,
// it uses the definition for operator<<, with a few special cases below.
template <typename T>
inline void MakeCheckOpValueString(std::ostream* os, const T& v) {
(*os) << v;
}
// Overrides for char types provide readable values for unprintable
// characters.
template <> GOOGLE_GLOG_DLL_DECL
void MakeCheckOpValueString(std::ostream* os, const char& v);
template <> GOOGLE_GLOG_DLL_DECL
void MakeCheckOpValueString(std::ostream* os, const signed char& v);
template <> GOOGLE_GLOG_DLL_DECL
void MakeCheckOpValueString(std::ostream* os, const unsigned char& v);
// Build the error message string. Specify no inlining for code size.
template <typename T1, typename T2>
std::string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext)
;
namespace base {
namespace internal {
// If "s" is less than base_logging::INFO, returns base_logging::INFO.
// If "s" is greater than base_logging::FATAL, returns
// base_logging::ERROR. Otherwise, returns "s".
LogSeverity NormalizeSeverity(LogSeverity s);
} // namespace internal
// A helper class for formatting "expr (V1 vs. V2)" in a CHECK_XX
// statement. See MakeCheckOpString for sample usage. Other
// approaches were considered: use of a template method (e.g.,
// base::BuildCheckOpString(exprtext, base::Print<T1>, &v1,
// base::Print<T2>, &v2), however this approach has complications
// related to volatile arguments and function-pointer arguments).
class GOOGLE_GLOG_DLL_DECL CheckOpMessageBuilder {
public:
// Inserts "exprtext" and " (" to the stream.
explicit CheckOpMessageBuilder(const char *exprtext);
// Deletes "stream_".
~CheckOpMessageBuilder();
// For inserting the first variable.
std::ostream* ForVar1() { return stream_; }
// For inserting the second variable (adds an intermediate " vs. ").
std::ostream* ForVar2();
// Get the result (inserts the closing ")").
std::string* NewString();
private:
std::ostringstream *stream_;
};
} // namespace base
template <typename T1, typename T2>
std::string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext) {
base::CheckOpMessageBuilder comb(exprtext);
MakeCheckOpValueString(comb.ForVar1(), v1);
MakeCheckOpValueString(comb.ForVar2(), v2);
return comb.NewString();
}
// Helper functions for CHECK_OP macro.
// The (int, int) specialization works around the issue that the compiler
// will not instantiate the template version of the function on values of
// unnamed enum type - see comment below.
#define DEFINE_CHECK_OP_IMPL(name, op) \
template <typename T1, typename T2> \
inline std::string* name##Impl(const T1& v1, const T2& v2, \
const char* exprtext) { \
if (GOOGLE_PREDICT_TRUE(v1 op v2)) return NULL; \
else return MakeCheckOpString(v1, v2, exprtext); \
} \
inline std::string* name##Impl(int v1, int v2, const char* exprtext) { \
return name##Impl<int, int>(v1, v2, exprtext); \
}
// We use the full name Check_EQ, Check_NE, etc. in case the file including
// base/logging.h provides its own #defines for the simpler names EQ, NE, etc.
// This happens if, for example, those are used as token names in a
// yacc grammar.
DEFINE_CHECK_OP_IMPL(Check_EQ, == ) // Compilation error with CHECK_EQ(NULL, x)?
DEFINE_CHECK_OP_IMPL(Check_NE, != ) // Use CHECK(x == NULL) instead.
DEFINE_CHECK_OP_IMPL(Check_LE, <= )
DEFINE_CHECK_OP_IMPL(Check_LT, <)
DEFINE_CHECK_OP_IMPL(Check_GE, >= )
DEFINE_CHECK_OP_IMPL(Check_GT, >)
#undef DEFINE_CHECK_OP_IMPL
// Helper macro for binary operators.
// Don't use this macro directly in your code, use CHECK_EQ et al below.
#if defined(STATIC_ANALYSIS)
// Only for static analysis tool to know that it is equivalent to assert
#define CHECK_OP_LOG(name, op, val1, val2, log) CHECK((val1) op (val2))
#elif !defined(NDEBUG)
// In debug mode, avoid constructing CheckOpStrings if possible,
// to reduce the overhead of CHECK statments by 2x.
// Real DCHECK-heavy tests have seen 1.5x speedups.
// The meaning of "string" might be different between now and
// when this macro gets invoked (e.g., if someone is experimenting
// with other string implementations that get defined after this
// file is included). Save the current meaning now and use it
// in the macro.
typedef std::string _Check_string;
#define CHECK_OP_LOG(name, op, val1, val2, log) \
while (google::_Check_string* _result = \
google::Check##name##Impl( \
google::GetReferenceableValue(val1), \
google::GetReferenceableValue(val2), \
#val1 " " #op " " #val2)) \
log(__FILE__, __LINE__, \
google::CheckOpString(_result)).stream()
#else
// In optimized mode, use CheckOpString to hint to compiler that
// the while condition is unlikely.
#define CHECK_OP_LOG(name, op, val1, val2, log) \
while (google::CheckOpString _result = \
google::Check##name##Impl( \
google::GetReferenceableValue(val1), \
google::GetReferenceableValue(val2), \
#val1 " " #op " " #val2)) \
log(__FILE__, __LINE__, _result).stream()
#endif // STATIC_ANALYSIS, !NDEBUG
#if GOOGLE_STRIP_LOG <= 3
#define CHECK_OP(name, op, val1, val2) \
CHECK_OP_LOG(name, op, val1, val2, google::LogMessageFatal)
#else
#define CHECK_OP(name, op, val1, val2) \
CHECK_OP_LOG(name, op, val1, val2, google::NullStreamFatal)
#endif // STRIP_LOG <= 3
// Equality/Inequality checks - compare two values, and log a FATAL message
// including the two values when the result is not as expected. The values
// must have operator<<(ostream, ...) defined.
//
// You may append to the error message like so:
// CHECK_NE(1, 2) << ": The world must be ending!";
//
// We are very careful to ensure that each argument is evaluated exactly
// once, and that anything which is legal to pass as a function argument is
// legal here. In particular, the arguments may be temporary expressions
// which will end up being destroyed at the end of the apparent statement,
// for example:
// CHECK_EQ(string("abc")[1], 'b');
//
// WARNING: These don't compile correctly if one of the arguments is a pointer
// and the other is NULL. To work around this, simply static_cast NULL to the
// type of the desired pointer.
#define CHECK_EQ(val1, val2) CHECK_OP(_EQ, ==, val1, val2)
#define CHECK_NE(val1, val2) CHECK_OP(_NE, !=, val1, val2)
#define CHECK_LE(val1, val2) CHECK_OP(_LE, <=, val1, val2)
#define CHECK_LT(val1, val2) CHECK_OP(_LT, < , val1, val2)
#define CHECK_GE(val1, val2) CHECK_OP(_GE, >=, val1, val2)
#define CHECK_GT(val1, val2) CHECK_OP(_GT, > , val1, val2)
// Check that the input is non NULL. This very useful in constructor
// initializer lists.
#define CHECK_NOTNULL(val) \
google::CheckNotNull(__FILE__, __LINE__, "'" #val "' Must be non NULL", (val))
// Helper functions for string comparisons.
// To avoid bloat, the definitions are in logging.cc.
#define DECLARE_CHECK_STROP_IMPL(func, expected) \
GOOGLE_GLOG_DLL_DECL std::string* Check##func##expected##Impl( \
const char* s1, const char* s2, const char* names);
DECLARE_CHECK_STROP_IMPL(strcmp, true)
DECLARE_CHECK_STROP_IMPL(strcmp, false)
DECLARE_CHECK_STROP_IMPL(strcasecmp, true)
DECLARE_CHECK_STROP_IMPL(strcasecmp, false)
#undef DECLARE_CHECK_STROP_IMPL
// Helper macro for string comparisons.
// Don't use this macro directly in your code, use CHECK_STREQ et al below.
#define CHECK_STROP(func, op, expected, s1, s2) \
while (google::CheckOpString _result = \
google::Check##func##expected##Impl((s1), (s2), \
#s1 " " #op " " #s2)) \
LOG(FATAL) << *_result.str_
// String (char*) equality/inequality checks.
// CASE versions are case-insensitive.
//
// Note that "s1" and "s2" may be temporary strings which are destroyed
// by the compiler at the end of the current "full expression"
// (e.g. CHECK_STREQ(Foo().c_str(), Bar().c_str())).
#define CHECK_STREQ(s1, s2) CHECK_STROP(strcmp, ==, true, s1, s2)
#define CHECK_STRNE(s1, s2) CHECK_STROP(strcmp, !=, false, s1, s2)
#define CHECK_STRCASEEQ(s1, s2) CHECK_STROP(strcasecmp, ==, true, s1, s2)
#define CHECK_STRCASENE(s1, s2) CHECK_STROP(strcasecmp, !=, false, s1, s2)
#define CHECK_INDEX(I,A) CHECK(I < (sizeof(A)/sizeof(A[0])))
#define CHECK_BOUND(B,A) CHECK(B <= (sizeof(A)/sizeof(A[0])))
#define CHECK_DOUBLE_EQ(val1, val2) \
do { \
CHECK_LE((val1), (val2)+0.000000000000001L); \
CHECK_GE((val1), (val2)-0.000000000000001L); \
} while (0)
#define CHECK_NEAR(val1, val2, margin) \
do { \
CHECK_LE((val1), (val2)+(margin)); \
CHECK_GE((val1), (val2)-(margin)); \
} while (0)
// perror()..googly style!
//
// PLOG() and PLOG_IF() and PCHECK() behave exactly like their LOG* and
// CHECK equivalents with the addition that they postpend a description
// of the current state of errno to their output lines.
#define PLOG(severity) GOOGLE_PLOG(severity, 0).stream()
#define GOOGLE_PLOG(severity, counter) \
google::ErrnoLogMessage( \
__FILE__, __LINE__, google::GLOG_ ## severity, counter, \
&google::LogMessage::SendToLog)
#define PLOG_IF(severity, condition) \
!(condition) ? (void) 0 : google::LogMessageVoidify() & PLOG(severity)
// A CHECK() macro that postpends errno if the condition is false. E.g.
//
// if (poll(fds, nfds, timeout) == -1) { PCHECK(errno == EINTR); ... }
#define PCHECK(condition) \
PLOG_IF(FATAL, GOOGLE_PREDICT_BRANCH_NOT_TAKEN(!(condition))) \
<< "Check failed: " #condition " "
// A CHECK() macro that lets you assert the success of a function that
// returns -1 and sets errno in case of an error. E.g.
//
// CHECK_ERR(mkdir(path, 0700));
//
// or
//
// int fd = open(filename, flags); CHECK_ERR(fd) << ": open " << filename;
#define CHECK_ERR(invocation) \
PLOG_IF(FATAL, GOOGLE_PREDICT_BRANCH_NOT_TAKEN((invocation) == -1)) \
<< #invocation
// Use macro expansion to create, for each use of LOG_EVERY_N(), static
// variables with the __LINE__ expansion as part of the variable name.
#define LOG_EVERY_N_VARNAME(base, line) LOG_EVERY_N_VARNAME_CONCAT(base, line)
#define LOG_EVERY_N_VARNAME_CONCAT(base, line) base ## line
#define LOG_OCCURRENCES LOG_EVERY_N_VARNAME(occurrences_, __LINE__)
#define LOG_OCCURRENCES_MOD_N LOG_EVERY_N_VARNAME(occurrences_mod_n_, __LINE__)
#define SOME_KIND_OF_LOG_EVERY_N(severity, n, what_to_do) \
static int LOG_OCCURRENCES = 0, LOG_OCCURRENCES_MOD_N = 0; \
++LOG_OCCURRENCES; \
if (++LOG_OCCURRENCES_MOD_N > n) LOG_OCCURRENCES_MOD_N -= n; \
if (LOG_OCCURRENCES_MOD_N == 1) \
google::LogMessage( \
__FILE__, __LINE__, google::GLOG_ ## severity, LOG_OCCURRENCES, \
&what_to_do).stream()
#define SOME_KIND_OF_LOG_IF_EVERY_N(severity, condition, n, what_to_do) \
static int LOG_OCCURRENCES = 0, LOG_OCCURRENCES_MOD_N = 0; \
++LOG_OCCURRENCES; \
if (condition && \
((LOG_OCCURRENCES_MOD_N=(LOG_OCCURRENCES_MOD_N + 1) % n) == (1 % n))) \
google::LogMessage( \
__FILE__, __LINE__, google::GLOG_ ## severity, LOG_OCCURRENCES, \
&what_to_do).stream()
#define SOME_KIND_OF_PLOG_EVERY_N(severity, n, what_to_do) \
static int LOG_OCCURRENCES = 0, LOG_OCCURRENCES_MOD_N = 0; \
++LOG_OCCURRENCES; \
if (++LOG_OCCURRENCES_MOD_N > n) LOG_OCCURRENCES_MOD_N -= n; \
if (LOG_OCCURRENCES_MOD_N == 1) \
google::ErrnoLogMessage( \
__FILE__, __LINE__, google::GLOG_ ## severity, LOG_OCCURRENCES, \
&what_to_do).stream()
#define SOME_KIND_OF_LOG_FIRST_N(severity, n, what_to_do) \
static int LOG_OCCURRENCES = 0; \
if (LOG_OCCURRENCES <= n) \
++LOG_OCCURRENCES; \
if (LOG_OCCURRENCES <= n) \
google::LogMessage( \
__FILE__, __LINE__, google::GLOG_ ## severity, LOG_OCCURRENCES, \
&what_to_do).stream()
namespace glog_internal_namespace_ {
template <bool>
struct CompileAssert {
};
struct CrashReason;
} // namespace glog_internal_namespace_
#define GOOGLE_GLOG_COMPILE_ASSERT(expr, msg) \
typedef google::glog_internal_namespace_::CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]
#define LOG_EVERY_N(severity, n) \
GOOGLE_GLOG_COMPILE_ASSERT(google::GLOG_ ## severity < \
google::NUM_SEVERITIES, \
INVALID_REQUESTED_LOG_SEVERITY); \
SOME_KIND_OF_LOG_EVERY_N(severity, (n), google::LogMessage::SendToLog)
#define SYSLOG_EVERY_N(severity, n) \
SOME_KIND_OF_LOG_EVERY_N(severity, (n), google::LogMessage::SendToSyslogAndLog)
#define PLOG_EVERY_N(severity, n) \
SOME_KIND_OF_PLOG_EVERY_N(severity, (n), google::LogMessage::SendToLog)
#define LOG_FIRST_N(severity, n) \
SOME_KIND_OF_LOG_FIRST_N(severity, (n), google::LogMessage::SendToLog)
#define LOG_IF_EVERY_N(severity, condition, n) \
SOME_KIND_OF_LOG_IF_EVERY_N(severity, (condition), (n), google::LogMessage::SendToLog)
// We want the special COUNTER value available for LOG_EVERY_X()'ed messages
enum PRIVATE_Counter { COUNTER };
#ifdef GLOG_NO_ABBREVIATED_SEVERITIES
// wingdi.h defines ERROR to be 0. When we call LOG(ERROR), it gets
// substituted with 0, and it expands to COMPACT_GOOGLE_LOG_0. To allow us
// to keep using this syntax, we define this macro to do the same thing
// as COMPACT_GOOGLE_LOG_ERROR.
#define COMPACT_GOOGLE_LOG_0 COMPACT_GOOGLE_LOG_ERROR
#define SYSLOG_0 SYSLOG_ERROR
#define LOG_TO_STRING_0 LOG_TO_STRING_ERROR
// Needed for LOG_IS_ON(ERROR).
const LogSeverity GLOG_0 = GLOG_ERROR;
#else
// Users may include windows.h after logging.h without
// GLOG_NO_ABBREVIATED_SEVERITIES nor WIN32_LEAN_AND_MEAN.
// For this case, we cannot detect if ERROR is defined before users
// actually use ERROR. Let's make an undefined symbol to warn users.
# define GLOG_ERROR_MSG ERROR_macro_is_defined_Define_GLOG_NO_ABBREVIATED_SEVERITIES_before_including_logging_h_See_the_document_for_detail
# define COMPACT_GOOGLE_LOG_0 GLOG_ERROR_MSG
# define SYSLOG_0 GLOG_ERROR_MSG
# define LOG_TO_STRING_0 GLOG_ERROR_MSG
# define GLOG_0 GLOG_ERROR_MSG
#endif
// Plus some debug-logging macros that get compiled to nothing for production
#ifndef NDEBUG
#define DLOG(severity) LOG(severity)
#define DVLOG(verboselevel) VLOG(verboselevel)
#define DLOG_IF(severity, condition) LOG_IF(severity, condition)
#define DLOG_EVERY_N(severity, n) LOG_EVERY_N(severity, n)
#define DLOG_IF_EVERY_N(severity, condition, n) \
LOG_IF_EVERY_N(severity, condition, n)
#define DLOG_ASSERT(condition) LOG_ASSERT(condition)
// debug-only checking. not executed in NDEBUG mode.
#define DCHECK(condition) CHECK(condition)
#define DCHECK_EQ(val1, val2) CHECK_EQ(val1, val2)
#define DCHECK_NE(val1, val2) CHECK_NE(val1, val2)
#define DCHECK_LE(val1, val2) CHECK_LE(val1, val2)
#define DCHECK_LT(val1, val2) CHECK_LT(val1, val2)
#define DCHECK_GE(val1, val2) CHECK_GE(val1, val2)
#define DCHECK_GT(val1, val2) CHECK_GT(val1, val2)
#define DCHECK_NOTNULL(val) CHECK_NOTNULL(val)
#define DCHECK_STREQ(str1, str2) CHECK_STREQ(str1, str2)
#define DCHECK_STRCASEEQ(str1, str2) CHECK_STRCASEEQ(str1, str2)
#define DCHECK_STRNE(str1, str2) CHECK_STRNE(str1, str2)
#define DCHECK_STRCASENE(str1, str2) CHECK_STRCASENE(str1, str2)
#else // NDEBUG
#define DLOG(severity) \
true ? (void) 0 : google::LogMessageVoidify() & LOG(severity)
#define DVLOG(verboselevel) \
(true || !VLOG_IS_ON(verboselevel)) ?\
(void) 0 : google::LogMessageVoidify() & LOG(INFO)
#define DLOG_IF(severity, condition) \
(true || !(condition)) ? (void) 0 : google::LogMessageVoidify() & LOG(severity)
#define DLOG_EVERY_N(severity, n) \
true ? (void) 0 : google::LogMessageVoidify() & LOG(severity)
#define DLOG_IF_EVERY_N(severity, condition, n) \
(true || !(condition))? (void) 0 : google::LogMessageVoidify() & LOG(severity)
#define DLOG_ASSERT(condition) \
true ? (void) 0 : LOG_ASSERT(condition)
// MSVC warning C4127: conditional expression is constant
#define DCHECK(condition) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) \
GLOG_MSVC_POP_WARNING() CHECK(condition)
#define DCHECK_EQ(val1, val2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) \
GLOG_MSVC_POP_WARNING() CHECK_EQ(val1, val2)
#define DCHECK_NE(val1, val2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) \
GLOG_MSVC_POP_WARNING() CHECK_NE(val1, val2)
#define DCHECK_LE(val1, val2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) \
GLOG_MSVC_POP_WARNING() CHECK_LE(val1, val2)
#define DCHECK_LT(val1, val2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) \
GLOG_MSVC_POP_WARNING() CHECK_LT(val1, val2)
#define DCHECK_GE(val1, val2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) \
GLOG_MSVC_POP_WARNING() CHECK_GE(val1, val2)
#define DCHECK_GT(val1, val2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) \
GLOG_MSVC_POP_WARNING() CHECK_GT(val1, val2)
// You may see warnings in release mode if you don't use the return
// value of DCHECK_NOTNULL. Please just use DCHECK for such cases.
#define DCHECK_NOTNULL(val) (val)
#define DCHECK_STREQ(str1, str2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) \
GLOG_MSVC_POP_WARNING() CHECK_STREQ(str1, str2)
#define DCHECK_STRCASEEQ(str1, str2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) \
GLOG_MSVC_POP_WARNING() CHECK_STRCASEEQ(str1, str2)
#define DCHECK_STRNE(str1, str2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) \
GLOG_MSVC_POP_WARNING() CHECK_STRNE(str1, str2)
#define DCHECK_STRCASENE(str1, str2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) \
GLOG_MSVC_POP_WARNING() CHECK_STRCASENE(str1, str2)
#endif // NDEBUG
// Log only in verbose mode.
#define VLOG(verboselevel) LOG_IF(INFO, VLOG_IS_ON(verboselevel))
#define VLOG_IF(verboselevel, condition) \
LOG_IF(INFO, (condition) && VLOG_IS_ON(verboselevel))
#define VLOG_EVERY_N(verboselevel, n) \
LOG_IF_EVERY_N(INFO, VLOG_IS_ON(verboselevel), n)
#define VLOG_IF_EVERY_N(verboselevel, condition, n) \
LOG_IF_EVERY_N(INFO, (condition) && VLOG_IS_ON(verboselevel), n)
namespace base_logging {
// LogMessage::LogStream is a std::ostream backed by this streambuf.
// This class ignores overflow and leaves two bytes at the end of the
// buffer to allow for a '\n' and '\0'.
class LogStreamBuf : public std::streambuf {
public:
// REQUIREMENTS: "len" must be >= 2 to account for the '\n' and '\n'.
LogStreamBuf(char *buf, int len) {
setp(buf, buf + len - 2);
}
// This effectively ignores overflow.
virtual int_type overflow(int_type ch) {
return ch;
}
// Legacy public ostrstream method.
size_t pcount() const { return pptr() - pbase(); }
char* pbase() const { return std::streambuf::pbase(); }
};
} // namespace base_logging
//
// This class more or less represents a particular log message. You
// create an instance of LogMessage and then stream stuff to it.
// When you finish streaming to it, ~LogMessage is called and the
// full message gets streamed to the appropriate destination.
//
// You shouldn't actually use LogMessage's constructor to log things,
// though. You should use the LOG() macro (and variants thereof)
// above.
class GOOGLE_GLOG_DLL_DECL LogMessage {
public:
enum {
// Passing kNoLogPrefix for the line number disables the
// log-message prefix. Useful for using the LogMessage
// infrastructure as a printing utility. See also the --log_prefix
// flag for controlling the log-message prefix on an
// application-wide basis.
kNoLogPrefix = -1
};
// LogStream inherit from non-DLL-exported class (std::ostrstream)
// and VC++ produces a warning for this situation.
// However, MSDN says "C4275 can be ignored in Microsoft Visual C++
// 2005 if you are deriving from a type in the Standard C++ Library"
// http://msdn.microsoft.com/en-us/library/3tdb471s(VS.80).aspx
// Let's just ignore the warning.
#ifdef _MSC_VER
# pragma warning(disable: 4275)
#endif
class GOOGLE_GLOG_DLL_DECL LogStream : public std::ostream {
#ifdef _MSC_VER
# pragma warning(default: 4275)
#endif
public:
LogStream(char *buf, int len, int ctr)
: std::ostream(NULL),
streambuf_(buf, len),
ctr_(ctr),
self_(this) {
rdbuf(&streambuf_);
}
LogStream(const LogStream &) = delete;
void operator=(const LogStream &) = delete;
int ctr() const { return ctr_; }
void set_ctr(int ctr) { ctr_ = ctr; }
LogStream* self() const { return self_; }
// Legacy std::streambuf methods.
size_t pcount() const { return streambuf_.pcount(); }
char* pbase() const { return streambuf_.pbase(); }
char* str() const { return pbase(); }
private:
base_logging::LogStreamBuf streambuf_;
int ctr_; // Counter hack (for the LOG_EVERY_X() macro)
LogStream *self_; // Consistency check hack
};
public:
// icc 8 requires this typedef to avoid an internal compiler error.
typedef void (LogMessage::*SendMethod)();
LogMessage(const char* file, int line, LogSeverity severity, int ctr,
SendMethod send_method);
// Two special constructors that generate reduced amounts of code at
// LOG call sites for common cases.
// Used for LOG(INFO): Implied are:
// severity = INFO, ctr = 0, send_method = &LogMessage::SendToLog.
//
// Using this constructor instead of the more complex constructor above
// saves 19 bytes per call site.
LogMessage(const char* file, int line);
// Used for LOG(severity) where severity != INFO. Implied
// are: ctr = 0, send_method = &LogMessage::SendToLog
//
// Using this constructor instead of the more complex constructor above
// saves 17 bytes per call site.
LogMessage(const char* file, int line, LogSeverity severity);
// Constructor to log this message to a specified sink (if not NULL).
// Implied are: ctr = 0, send_method = &LogMessage::SendToSinkAndLog if
// also_send_to_log is true, send_method = &LogMessage::SendToSink otherwise.
LogMessage(const char* file, int line, LogSeverity severity, LogSink* sink,
bool also_send_to_log);
// Constructor where we also give a vector<string> pointer
// for storing the messages (if the pointer is not NULL).
// Implied are: ctr = 0, send_method = &LogMessage::SaveOrSendToLog.
LogMessage(const char* file, int line, LogSeverity severity,
std::vector<std::string>* outvec);
// Constructor where we also give a string pointer for storing the
// message (if the pointer is not NULL). Implied are: ctr = 0,
// send_method = &LogMessage::WriteToStringAndLog.
LogMessage(const char* file, int line, LogSeverity severity,
std::string* message);
// A special constructor used for check failures
LogMessage(const char* file, int line, const CheckOpString& result);
~LogMessage();
// Flush a buffered message to the sink set in the constructor. Always
// called by the destructor, it may also be called from elsewhere if
// needed. Only the first call is actioned; any later ones are ignored.
void Flush();
// An arbitrary limit on the length of a single log message. This
// is so that streaming can be done more efficiently.
static const size_t kMaxLogMessageLen;
// Theses should not be called directly outside of logging.*,
// only passed as SendMethod arguments to other LogMessage methods:
void SendToLog(); // Actually dispatch to the logs
void SendToSyslogAndLog(); // Actually dispatch to syslog and the logs
// Call abort() or similar to perform LOG(FATAL) crash.
static void Fail();
std::ostream& stream();
int preserved_errno() const;
// Must be called without the log_mutex held. (L < log_mutex)
static int64 num_messages(int severity);
struct LogMessageData;
private:
// Fully internal SendMethod cases:
void SendToSinkAndLog(); // Send to sink if provided and dispatch to the logs
void SendToSink(); // Send to sink if provided, do nothing otherwise.
// Write to string if provided and dispatch to the logs.
void WriteToStringAndLog();
void SaveOrSendToLog(); // Save to stringvec if provided, else to logs
void Init(const char* file, int line, LogSeverity severity,
void (LogMessage::*send_method)());
// Used to fill in crash information during LOG(FATAL) failures.
void RecordCrashReason(glog_internal_namespace_::CrashReason* reason);
// Counts of messages sent at each priority:
static int64 num_messages_[NUM_SEVERITIES]; // under log_mutex
// We keep the data in a separate struct so that each instance of
// LogMessage uses less stack space.
LogMessageData* allocated_;
LogMessageData* data_;
friend class LogDestination;
LogMessage(const LogMessage&);
void operator=(const LogMessage&);
};
// This class happens to be thread-hostile because all instances share
// a single data buffer, but since it can only be created just before
// the process dies, we don't worry so much.
class GOOGLE_GLOG_DLL_DECL LogMessageFatal : public LogMessage {
public:
LogMessageFatal(const char* file, int line);
LogMessageFatal(const char* file, int line, const CheckOpString& result);
~LogMessageFatal();
};
// A non-macro interface to the log facility; (useful
// when the logging level is not a compile-time constant).
inline void LogAtLevel(int const severity, std::string const &msg) {
LogMessage(__FILE__, __LINE__, severity).stream() << msg;
}
// A macro alternative of LogAtLevel. New code may want to use this
// version since there are two advantages: 1. this version outputs the
// file name and the line number where this macro is put like other
// LOG macros, 2. this macro can be used as C++ stream.
#define LOG_AT_LEVEL(severity) google::LogMessage(__FILE__, __LINE__, severity).stream()
// A small helper for CHECK_NOTNULL().
template <typename T>
T* CheckNotNull(const char *file, int line, const char *names, T* t) {
if (t == NULL) {
LogMessageFatal(file, line, new std::string(names));
}
return t;
}
// Allow folks to put a counter in the LOG_EVERY_X()'ed messages. This
// only works if ostream is a LogStream. If the ostream is not a
// LogStream you'll get an assert saying as much at runtime.
GOOGLE_GLOG_DLL_DECL std::ostream& operator<<(std::ostream &os,
const PRIVATE_Counter&);
// Derived class for PLOG*() above.
class GOOGLE_GLOG_DLL_DECL ErrnoLogMessage : public LogMessage {
public:
ErrnoLogMessage(const char* file, int line, LogSeverity severity, int ctr,
void (LogMessage::*send_method)());
// Postpends ": strerror(errno) [errno]".
~ErrnoLogMessage();
private:
ErrnoLogMessage(const ErrnoLogMessage&);
void operator=(const ErrnoLogMessage&);
};
// This class is used to explicitly ignore values in the conditional
// logging macros. This avoids compiler warnings like "value computed
// is not used" and "statement has no effect".
class GOOGLE_GLOG_DLL_DECL LogMessageVoidify {
public:
LogMessageVoidify() { }
// This has to be an operator with a precedence lower than << but
// higher than ?:
void operator&(std::ostream&) { }
};
// Flushes all log files that contains messages that are at least of
// the specified severity level. Thread-safe.
GOOGLE_GLOG_DLL_DECL void FlushLogFiles(LogSeverity min_severity);
// Flushes all log files that contains messages that are at least of
// the specified severity level. Thread-hostile because it ignores
// locking -- used for catastrophic failures.
GOOGLE_GLOG_DLL_DECL void FlushLogFilesUnsafe(LogSeverity min_severity);
//
// Set the destination to which a particular severity level of log
// messages is sent. If base_filename is "", it means "don't log this
// severity". Thread-safe.
//
GOOGLE_GLOG_DLL_DECL void SetLogDestination(LogSeverity severity,
const char* base_filename);
//
// Set the basename of the symlink to the latest log file at a given
// severity. If symlink_basename is empty, do not make a symlink. If
// you don't call this function, the symlink basename is the
// invocation name of the program. Thread-safe.
//
GOOGLE_GLOG_DLL_DECL void SetLogSymlink(LogSeverity severity,
const char* symlink_basename);
//
// Used to send logs to some other kind of destination
// Users should subclass LogSink and override send to do whatever they want.
// Implementations must be thread-safe because a shared instance will
// be called from whichever thread ran the LOG(XXX) line.
class GOOGLE_GLOG_DLL_DECL LogSink {
public:
virtual ~LogSink();
// Sink's logging logic (message_len is such as to exclude '\n' at the end).
// This method can't use LOG() or CHECK() as logging system mutex(s) are held
// during this call.
virtual void send(LogSeverity severity, const char* full_filename,
const char* base_filename, int line,
const struct ::tm* tm_time,
const char* message, size_t message_len) = 0;
// Redefine this to implement waiting for
// the sink's logging logic to complete.
// It will be called after each send() returns,
// but before that LogMessage exits or crashes.
// By default this function does nothing.
// Using this function one can implement complex logic for send()
// that itself involves logging; and do all this w/o causing deadlocks and
// inconsistent rearrangement of log messages.
// E.g. if a LogSink has thread-specific actions, the send() method
// can simply add the message to a queue and wake up another thread that
// handles real logging while itself making some LOG() calls;
// WaitTillSent() can be implemented to wait for that logic to complete.
// See our unittest for an example.
virtual void WaitTillSent();
// Returns the normal text output of the log message.
// Can be useful to implement send().
static std::string ToString(LogSeverity severity, const char* file, int line,
const struct ::tm* tm_time,
const char* message, size_t message_len);
};
// Add or remove a LogSink as a consumer of logging data. Thread-safe.
GOOGLE_GLOG_DLL_DECL void AddLogSink(LogSink *destination);
GOOGLE_GLOG_DLL_DECL void RemoveLogSink(LogSink *destination);
//
// Specify an "extension" added to the filename specified via
// SetLogDestination. This applies to all severity levels. It's
// often used to append the port we're listening on to the logfile
// name. Thread-safe.
//
GOOGLE_GLOG_DLL_DECL void SetLogFilenameExtension(
const char* filename_extension);
//
// Make it so that all log messages of at least a particular severity
// are logged to stderr (in addition to logging to the usual log
// file(s)). Thread-safe.
//
GOOGLE_GLOG_DLL_DECL void SetStderrLogging(LogSeverity min_severity);
//
// Make it so that all log messages go only to stderr. Thread-safe.
//
GOOGLE_GLOG_DLL_DECL void LogToStderr();
//
// Make it so that all log messages of at least a particular severity are
// logged via email to a list of addresses (in addition to logging to the
// usual log file(s)). The list of addresses is just a string containing
// the email addresses to send to (separated by spaces, say). Thread-safe.
//
GOOGLE_GLOG_DLL_DECL void SetEmailLogging(LogSeverity min_severity,
const char* addresses);
// A simple function that sends email. dest is a commma-separated
// list of addressess. Thread-safe.
GOOGLE_GLOG_DLL_DECL bool SendEmail(const char *dest,
const char *subject, const char *body);
GOOGLE_GLOG_DLL_DECL const std::vector<std::string>& GetLoggingDirectories();
// For tests only: Clear the internal [cached] list of logging directories to
// force a refresh the next time GetLoggingDirectories is called.
// Thread-hostile.
void TestOnly_ClearLoggingDirectoriesList();
// Returns a set of existing temporary directories, which will be a
// subset of the directories returned by GetLogginDirectories().
// Thread-safe.
GOOGLE_GLOG_DLL_DECL void GetExistingTempDirectories(
std::vector<std::string>* list);
// Print any fatal message again -- useful to call from signal handler
// so that the last thing in the output is the fatal message.
// Thread-hostile, but a race is unlikely.
GOOGLE_GLOG_DLL_DECL void ReprintFatalMessage();
// Truncate a log file that may be the append-only output of multiple
// processes and hence can't simply be renamed/reopened (typically a
// stdout/stderr). If the file "path" is > "limit" bytes, copy the
// last "keep" bytes to offset 0 and truncate the rest. Since we could
// be racing with other writers, this approach has the potential to
// lose very small amounts of data. For security, only follow symlinks
// if the path is /proc/self/fd/*
GOOGLE_GLOG_DLL_DECL void TruncateLogFile(const char *path,
int64 limit, int64 keep);
// Truncate stdout and stderr if they are over the value specified by
// --max_log_size; keep the final 1MB. This function has the same
// race condition as TruncateLogFile.
GOOGLE_GLOG_DLL_DECL void TruncateStdoutStderr();
// Return the string representation of the provided LogSeverity level.
// Thread-safe.
GOOGLE_GLOG_DLL_DECL const char* GetLogSeverityName(LogSeverity severity);
// ---------------------------------------------------------------------
// Implementation details that are not useful to most clients
// ---------------------------------------------------------------------
// A Logger is the interface used by logging modules to emit entries
// to a log. A typical implementation will dump formatted data to a
// sequence of files. We also provide interfaces that will forward
// the data to another thread so that the invoker never blocks.
// Implementations should be thread-safe since the logging system
// will write to them from multiple threads.
namespace base {
class GOOGLE_GLOG_DLL_DECL Logger {
public:
virtual ~Logger();
// Writes "message[0,message_len-1]" corresponding to an event that
// occurred at "timestamp". If "force_flush" is true, the log file
// is flushed immediately.
//
// The input message has already been formatted as deemed
// appropriate by the higher level logging facility. For example,
// textual log messages already contain timestamps, and the
// file:linenumber header.
virtual void Write(bool force_flush,
time_t timestamp,
const char* message,
int message_len) = 0;
// Flush any buffered messages
virtual void Flush() = 0;
// Get the current LOG file size.
// The returned value is approximate since some
// logged data may not have been flushed to disk yet.
virtual uint32 LogSize() = 0;
};
// Get the logger for the specified severity level. The logger
// remains the property of the logging module and should not be
// deleted by the caller. Thread-safe.
extern GOOGLE_GLOG_DLL_DECL Logger* GetLogger(LogSeverity level);
// Set the logger for the specified severity level. The logger
// becomes the property of the logging module and should not
// be deleted by the caller. Thread-safe.
extern GOOGLE_GLOG_DLL_DECL void SetLogger(LogSeverity level, Logger* logger);
}
// glibc has traditionally implemented two incompatible versions of
// strerror_r(). There is a poorly defined convention for picking the
// version that we want, but it is not clear whether it even works with
// all versions of glibc.
// So, instead, we provide this wrapper that automatically detects the
// version that is in use, and then implements POSIX semantics.
// N.B. In addition to what POSIX says, we also guarantee that "buf" will
// be set to an empty string, if this function failed. This means, in most
// cases, you do not need to check the error code and you can directly
// use the value of "buf". It will never have an undefined value.
GOOGLE_GLOG_DLL_DECL int posix_strerror_r(int err, char *buf, size_t len);
// A class for which we define operator<<, which does nothing.
class GOOGLE_GLOG_DLL_DECL NullStream : public LogMessage::LogStream {
public:
// Initialize the LogStream so the messages can be written somewhere
// (they'll never be actually displayed). This will be needed if a
// NullStream& is implicitly converted to LogStream&, in which case
// the overloaded NullStream::operator<< will not be invoked.
NullStream() : LogMessage::LogStream(message_buffer_, 1, 0) { }
NullStream(const char* /*file*/, int /*line*/,
const CheckOpString& /*result*/) :
LogMessage::LogStream(message_buffer_, 1, 0) { }
NullStream &stream() { return *this; }
private:
// A very short buffer for messages (which we discard anyway). This
// will be needed if NullStream& converted to LogStream& (e.g. as a
// result of a conditional expression).
char message_buffer_[2];
};
// Do nothing. This operator is inline, allowing the message to be
// compiled away. The message will not be compiled away if we do
// something like (flag ? LOG(INFO) : LOG(ERROR)) << message; when
// SKIP_LOG=WARNING. In those cases, NullStream will be implicitly
// converted to LogStream and the message will be computed and then
// quietly discarded.
template<class T>
inline NullStream& operator<<(NullStream &str, const T &) { return str; }
// Similar to NullStream, but aborts the program (without stack
// trace), like LogMessageFatal.
class GOOGLE_GLOG_DLL_DECL NullStreamFatal : public NullStream {
public:
NullStreamFatal() { }
NullStreamFatal(const char* file, int line, const CheckOpString& result) :
NullStream(file, line, result) { }
~NullStreamFatal() { _exit(1); }
};
// Install a signal handler that will dump signal information and a stack
// trace when the program crashes on certain signals. We'll install the
// signal handler for the following signals.
//
// SIGSEGV, SIGILL, SIGFPE, SIGABRT, SIGBUS, and SIGTERM.
//
// By default, the signal handler will write the failure dump to the
// standard error. You can customize the destination by installing your
// own writer function by InstallFailureWriter() below.
//
// Note on threading:
//
// The function should be called before threads are created, if you want
// to use the failure signal handler for all threads. The stack trace
// will be shown only for the thread that receives the signal. In other
// words, stack traces of other threads won't be shown.
GOOGLE_GLOG_DLL_DECL void InstallFailureSignalHandler();
// Installs a function that is used for writing the failure dump. "data"
// is the pointer to the beginning of a message to be written, and "size"
// is the size of the message. You should not expect the data is
// terminated with '\0'.
GOOGLE_GLOG_DLL_DECL void InstallFailureWriter(
void(*writer)(const char* data, int size));
}
#endif // _LOGGING_H_
// Copyright (c) 2007, 2008 libmv authors.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
#ifndef LIBMV_NUMERIC_POLY_H_
#define LIBMV_NUMERIC_POLY_H_
#define M_E 2.71828182845904523536
#define M_LOG2E 1.44269504088896340736
#define M_LOG10E 0.434294481903251827651
#define M_LN2 0.693147180559945309417
#define M_LN10 2.30258509299404568402
#define M_PI 3.14159265358979323846
#define M_PI_2 1.57079632679489661923
#define M_PI_4 0.785398163397448309616
#define M_1_PI 0.318309886183790671538
#define M_2_PI 0.636619772367581343076
#define M_2_SQRTPI 1.12837916709551257390
#define M_SQRT2 1.41421356237309504880
#define M_SQRT1_2 0.707106781186547524401
#include <cmath>
#include <stdio.h>
namespace libmv {
// Solve the cubic polynomial
//
// x^3 + a*x^2 + b*x + c = 0
//
// The number of roots (from zero to three) is returned. If the number of roots
// is less than three, then higher numbered x's are not changed. For example,
// if there are 2 roots, only x0 and x1 are set.
//
// The GSL cubic solver was used as a reference for this routine.
template<typename Real>
int SolveCubicPolynomial(Real a, Real b, Real c,
Real *x0, Real *x1, Real *x2) {
Real q = a * a - 3 * b;
Real r = 2 * a * a * a - 9 * a * b + 27 * c;
Real Q = q / 9;
Real R = r / 54;
Real Q3 = Q * Q * Q;
Real R2 = R * R;
Real CR2 = 729 * r * r;
Real CQ3 = 2916 * q * q * q;
if (R == 0 && Q == 0) {
// Tripple root in one place.
*x0 = *x1 = *x2 = -a / 3;
return 3;
} else if (CR2 == CQ3) {
// This test is actually R2 == Q3, written in a form suitable for exact
// computation with integers.
//
// Due to finite precision some double roots may be missed, and considered
// to be a pair of complex roots z = x +/- epsilon i close to the real
// axis.
Real sqrtQ = sqrt(Q);
if (R > 0) {
*x0 = -2 * sqrtQ - a / 3;
*x1 = sqrtQ - a / 3;
*x2 = sqrtQ - a / 3;
} else {
*x0 = -sqrtQ - a / 3;
*x1 = -sqrtQ - a / 3;
*x2 = 2 * sqrtQ - a / 3;
}
return 3;
} else if (CR2 < CQ3) {
// This case is equivalent to R2 < Q3.
Real sqrtQ = sqrt(Q);
Real sqrtQ3 = sqrtQ * sqrtQ * sqrtQ;
Real theta = acos(R / sqrtQ3);
Real norm = -2 * sqrtQ;
*x0 = norm * cos(theta / 3) - a / 3;
*x1 = norm * cos((theta + 2.0 * M_PI) / 3) - a / 3;
*x2 = norm * cos((theta - 2.0 * M_PI) / 3) - a / 3;
// Put the roots in ascending order.
if (*x0 > *x1) {
std::swap(*x0, *x1);
}
if (*x1 > *x2) {
std::swap(*x1, *x2);
if (*x0 > *x1) {
std::swap(*x0, *x1);
}
}
return 3;
}
Real sgnR = (R >= 0 ? 1 : -1);
Real A = -sgnR * pow(fabs(R) + sqrt(R2 - Q3), 1.0/3.0);
Real B = Q / A;
*x0 = A + B - a / 3;
return 1;
}
// The coefficients are in ascending powers, i.e. coeffs[N]*x^N.
template<typename Real>
int SolveCubicPolynomial(const Real *coeffs, Real *solutions) {
if (coeffs[0] == 0.0) {
// TODO(keir): This is a quadratic not a cubic. Implement a quadratic
// solver!
return 0;
}
Real a = coeffs[2] / coeffs[3];
Real b = coeffs[1] / coeffs[3];
Real c = coeffs[0] / coeffs[3];
return SolveCubicPolynomial(a, b, c,
solutions + 0,
solutions + 1,
solutions + 2);
}
} // namespace libmv
#endif // LIBMV_NUMERIC_POLY_H_
/* This is an implementation of the threads API of POSIX 1003.1-2001.
*
* --------------------------------------------------------------------------
*
* Pthreads-win32 - POSIX Threads Library for Win32
* Copyright(C) 1998 John E. Bossom
* Copyright(C) 1999,2005 Pthreads-win32 contributors
*
* Contact Email: rpj@callisto.canberra.edu.au
*
* The current list of contributors is contained
* in the file CONTRIBUTORS included with the source
* code distribution. The list can also be seen at the
* following World Wide Web location:
* http://sources.redhat.com/pthreads-win32/contributors.html
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library in the file COPYING.LIB;
* if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined( PTHREAD_H )
#define PTHREAD_H
/*
* See the README file for an explanation of the pthreads-win32 version
* numbering scheme and how the DLL is named etc.
*/
#define PTW32_VERSION 2,8,0,0
#define PTW32_VERSION_STRING "2, 8, 0, 0\0"
/* There are three implementations of cancel cleanup.
* Note that pthread.h is included in both application
* compilation units and also internally for the library.
* The code here and within the library aims to work
* for all reasonable combinations of environments.
*
* The three implementations are:
*
* WIN32 SEH
* C
* C++
*
* Please note that exiting a push/pop block via
* "return", "exit", "break", or "continue" will
* lead to different behaviour amongst applications
* depending upon whether the library was built
* using SEH, C++, or C. For example, a library built
* with SEH will call the cleanup routine, while both
* C++ and C built versions will not.
*/
/*
* Define defaults for cleanup code.
* Note: Unless the build explicitly defines one of the following, then
* we default to standard C style cleanup. This style uses setjmp/longjmp
* in the cancelation and thread exit implementations and therefore won't
* do stack unwinding if linked to applications that have it (e.g.
* C++ apps). This is currently consistent with most/all commercial Unix
* POSIX threads implementations.
*/
#if !defined( __CLEANUP_SEH ) && !defined( __CLEANUP_CXX ) && !defined( __CLEANUP_C )
# define __CLEANUP_C
#endif
#if defined( __CLEANUP_SEH ) && ( !defined( _MSC_VER ) && !defined(PTW32_RC_MSC))
#error ERROR [__FILE__, line __LINE__]: SEH is not supported for this compiler.
#endif
/*
* Stop here if we are being included by the resource compiler.
*/
#ifndef RC_INVOKED
#undef PTW32_LEVEL
#if defined(_POSIX_SOURCE)
#define PTW32_LEVEL 0
/* Early POSIX */
#endif
#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
#undef PTW32_LEVEL
#define PTW32_LEVEL 1
/* Include 1b, 1c and 1d */
#endif
#if defined(INCLUDE_NP)
#undef PTW32_LEVEL
#define PTW32_LEVEL 2
/* Include Non-Portable extensions */
#endif
#define PTW32_LEVEL_MAX 3
#if !defined(PTW32_LEVEL)
#define PTW32_LEVEL PTW32_LEVEL_MAX
/* Include everything */
#endif
#ifdef _UWIN
# define HAVE_STRUCT_TIMESPEC 1
# define HAVE_SIGNAL_H 1
# undef HAVE_CONFIG_H
# pragma comment(lib, "pthread")
#endif
/*
* -------------------------------------------------------------
*
*
* Module: pthread.h
*
* Purpose:
* Provides an implementation of PThreads based upon the
* standard:
*
* POSIX 1003.1-2001
* and
* The Single Unix Specification version 3
*
* (these two are equivalent)
*
* in order to enhance code portability between Windows,
* various commercial Unix implementations, and Linux.
*
* See the ANNOUNCE file for a full list of conforming
* routines and defined constants, and a list of missing
* routines and constants not defined in this implementation.
*
* Authors:
* There have been many contributors to this library.
* The initial implementation was contributed by
* John Bossom, and several others have provided major
* sections or revisions of parts of the implementation.
* Often significant effort has been contributed to
* find and fix important bugs and other problems to
* improve the reliability of the library, which sometimes
* is not reflected in the amount of code which changed as
* result.
* As much as possible, the contributors are acknowledged
* in the ChangeLog file in the source code distribution
* where their changes are noted in detail.
*
* Contributors are listed in the CONTRIBUTORS file.
*
* As usual, all bouquets go to the contributors, and all
* brickbats go to the project maintainer.
*
* Maintainer:
* The code base for this project is coordinated and
* eventually pre-tested, packaged, and made available by
*
* Ross Johnson <rpj@callisto.canberra.edu.au>
*
* QA Testers:
* Ultimately, the library is tested in the real world by
* a host of competent and demanding scientists and
* engineers who report bugs and/or provide solutions
* which are then fixed or incorporated into subsequent
* versions of the library. Each time a bug is fixed, a
* test case is written to prove the fix and ensure
* that later changes to the code don't reintroduce the
* same error. The number of test cases is slowly growing
* and therefore so is the code reliability.
*
* Compliance:
* See the file ANNOUNCE for the list of implemented
* and not-implemented routines and defined options.
* Of course, these are all defined is this file as well.
*
* Web site:
* The source code and other information about this library
* are available from
*
* http://sources.redhat.com/pthreads-win32/
*
* -------------------------------------------------------------
*/
/* Try to avoid including windows.h */
#if defined(__MINGW32__) && defined(__cplusplus)
#define PTW32_INCLUDE_WINDOWS_H
#endif
#ifdef PTW32_INCLUDE_WINDOWS_H
#include <windows.h>
#endif
#if defined(_MSC_VER) && _MSC_VER < 1300 || defined(__DMC__)
/*
* VC++6.0 or early compiler's header has no DWORD_PTR type.
*/
typedef unsigned long DWORD_PTR;
#endif
/*
* -----------------
* autoconf switches
* -----------------
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#ifndef NEED_FTIME
#include <time.h>
#else /* NEED_FTIME */
/* use native WIN32 time API */
#endif /* NEED_FTIME */
#if HAVE_SIGNAL_H
#include <signal.h>
#endif /* HAVE_SIGNAL_H */
#include <setjmp.h>
#include <limits.h>
/*
* Boolean values to make us independent of system includes.
*/
enum {
PTW32_FALSE = 0,
PTW32_TRUE = (! PTW32_FALSE)
};
/*
* This is a duplicate of what is in the autoconf config.h,
* which is only used when building the pthread-win32 libraries.
*/
#ifndef PTW32_CONFIG_H
# if defined(WINCE)
# define NEED_ERRNO
# define NEED_SEM
# endif
# if defined(_UWIN) || defined(__MINGW32__)
# define HAVE_MODE_T
# endif
#endif
/*
*
*/
#if PTW32_LEVEL >= PTW32_LEVEL_MAX
#ifdef NEED_ERRNO
#include "need_errno.h"
#else
#include <errno.h>
#endif
#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
/*
* Several systems don't define some error numbers.
*/
#ifndef ENOTSUP
# define ENOTSUP 48 /* This is the value in Solaris. */
#endif
#ifndef ETIMEDOUT
# define ETIMEDOUT 10060 /* This is the value in winsock.h. */
#endif
#ifndef ENOSYS
# define ENOSYS 140 /* Semi-arbitrary value */
#endif
#ifndef EDEADLK
# ifdef EDEADLOCK
# define EDEADLK EDEADLOCK
# else
# define EDEADLK 36 /* This is the value in MSVC. */
# endif
#endif
#include <sched.h>
/*
* To avoid including windows.h we define only those things that we
* actually need from it.
*/
#ifndef PTW32_INCLUDE_WINDOWS_H
#ifndef HANDLE
# define PTW32__HANDLE_DEF
# define HANDLE void *
#endif
#ifndef DWORD
# define PTW32__DWORD_DEF
# define DWORD unsigned long
#endif
#endif
#ifndef HAVE_STRUCT_TIMESPEC
#define HAVE_STRUCT_TIMESPEC 1
//struct timespec {
// long tv_sec;
// long tv_nsec;
//};
#endif /* HAVE_STRUCT_TIMESPEC */
#ifndef SIG_BLOCK
#define SIG_BLOCK 0
#endif /* SIG_BLOCK */
#ifndef SIG_UNBLOCK
#define SIG_UNBLOCK 1
#endif /* SIG_UNBLOCK */
#ifndef SIG_SETMASK
#define SIG_SETMASK 2
#endif /* SIG_SETMASK */
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
/*
* -------------------------------------------------------------
*
* POSIX 1003.1-2001 Options
* =========================
*
* Options are normally set in <unistd.h>, which is not provided
* with pthreads-win32.
*
* For conformance with the Single Unix Specification (version 3), all of the
* options below are defined, and have a value of either -1 (not supported)
* or 200112L (supported).
*
* These options can neither be left undefined nor have a value of 0, because
* either indicates that sysconf(), which is not implemented, may be used at
* runtime to check the status of the option.
*
* _POSIX_THREADS (== 200112L)
* If == 200112L, you can use threads
*
* _POSIX_THREAD_ATTR_STACKSIZE (== 200112L)
* If == 200112L, you can control the size of a thread's
* stack
* pthread_attr_getstacksize
* pthread_attr_setstacksize
*
* _POSIX_THREAD_ATTR_STACKADDR (== -1)
* If == 200112L, you can allocate and control a thread's
* stack. If not supported, the following functions
* will return ENOSYS, indicating they are not
* supported:
* pthread_attr_getstackaddr
* pthread_attr_setstackaddr
*
* _POSIX_THREAD_PRIORITY_SCHEDULING (== -1)
* If == 200112L, you can use realtime scheduling.
* This option indicates that the behaviour of some
* implemented functions conforms to the additional TPS
* requirements in the standard. E.g. rwlocks favour
* writers over readers when threads have equal priority.
*
* _POSIX_THREAD_PRIO_INHERIT (== -1)
* If == 200112L, you can create priority inheritance
* mutexes.
* pthread_mutexattr_getprotocol +
* pthread_mutexattr_setprotocol +
*
* _POSIX_THREAD_PRIO_PROTECT (== -1)
* If == 200112L, you can create priority ceiling mutexes
* Indicates the availability of:
* pthread_mutex_getprioceiling
* pthread_mutex_setprioceiling
* pthread_mutexattr_getprioceiling
* pthread_mutexattr_getprotocol +
* pthread_mutexattr_setprioceiling
* pthread_mutexattr_setprotocol +
*
* _POSIX_THREAD_PROCESS_SHARED (== -1)
* If set, you can create mutexes and condition
* variables that can be shared with another
* process.If set, indicates the availability
* of:
* pthread_mutexattr_getpshared
* pthread_mutexattr_setpshared
* pthread_condattr_getpshared
* pthread_condattr_setpshared
*
* _POSIX_THREAD_SAFE_FUNCTIONS (== 200112L)
* If == 200112L you can use the special *_r library
* functions that provide thread-safe behaviour
*
* _POSIX_READER_WRITER_LOCKS (== 200112L)
* If == 200112L, you can use read/write locks
*
* _POSIX_SPIN_LOCKS (== 200112L)
* If == 200112L, you can use spin locks
*
* _POSIX_BARRIERS (== 200112L)
* If == 200112L, you can use barriers
*
* + These functions provide both 'inherit' and/or
* 'protect' protocol, based upon these macro
* settings.
*
* -------------------------------------------------------------
*/
/*
* POSIX Options
*/
#undef _POSIX_THREADS
#define _POSIX_THREADS 200112L
#undef _POSIX_READER_WRITER_LOCKS
#define _POSIX_READER_WRITER_LOCKS 200112L
#undef _POSIX_SPIN_LOCKS
#define _POSIX_SPIN_LOCKS 200112L
#undef _POSIX_BARRIERS
#define _POSIX_BARRIERS 200112L
#undef _POSIX_THREAD_SAFE_FUNCTIONS
#define _POSIX_THREAD_SAFE_FUNCTIONS 200112L
#undef _POSIX_THREAD_ATTR_STACKSIZE
#define _POSIX_THREAD_ATTR_STACKSIZE 200112L
/*
* The following options are not supported
*/
#undef _POSIX_THREAD_ATTR_STACKADDR
#define _POSIX_THREAD_ATTR_STACKADDR -1
#undef _POSIX_THREAD_PRIO_INHERIT
#define _POSIX_THREAD_PRIO_INHERIT -1
#undef _POSIX_THREAD_PRIO_PROTECT
#define _POSIX_THREAD_PRIO_PROTECT -1
/* TPS is not fully supported. */
#undef _POSIX_THREAD_PRIORITY_SCHEDULING
#define _POSIX_THREAD_PRIORITY_SCHEDULING -1
#undef _POSIX_THREAD_PROCESS_SHARED
#define _POSIX_THREAD_PROCESS_SHARED -1
/*
* POSIX 1003.1-2001 Limits
* ===========================
*
* These limits are normally set in <limits.h>, which is not provided with
* pthreads-win32.
*
* PTHREAD_DESTRUCTOR_ITERATIONS
* Maximum number of attempts to destroy
* a thread's thread-specific data on
* termination (must be at least 4)
*
* PTHREAD_KEYS_MAX
* Maximum number of thread-specific data keys
* available per process (must be at least 128)
*
* PTHREAD_STACK_MIN
* Minimum supported stack size for a thread
*
* PTHREAD_THREADS_MAX
* Maximum number of threads supported per
* process (must be at least 64).
*
* SEM_NSEMS_MAX
* The maximum number of semaphores a process can have.
* (must be at least 256)
*
* SEM_VALUE_MAX
* The maximum value a semaphore can have.
* (must be at least 32767)
*
*/
#undef _POSIX_THREAD_DESTRUCTOR_ITERATIONS
#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4
#undef PTHREAD_DESTRUCTOR_ITERATIONS
#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS
#undef _POSIX_THREAD_KEYS_MAX
#define _POSIX_THREAD_KEYS_MAX 128
#undef PTHREAD_KEYS_MAX
#define PTHREAD_KEYS_MAX _POSIX_THREAD_KEYS_MAX
#undef PTHREAD_STACK_MIN
#define PTHREAD_STACK_MIN 0
#undef _POSIX_THREAD_THREADS_MAX
#define _POSIX_THREAD_THREADS_MAX 64
/* Arbitrary value */
#undef PTHREAD_THREADS_MAX
#define PTHREAD_THREADS_MAX 2019
#undef _POSIX_SEM_NSEMS_MAX
#define _POSIX_SEM_NSEMS_MAX 256
/* Arbitrary value */
#undef SEM_NSEMS_MAX
#define SEM_NSEMS_MAX 1024
#undef _POSIX_SEM_VALUE_MAX
#define _POSIX_SEM_VALUE_MAX 32767
#undef SEM_VALUE_MAX
#define SEM_VALUE_MAX INT_MAX
#if __GNUC__ && ! defined (__declspec)
# error Please upgrade your GNU compiler to one that supports __declspec.
#endif
/*
* When building the DLL code, you should define PTW32_BUILD so that
* the variables/functions are exported correctly. When using the DLL,
* do NOT define PTW32_BUILD, and then the variables/functions will
* be imported correctly.
*/
#ifndef PTW32_STATIC_LIB
# ifdef PTW32_BUILD
# define PTW32_DLLPORT __declspec (dllexport)
# else
# define PTW32_DLLPORT __declspec (dllimport)
# endif
#else
# define PTW32_DLLPORT
#endif
/*
* The Open Watcom C/C++ compiler uses a non-standard calling convention
* that passes function args in registers unless __cdecl is explicitly specified
* in exposed function prototypes.
*
* We force all calls to cdecl even though this could slow Watcom code down
* slightly. If you know that the Watcom compiler will be used to build both
* the DLL and application, then you can probably define this as a null string.
* Remember that pthread.h (this file) is used for both the DLL and application builds.
*/
#define PTW32_CDECL __cdecl
#if defined(_UWIN) && PTW32_LEVEL >= PTW32_LEVEL_MAX
# include <sys/types.h>
#else
/*
* Generic handle type - intended to extend uniqueness beyond
* that available with a simple pointer. It should scale for either
* IA-32 or IA-64.
*/
typedef struct {
void * p; /* Pointer to actual object */
unsigned int x; /* Extra information - reuse count etc */
} ptw32_handle_t;
typedef ptw32_handle_t pthread_t;
typedef struct pthread_attr_t_ * pthread_attr_t;
typedef struct pthread_once_t_ pthread_once_t;
typedef struct pthread_key_t_ * pthread_key_t;
typedef struct pthread_mutex_t_ * pthread_mutex_t;
typedef struct pthread_mutexattr_t_ * pthread_mutexattr_t;
typedef struct pthread_cond_t_ * pthread_cond_t;
typedef struct pthread_condattr_t_ * pthread_condattr_t;
#endif
typedef struct pthread_rwlock_t_ * pthread_rwlock_t;
typedef struct pthread_rwlockattr_t_ * pthread_rwlockattr_t;
typedef struct pthread_spinlock_t_ * pthread_spinlock_t;
typedef struct pthread_barrier_t_ * pthread_barrier_t;
typedef struct pthread_barrierattr_t_ * pthread_barrierattr_t;
/*
* ====================
* ====================
* POSIX Threads
* ====================
* ====================
*/
enum {
/*
* pthread_attr_{get,set}detachstate
*/
PTHREAD_CREATE_JOINABLE = 0, /* Default */
PTHREAD_CREATE_DETACHED = 1,
/*
* pthread_attr_{get,set}inheritsched
*/
PTHREAD_INHERIT_SCHED = 0,
PTHREAD_EXPLICIT_SCHED = 1, /* Default */
/*
* pthread_{get,set}scope
*/
PTHREAD_SCOPE_PROCESS = 0,
PTHREAD_SCOPE_SYSTEM = 1, /* Default */
/*
* pthread_setcancelstate paramters
*/
PTHREAD_CANCEL_ENABLE = 0, /* Default */
PTHREAD_CANCEL_DISABLE = 1,
/*
* pthread_setcanceltype parameters
*/
PTHREAD_CANCEL_ASYNCHRONOUS = 0,
PTHREAD_CANCEL_DEFERRED = 1, /* Default */
/*
* pthread_mutexattr_{get,set}pshared
* pthread_condattr_{get,set}pshared
*/
PTHREAD_PROCESS_PRIVATE = 0,
PTHREAD_PROCESS_SHARED = 1,
/*
* pthread_barrier_wait
*/
PTHREAD_BARRIER_SERIAL_THREAD = -1
};
/*
* ====================
* ====================
* Cancelation
* ====================
* ====================
*/
#define PTHREAD_CANCELED ((void *) -1)
/*
* ====================
* ====================
* Once Key
* ====================
* ====================
*/
#define PTHREAD_ONCE_INIT { PTW32_FALSE, 0, 0, 0}
struct pthread_once_t_
{
int done; /* indicates if user function has been executed */
void * lock;
int reserved1;
int reserved2;
};
/*
* ====================
* ====================
* Object initialisers
* ====================
* ====================
*/
#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t) -1)
#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER ((pthread_mutex_t) -2)
#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER ((pthread_mutex_t) -3)
/*
* Compatibility with LinuxThreads
*/
#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER
#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP PTHREAD_ERRORCHECK_MUTEX_INITIALIZER
#define PTHREAD_COND_INITIALIZER ((pthread_cond_t) -1)
#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t) -1)
#define PTHREAD_SPINLOCK_INITIALIZER ((pthread_spinlock_t) -1)
/*
* Mutex types.
*/
enum
{
/* Compatibility with LinuxThreads */
PTHREAD_MUTEX_FAST_NP,
PTHREAD_MUTEX_RECURSIVE_NP,
PTHREAD_MUTEX_ERRORCHECK_NP,
PTHREAD_MUTEX_TIMED_NP = PTHREAD_MUTEX_FAST_NP,
PTHREAD_MUTEX_ADAPTIVE_NP = PTHREAD_MUTEX_FAST_NP,
/* For compatibility with POSIX */
PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_FAST_NP,
PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP,
PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP,
PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL
};
typedef struct ptw32_cleanup_t ptw32_cleanup_t;
#if defined(_MSC_VER)
/* Disable MSVC 'anachronism used' warning */
#pragma warning( disable : 4229 )
#endif
typedef void (* PTW32_CDECL ptw32_cleanup_callback_t)(void *);
#if defined(_MSC_VER)
#pragma warning( default : 4229 )
#endif
struct ptw32_cleanup_t
{
ptw32_cleanup_callback_t routine;
void *arg;
struct ptw32_cleanup_t *prev;
};
#ifdef __CLEANUP_SEH
/*
* WIN32 SEH version of cancel cleanup.
*/
#define pthread_cleanup_push( _rout, _arg ) \
{ \
ptw32_cleanup_t _cleanup; \
\
_cleanup.routine = (ptw32_cleanup_callback_t)(_rout); \
_cleanup.arg = (_arg); \
__try \
{ \
#define pthread_cleanup_pop( _execute ) \
} \
__finally \
{ \
if( _execute || AbnormalTermination()) \
{ \
(*(_cleanup.routine))( _cleanup.arg ); \
} \
} \
}
#else /* __CLEANUP_SEH */
#ifdef __CLEANUP_C
/*
* C implementation of PThreads cancel cleanup
*/
#define pthread_cleanup_push( _rout, _arg ) \
{ \
ptw32_cleanup_t _cleanup; \
\
ptw32_push_cleanup( &_cleanup, (ptw32_cleanup_callback_t) (_rout), (_arg) ); \
#define pthread_cleanup_pop( _execute ) \
(void) ptw32_pop_cleanup( _execute ); \
}
#else /* __CLEANUP_C */
#ifdef __CLEANUP_CXX
/*
* C++ version of cancel cleanup.
* - John E. Bossom.
*/
class PThreadCleanup {
/*
* PThreadCleanup
*
* Purpose
* This class is a C++ helper class that is
* used to implement pthread_cleanup_push/
* pthread_cleanup_pop.
* The destructor of this class automatically
* pops the pushed cleanup routine regardless
* of how the code exits the scope
* (i.e. such as by an exception)
*/
ptw32_cleanup_callback_t cleanUpRout;
void * obj;
int executeIt;
public:
PThreadCleanup() :
cleanUpRout( 0 ),
obj( 0 ),
executeIt( 0 )
/*
* No cleanup performed
*/
{
}
PThreadCleanup(
ptw32_cleanup_callback_t routine,
void * arg ) :
cleanUpRout( routine ),
obj( arg ),
executeIt( 1 )
/*
* Registers a cleanup routine for 'arg'
*/
{
}
~PThreadCleanup()
{
if ( executeIt && ((void *) cleanUpRout != (void *) 0) )
{
(void) (*cleanUpRout)( obj );
}
}
void execute( int exec )
{
executeIt = exec;
}
};
/*
* C++ implementation of PThreads cancel cleanup;
* This implementation takes advantage of a helper
* class who's destructor automatically calls the
* cleanup routine if we exit our scope weirdly
*/
#define pthread_cleanup_push( _rout, _arg ) \
{ \
PThreadCleanup cleanup((ptw32_cleanup_callback_t)(_rout), \
(void *) (_arg) );
#define pthread_cleanup_pop( _execute ) \
cleanup.execute( _execute ); \
}
#else
#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined.
#endif /* __CLEANUP_CXX */
#endif /* __CLEANUP_C */
#endif /* __CLEANUP_SEH */
/*
* ===============
* ===============
* Methods
* ===============
* ===============
*/
/*
* PThread Attribute Functions
*/
PTW32_DLLPORT int PTW32_CDECL pthread_attr_init (pthread_attr_t * attr);
PTW32_DLLPORT int PTW32_CDECL pthread_attr_destroy (pthread_attr_t * attr);
PTW32_DLLPORT int PTW32_CDECL pthread_attr_getdetachstate (const pthread_attr_t * attr,
int *detachstate);
PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstackaddr (const pthread_attr_t * attr,
void **stackaddr);
PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstacksize (const pthread_attr_t * attr,
size_t * stacksize);
PTW32_DLLPORT int PTW32_CDECL pthread_attr_setdetachstate (pthread_attr_t * attr,
int detachstate);
PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstackaddr (pthread_attr_t * attr,
void *stackaddr);
PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstacksize (pthread_attr_t * attr,
size_t stacksize);
PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedparam (const pthread_attr_t *attr,
struct sched_param *param);
PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedparam (pthread_attr_t *attr,
const struct sched_param *param);
PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedpolicy (pthread_attr_t *,
int);
PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedpolicy (pthread_attr_t *,
int *);
PTW32_DLLPORT int PTW32_CDECL pthread_attr_setinheritsched(pthread_attr_t * attr,
int inheritsched);
PTW32_DLLPORT int PTW32_CDECL pthread_attr_getinheritsched(pthread_attr_t * attr,
int * inheritsched);
PTW32_DLLPORT int PTW32_CDECL pthread_attr_setscope (pthread_attr_t *,
int);
PTW32_DLLPORT int PTW32_CDECL pthread_attr_getscope (const pthread_attr_t *,
int *);
/*
* PThread Functions
*/
PTW32_DLLPORT int PTW32_CDECL pthread_create (pthread_t * tid,
const pthread_attr_t * attr,
void *(*start) (void *),
void *arg);
PTW32_DLLPORT int PTW32_CDECL pthread_detach (pthread_t tid);
PTW32_DLLPORT int PTW32_CDECL pthread_equal (pthread_t t1,
pthread_t t2);
PTW32_DLLPORT void PTW32_CDECL pthread_exit (void *value_ptr);
PTW32_DLLPORT int PTW32_CDECL pthread_join (pthread_t thread,
void **value_ptr);
PTW32_DLLPORT pthread_t PTW32_CDECL pthread_self (void);
PTW32_DLLPORT int PTW32_CDECL pthread_cancel (pthread_t thread);
PTW32_DLLPORT int PTW32_CDECL pthread_setcancelstate (int state,
int *oldstate);
PTW32_DLLPORT int PTW32_CDECL pthread_setcanceltype (int type,
int *oldtype);
PTW32_DLLPORT void PTW32_CDECL pthread_testcancel (void);
PTW32_DLLPORT int PTW32_CDECL pthread_once (pthread_once_t * once_control,
void (*init_routine) (void));
#if PTW32_LEVEL >= PTW32_LEVEL_MAX
PTW32_DLLPORT ptw32_cleanup_t * PTW32_CDECL ptw32_pop_cleanup (int execute);
PTW32_DLLPORT void PTW32_CDECL ptw32_push_cleanup (ptw32_cleanup_t * cleanup,
void (*routine) (void *),
void *arg);
#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
/*
* Thread Specific Data Functions
*/
PTW32_DLLPORT int PTW32_CDECL pthread_key_create (pthread_key_t * key,
void (*destructor) (void *));
PTW32_DLLPORT int PTW32_CDECL pthread_key_delete (pthread_key_t key);
PTW32_DLLPORT int PTW32_CDECL pthread_setspecific (pthread_key_t key,
const void *value);
PTW32_DLLPORT void * PTW32_CDECL pthread_getspecific (pthread_key_t key);
/*
* Mutex Attribute Functions
*/
PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_init (pthread_mutexattr_t * attr);
PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_destroy (pthread_mutexattr_t * attr);
PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getpshared (const pthread_mutexattr_t
* attr,
int *pshared);
PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setpshared (pthread_mutexattr_t * attr,
int pshared);
PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind);
PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_gettype (pthread_mutexattr_t * attr, int *kind);
/*
* Barrier Attribute Functions
*/
PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_init (pthread_barrierattr_t * attr);
PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_destroy (pthread_barrierattr_t * attr);
PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_getpshared (const pthread_barrierattr_t
* attr,
int *pshared);
PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_setpshared (pthread_barrierattr_t * attr,
int pshared);
/*
* Mutex Functions
*/
PTW32_DLLPORT int PTW32_CDECL pthread_mutex_init (pthread_mutex_t * mutex,
const pthread_mutexattr_t * attr);
PTW32_DLLPORT int PTW32_CDECL pthread_mutex_destroy (pthread_mutex_t * mutex);
PTW32_DLLPORT int PTW32_CDECL pthread_mutex_lock (pthread_mutex_t * mutex);
PTW32_DLLPORT int PTW32_CDECL pthread_mutex_timedlock(pthread_mutex_t *mutex,
const struct timespec *abstime);
PTW32_DLLPORT int PTW32_CDECL pthread_mutex_trylock (pthread_mutex_t * mutex);
PTW32_DLLPORT int PTW32_CDECL pthread_mutex_unlock (pthread_mutex_t * mutex);
/*
* Spinlock Functions
*/
PTW32_DLLPORT int PTW32_CDECL pthread_spin_init (pthread_spinlock_t * lock, int pshared);
PTW32_DLLPORT int PTW32_CDECL pthread_spin_destroy (pthread_spinlock_t * lock);
PTW32_DLLPORT int PTW32_CDECL pthread_spin_lock (pthread_spinlock_t * lock);
PTW32_DLLPORT int PTW32_CDECL pthread_spin_trylock (pthread_spinlock_t * lock);
PTW32_DLLPORT int PTW32_CDECL pthread_spin_unlock (pthread_spinlock_t * lock);
/*
* Barrier Functions
*/
PTW32_DLLPORT int PTW32_CDECL pthread_barrier_init (pthread_barrier_t * barrier,
const pthread_barrierattr_t * attr,
unsigned int count);
PTW32_DLLPORT int PTW32_CDECL pthread_barrier_destroy (pthread_barrier_t * barrier);
PTW32_DLLPORT int PTW32_CDECL pthread_barrier_wait (pthread_barrier_t * barrier);
/*
* Condition Variable Attribute Functions
*/
PTW32_DLLPORT int PTW32_CDECL pthread_condattr_init (pthread_condattr_t * attr);
PTW32_DLLPORT int PTW32_CDECL pthread_condattr_destroy (pthread_condattr_t * attr);
PTW32_DLLPORT int PTW32_CDECL pthread_condattr_getpshared (const pthread_condattr_t * attr,
int *pshared);
PTW32_DLLPORT int PTW32_CDECL pthread_condattr_setpshared (pthread_condattr_t * attr,
int pshared);
/*
* Condition Variable Functions
*/
PTW32_DLLPORT int PTW32_CDECL pthread_cond_init (pthread_cond_t * cond,
const pthread_condattr_t * attr);
PTW32_DLLPORT int PTW32_CDECL pthread_cond_destroy (pthread_cond_t * cond);
PTW32_DLLPORT int PTW32_CDECL pthread_cond_wait (pthread_cond_t * cond,
pthread_mutex_t * mutex);
PTW32_DLLPORT int PTW32_CDECL pthread_cond_timedwait (pthread_cond_t * cond,
pthread_mutex_t * mutex,
const struct timespec *abstime);
PTW32_DLLPORT int PTW32_CDECL pthread_cond_signal (pthread_cond_t * cond);
PTW32_DLLPORT int PTW32_CDECL pthread_cond_broadcast (pthread_cond_t * cond);
/*
* Scheduling
*/
PTW32_DLLPORT int PTW32_CDECL pthread_setschedparam (pthread_t thread,
int policy,
const struct sched_param *param);
PTW32_DLLPORT int PTW32_CDECL pthread_getschedparam (pthread_t thread,
int *policy,
struct sched_param *param);
PTW32_DLLPORT int PTW32_CDECL pthread_setconcurrency (int);
PTW32_DLLPORT int PTW32_CDECL pthread_getconcurrency (void);
/*
* Read-Write Lock Functions
*/
PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_init(pthread_rwlock_t *lock,
const pthread_rwlockattr_t *attr);
PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_destroy(pthread_rwlock_t *lock);
PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_tryrdlock(pthread_rwlock_t *);
PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_trywrlock(pthread_rwlock_t *);
PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_rdlock(pthread_rwlock_t *lock);
PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedrdlock(pthread_rwlock_t *lock,
const struct timespec *abstime);
PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_wrlock(pthread_rwlock_t *lock);
PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedwrlock(pthread_rwlock_t *lock,
const struct timespec *abstime);
PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_unlock(pthread_rwlock_t *lock);
PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_init (pthread_rwlockattr_t * attr);
PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr);
PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr,
int *pshared);
PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr,
int pshared);
#if PTW32_LEVEL >= PTW32_LEVEL_MAX - 1
/*
* Signal Functions. Should be defined in <signal.h> but MSVC and MinGW32
* already have signal.h that don't define these.
*/
PTW32_DLLPORT int PTW32_CDECL pthread_kill(pthread_t thread, int sig);
/*
* Non-portable functions
*/
/*
* Compatibility with Linux.
*/
PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr,
int kind);
PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr,
int *kind);
/*
* Possibly supported by other POSIX threads implementations
*/
PTW32_DLLPORT int PTW32_CDECL pthread_delay_np (struct timespec * interval);
PTW32_DLLPORT int PTW32_CDECL pthread_num_processors_np(void);
/*
* Useful if an application wants to statically link
* the lib rather than load the DLL at run-time.
*/
PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_attach_np(void);
PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_detach_np(void);
PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_attach_np(void);
PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_detach_np(void);
/*
* Features that are auto-detected at load/run time.
*/
PTW32_DLLPORT int PTW32_CDECL pthread_win32_test_features_np(int);
enum ptw32_features {
PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE = 0x0001, /* System provides it. */
PTW32_ALERTABLE_ASYNC_CANCEL = 0x0002 /* Can cancel blocked threads. */
};
/*
* Register a system time change with the library.
* Causes the library to perform various functions
* in response to the change. Should be called whenever
* the application's top level window receives a
* WM_TIMECHANGE message. It can be passed directly to
* pthread_create() as a new thread if desired.
*/
PTW32_DLLPORT void * PTW32_CDECL pthread_timechange_handler_np(void *);
#endif /*PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 */
#if PTW32_LEVEL >= PTW32_LEVEL_MAX
/*
* Returns the Win32 HANDLE for the POSIX thread.
*/
PTW32_DLLPORT HANDLE PTW32_CDECL pthread_getw32threadhandle_np(pthread_t thread);
/*
* Protected Methods
*
* This function blocks until the given WIN32 handle
* is signaled or pthread_cancel had been called.
* This function allows the caller to hook into the
* PThreads cancel mechanism. It is implemented using
*
* WaitForMultipleObjects
*
* on 'waitHandle' and a manually reset WIN32 Event
* used to implement pthread_cancel. The 'timeout'
* argument to TimedWait is simply passed to
* WaitForMultipleObjects.
*/
PTW32_DLLPORT int PTW32_CDECL pthreadCancelableWait (HANDLE waitHandle);
PTW32_DLLPORT int PTW32_CDECL pthreadCancelableTimedWait (HANDLE waitHandle,
DWORD timeout);
#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
/*
* Thread-Safe C Runtime Library Mappings.
*/
#ifndef _UWIN
# if defined(NEED_ERRNO)
PTW32_DLLPORT int * PTW32_CDECL _errno( void );
# else
# ifndef errno
# if (defined(_MT) || defined(_DLL))
__declspec(dllimport) extern int * __cdecl _errno(void);
# define errno (*_errno())
# endif
# endif
# endif
#endif
/*
* WIN32 C runtime library had been made thread-safe
* without affecting the user interface. Provide
* mappings from the UNIX thread-safe versions to
* the standard C runtime library calls.
* Only provide function mappings for functions that
* actually exist on WIN32.
*/
#if !defined(__MINGW32__)
#define strtok_r( _s, _sep, _lasts ) \
( *(_lasts) = strtok( (_s), (_sep) ) )
#endif /* !__MINGW32__ */
#define asctime_r( _tm, _buf ) \
( strcpy( (_buf), asctime( (_tm) ) ), \
(_buf) )
#define ctime_r( _clock, _buf ) \
( strcpy( (_buf), ctime( (_clock) ) ), \
(_buf) )
#define gmtime_r( _clock, _result ) \
( *(_result) = *gmtime( (_clock) ), \
(_result) )
#define localtime_r( _clock, _result ) \
( *(_result) = *localtime( (_clock) ), \
(_result) )
#define rand_r( _seed ) \
( _seed == _seed? rand() : rand() )
/*
* Some compiler environments don't define some things.
*/
#if defined(__BORLANDC__)
# define _ftime ftime
# define _timeb timeb
#endif
#ifdef __cplusplus
/*
* Internal exceptions
*/
class ptw32_exception {};
class ptw32_exception_cancel : public ptw32_exception {};
class ptw32_exception_exit : public ptw32_exception {};
#endif
#if PTW32_LEVEL >= PTW32_LEVEL_MAX
/* FIXME: This is only required if the library was built using SEH */
/*
* Get internal SEH tag
*/
PTW32_DLLPORT DWORD PTW32_CDECL ptw32_get_exception_services_code(void);
#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
#ifndef PTW32_BUILD
#ifdef __CLEANUP_SEH
/*
* Redefine the SEH __except keyword to ensure that applications
* propagate our internal exceptions up to the library's internal handlers.
*/
#define __except( E ) \
__except( ( GetExceptionCode() == ptw32_get_exception_services_code() ) \
? EXCEPTION_CONTINUE_SEARCH : ( E ) )
#endif /* __CLEANUP_SEH */
#ifdef __CLEANUP_CXX
/*
* Redefine the C++ catch keyword to ensure that applications
* propagate our internal exceptions up to the library's internal handlers.
*/
#ifdef _MSC_VER
/*
* WARNING: Replace any 'catch( ... )' with 'PtW32CatchAll'
* if you want Pthread-Win32 cancelation and pthread_exit to work.
*/
#ifndef PtW32NoCatchWarn
#pragma message("Specify \"/DPtW32NoCatchWarn\" compiler flag to skip this message.")
#pragma message("------------------------------------------------------------------")
#pragma message("When compiling applications with MSVC++ and C++ exception handling:")
#pragma message(" Replace any 'catch( ... )' in routines called from POSIX threads")
#pragma message(" with 'PtW32CatchAll' or 'CATCHALL' if you want POSIX thread")
#pragma message(" cancelation and pthread_exit to work. For example:")
#pragma message("")
#pragma message(" #ifdef PtW32CatchAll")
#pragma message(" PtW32CatchAll")
#pragma message(" #else")
#pragma message(" catch(...)")
#pragma message(" #endif")
#pragma message(" {")
#pragma message(" /* Catchall block processing */")
#pragma message(" }")
#pragma message("------------------------------------------------------------------")
#endif
#define PtW32CatchAll \
catch( ptw32_exception & ) { throw; } \
catch( ... )
#else /* _MSC_VER */
#define catch( E ) \
catch( ptw32_exception & ) { throw; } \
catch( E )
#endif /* _MSC_VER */
#endif /* __CLEANUP_CXX */
#endif /* ! PTW32_BUILD */
#ifdef __cplusplus
} /* End of extern "C" */
#endif /* __cplusplus */
#ifdef PTW32__HANDLE_DEF
# undef HANDLE
#endif
#ifdef PTW32__DWORD_DEF
# undef DWORD
#endif
#undef PTW32_LEVEL
#undef PTW32_LEVEL_MAX
#endif /* ! RC_INVOKED */
#endif /* PTHREAD_H */