New upstream version 8.1.0

This commit is contained in:
geos_one
2025-08-10 01:34:16 +02:00
commit c891bb7105
4398 changed files with 838833 additions and 0 deletions

23
thirdparty/build/Makefile vendored Normal file
View File

@@ -0,0 +1,23 @@
SHELL := /bin/bash
SOURCE_PATH = $(shell echo `pwd`/../source )
BUILD_PATH = $(shell echo `pwd` )
BUILDTYPE = $(shell `pwd`/get-build-type.sh)
FINDBUGS_HOME = $(shell echo `pwd`/../source/findbugs)
# note: cppunit not included in "all" by default, because we prefer system lib by default
all: gtest
GTEST_DIR = ../source/gtest/googletest
GTEST_SRC = $(GTEST_DIR)/src/gtest-all.cc $(GTEST_DIR)/src/gtest_main.cc
libgtest.a: $(GTEST_SRC)
$(CXX) -fPIC -isystem $(GTEST_DIR)/include -I$(GTEST_DIR) -pthread -c $^
$(AR) -r libgtest.a gtest-all.o gtest_main.o
gtest: libgtest.a
clean:
rm -f gtest-all.o gtest_main.o libgtest.a

28
thirdparty/build/get-build-type.sh vendored Executable file
View File

@@ -0,0 +1,28 @@
#!/bin/bash
# Print the build type suitable to be used for autoconf
# we need this for cppunit and tilera architechture
# ./configure --build the-build-type
# on success print the build type and exit
print_build_type()
{
cmd="$@"
build_type=`eval $cmd 2>/dev/null`
if [ $? -eq 0 ]; then
echo --build $build_type
exit 0
fi
}
# try rpm first
print_build_type "rpm --eval %{_host}"
# rpm failed, now dpkg
print_build_type "dpkg-architecture -qDEB_BUILD_GNU_TYPE"
# unknown build type
exit 1

1
thirdparty/source/boost vendored Symbolic link
View File

@@ -0,0 +1 @@
boost_1_61_0

291
thirdparty/source/boost_1_61_0/Jamroot vendored Normal file
View File

@@ -0,0 +1,291 @@
# Copyright Vladimir Prus 2002-2006.
# Copyright Dave Abrahams 2005-2006.
# Copyright Rene Rivera 2005-2007.
# Copyright Douglas Gregor 2005.
#
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
# Usage:
#
# b2 [options] [properties] [install|stage]
#
# Builds and installs Boost.
#
# Targets and Related Options:
#
# install Install headers and compiled library files to the
# ======= configured locations (below).
#
# --prefix=<PREFIX> Install architecture independent files here.
# Default; C:\Boost on Win32
# Default; /usr/local on Unix. Linux, etc.
#
# --exec-prefix=<EPREFIX> Install architecture dependent files here.
# Default; <PREFIX>
#
# --libdir=<DIR> Install library files here.
# Default; <EPREFIX>/lib
#
# --includedir=<HDRDIR> Install header files here.
# Default; <PREFIX>/include
#
# stage Build and install only compiled library files to the
# ===== stage directory.
#
# --stagedir=<STAGEDIR> Install library files here
# Default; ./stage
#
# Other Options:
#
# --build-type=<type> Build the specified pre-defined set of variations of
# the libraries. Note, that which variants get built
# depends on what each library supports.
#
# -- minimal -- (default) Builds a minimal set of
# variants. On Windows, these are static
# multithreaded libraries in debug and release
# modes, using shared runtime. On Linux, these are
# static and shared multithreaded libraries in
# release mode.
#
# -- complete -- Build all possible variations.
#
# --build-dir=DIR Build in this location instead of building within
# the distribution tree. Recommended!
#
# --show-libraries Display the list of Boost libraries that require
# build and installation steps, and then exit.
#
# --layout=<layout> Determine whether to choose library names and header
# locations such that multiple versions of Boost or
# multiple compilers can be used on the same system.
#
# -- versioned -- Names of boost binaries include
# the Boost version number, name and version of
# the compiler and encoded build properties. Boost
# headers are installed in a subdirectory of
# <HDRDIR> whose name contains the Boost version
# number.
#
# -- tagged -- Names of boost binaries include the
# encoded build properties such as variant and
# threading, but do not including compiler name
# and version, or Boost version. This option is
# useful if you build several variants of Boost,
# using the same compiler.
#
# -- system -- Binaries names do not include the
# Boost version number or the name and version
# number of the compiler. Boost headers are
# installed directly into <HDRDIR>. This option is
# intended for system integrators building
# distribution packages.
#
# The default value is 'versioned' on Windows, and
# 'system' on Unix.
#
# --buildid=ID Add the specified ID to the name of built libraries.
# The default is to not add anything.
#
# --python-buildid=ID Add the specified ID to the name of built libraries
# that depend on Python. The default is to not add
# anything. This ID is added in addition to --buildid.
#
# --help This message.
#
# --with-<library> Build and install the specified <library>. If this
# option is used, only libraries specified using this
# option will be built.
#
# --without-<library> Do not build, stage, or install the specified
# <library>. By default, all libraries are built.
#
# Properties:
#
# toolset=toolset Indicate the toolset to build with.
#
# variant=debug|release Select the build variant
#
# link=static|shared Whether to build static or shared libraries
#
# threading=single|multi Whether to build single or multithreaded binaries
#
# runtime-link=static|shared
# Whether to link to static or shared C and C++
# runtime.
#
# TODO:
# - handle boost version
# - handle python options such as pydebug
import boostcpp ;
import package ;
import sequence ;
import xsltproc ;
import set ;
import path ;
import link ;
path-constant BOOST_ROOT : . ;
constant BOOST_VERSION : 1.61.0 ;
constant BOOST_JAMROOT_MODULE : $(__name__) ;
boostcpp.set-version $(BOOST_VERSION) ;
use-project /boost/architecture : libs/config/checks/architecture ;
local all-headers =
[ MATCH .*libs/(.*)/include/boost : [ glob libs/*/include/boost libs/*/*/include/boost ] ] ;
for dir in $(all-headers)
{
link-directory $(dir)-headers : libs/$(dir)/include/boost : <location>. ;
explicit $(dir)-headers ;
}
if $(all-headers)
{
constant BOOST_MODULARLAYOUT : $(all-headers) ;
}
project boost
: requirements <include>.
[ boostcpp.architecture ]
[ boostcpp.address-model ]
# Disable auto-linking for all targets here, primarily because it caused
# troubles with V2.
<define>BOOST_ALL_NO_LIB=1
# Used to encode variant in target name. See the 'tag' rule below.
<tag>@$(__name__).tag
<conditional>@handle-static-runtime
# Comeau does not support shared lib
<toolset>como:<link>static
<toolset>como-linux:<define>_GNU_SOURCE=1
# When building docs within Boost, we want the standard Boost style
<xsl:param>boost.defaults=Boost
: usage-requirements <include>.
: build-dir bin.v2
;
# This rule is called by Boost.Build to determine the name of target. We use it
# to encode the build variant, compiler name and boost version in the target
# name.
#
rule tag ( name : type ? : property-set )
{
return [ boostcpp.tag $(name) : $(type) : $(property-set) ] ;
}
rule handle-static-runtime ( properties * )
{
# Using static runtime with shared libraries is impossible on Linux, and
# dangerous on Windows. Therefore, we disallow it. This might be drastic,
# but it was disabled for a while without anybody complaining.
# For CW, static runtime is needed so that std::locale works.
if <link>shared in $(properties) && <runtime-link>static in $(properties) &&
! ( <toolset>cw in $(properties) )
{
ECHO "error: link=shared together with runtime-link=static is not allowed" ;
ECHO "error: such property combination is either impossible " ;
ECHO "error: or too dangerious to be of any use" ;
EXIT ;
}
}
all-libraries = [ MATCH .*libs/(.*)/build/.* : [ glob libs/*/build/Jamfile.v2 ]
[ glob libs/*/build/Jamfile ] ] ;
all-libraries = [ sequence.unique $(all-libraries) ] ;
# The function_types library has a Jamfile, but it's used for maintenance
# purposes, there's no library to build and install.
all-libraries = [ set.difference $(all-libraries) : function_types ] ;
# Setup convenient aliases for all libraries.
local rule explicit-alias ( id : targets + )
{
alias $(id) : $(targets) ;
explicit $(id) ;
}
# First, the complicated libraries: where the target name in Jamfile is
# different from its directory name.
explicit-alias prg_exec_monitor : libs/test/build//boost_prg_exec_monitor ;
explicit-alias test_exec_monitor : libs/test/build//boost_test_exec_monitor ;
explicit-alias unit_test_framework : libs/test/build//boost_unit_test_framework ;
explicit-alias bgl-vis : libs/graps/build//bgl-vis ;
explicit-alias serialization : libs/serialization/build//boost_serialization ;
explicit-alias wserialization : libs/serialization/build//boost_wserialization ;
for local l in $(all-libraries)
{
if ! $(l) in test graph serialization
{
explicit-alias $(l) : libs/$(l)/build//boost_$(l) ;
}
}
# Log has an additional target
explicit-alias log_setup : libs/log/build//boost_log_setup ;
alias headers : $(all-headers)-headers : : : <include>. ;
explicit headers ;
# Make project ids of all libraries known.
for local l in $(all-libraries)
{
use-project /boost/$(l) : libs/$(l)/build ;
}
if [ path.exists $(BOOST_ROOT)/tools/inspect ]
{
use-project /boost/tools/inspect : tools/inspect/build ;
}
if [ path.exists $(BOOST_ROOT)/libs/wave/tool ]
{
use-project /boost/libs/wave/tool : libs/wave/tool/build ;
}
# This rule should be called from libraries' Jamfiles and will create two
# targets, "install" and "stage", that will install or stage that library. The
# --prefix option is respected, but --with and --without options, naturally, are
# ignored.
#
# - libraries -- list of library targets to install.
#
rule boost-install ( libraries * )
{
package.install install
: <dependency>/boost//install-proper-headers $(install-requirements)
: # No binaries
: $(libraries)
: # No headers, it is handled by the dependency.
;
install stage : $(libraries) : <location>$(BOOST_STAGE_LOCATE) ;
module [ CALLER_MODULE ]
{
explicit stage ;
explicit install ;
}
}
headers =
# The .SUNWCCh files are present in tr1 include directory and have to be
# installed (see http://lists.boost.org/Archives/boost/2007/05/121430.php).
[ path.glob-tree $(BOOST_ROOT)/boost : *.hpp *.ipp *.h *.inc *.SUNWCCh : CVS .svn ]
[ path.glob-tree $(BOOST_ROOT)/boost/compatibility/cpp_c_headers : c* : CVS .svn ]
[ path.glob boost/tr1/tr1 : * : bcc32 sun CVS .svn ]
;
# Declare special top-level targets that build and install the desired variants
# of the libraries.
boostcpp.declare-targets $(all-libraries) : $(headers) ;

View File

@@ -0,0 +1,23 @@
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

BIN
thirdparty/source/boost_1_61_0/boost.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@@ -0,0 +1,86 @@
/*
Copyright (c) Marshall Clow 2008-2012.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
/// \file all_of.hpp
/// \brief Test ranges to see if all elements match a value or predicate.
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_ALL_OF_HPP
#define BOOST_ALGORITHM_ALL_OF_HPP
#include <algorithm> // for std::all_of, if available
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
namespace boost { namespace algorithm {
/// \fn all_of ( InputIterator first, InputIterator last, Predicate p )
/// \return true if all elements in [first, last) satisfy the predicate 'p'
/// \note returns true on an empty range
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param p A predicate for testing the elements of the sequence
///
/// \note This function is part of the C++2011 standard library.
/// We will use the standard one if it is available,
/// otherwise we have our own implementation.
template<typename InputIterator, typename Predicate>
bool all_of ( InputIterator first, InputIterator last, Predicate p )
{
for ( ; first != last; ++first )
if ( !p(*first))
return false;
return true;
}
/// \fn all_of ( const Range &r, Predicate p )
/// \return true if all elements in the range satisfy the predicate 'p'
/// \note returns true on an empty range
///
/// \param r The input range
/// \param p A predicate for testing the elements of the range
///
template<typename Range, typename Predicate>
bool all_of ( const Range &r, Predicate p )
{
return boost::algorithm::all_of ( boost::begin (r), boost::end (r), p );
}
/// \fn all_of_equal ( InputIterator first, InputIterator last, const T &val )
/// \return true if all elements in [first, last) are equal to 'val'
/// \note returns true on an empty range
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param val A value to compare against
///
template<typename InputIterator, typename T>
bool all_of_equal ( InputIterator first, InputIterator last, const T &val )
{
for ( ; first != last; ++first )
if ( val != *first )
return false;
return true;
}
/// \fn all_of_equal ( const Range &r, const T &val )
/// \return true if all elements in the range are equal to 'val'
/// \note returns true on an empty range
///
/// \param r The input range
/// \param val A value to compare against
///
template<typename Range, typename T>
bool all_of_equal ( const Range &r, const T &val )
{
return boost::algorithm::all_of_equal ( boost::begin (r), boost::end (r), val );
}
}} // namespace boost and algorithm
#endif // BOOST_ALGORITHM_ALL_OF_HPP

View File

@@ -0,0 +1,31 @@
// Boost string_algo library string_algo.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2004.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_ALGO_HPP
#define BOOST_STRING_ALGO_HPP
/*! \file
Cumulative include for string_algo library
*/
#include <boost/algorithm/string/std_containers_traits.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/find.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/join.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/erase.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/find_iterator.hpp>
#endif // BOOST_STRING_ALGO_HPP

View File

@@ -0,0 +1,176 @@
// Boost string_algo library case_conv.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_CASE_CONV_HPP
#define BOOST_STRING_CASE_CONV_HPP
#include <boost/algorithm/string/config.hpp>
#include <algorithm>
#include <locale>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/range/as_literal.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/value_type.hpp>
#include <boost/algorithm/string/detail/case_conv.hpp>
/*! \file
Defines sequence case-conversion algorithms.
Algorithms convert each element in the input sequence to the
desired case using provided locales.
*/
namespace boost {
namespace algorithm {
// to_lower -----------------------------------------------//
//! Convert to lower case
/*!
Each element of the input sequence is converted to lower
case. The result is a copy of the input converted to lower case.
It is returned as a sequence or copied to the output iterator.
\param Output An output iterator to which the result will be copied
\param Input An input range
\param Loc A locale used for conversion
\return
An output iterator pointing just after the last inserted character or
a copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<typename OutputIteratorT, typename RangeT>
inline OutputIteratorT
to_lower_copy(
OutputIteratorT Output,
const RangeT& Input,
const std::locale& Loc=std::locale())
{
return ::boost::algorithm::detail::transform_range_copy(
Output,
::boost::as_literal(Input),
::boost::algorithm::detail::to_lowerF<
typename range_value<RangeT>::type >(Loc));
}
//! Convert to lower case
/*!
\overload
*/
template<typename SequenceT>
inline SequenceT to_lower_copy(
const SequenceT& Input,
const std::locale& Loc=std::locale())
{
return ::boost::algorithm::detail::transform_range_copy<SequenceT>(
Input,
::boost::algorithm::detail::to_lowerF<
typename range_value<SequenceT>::type >(Loc));
}
//! Convert to lower case
/*!
Each element of the input sequence is converted to lower
case. The input sequence is modified in-place.
\param Input A range
\param Loc a locale used for conversion
*/
template<typename WritableRangeT>
inline void to_lower(
WritableRangeT& Input,
const std::locale& Loc=std::locale())
{
::boost::algorithm::detail::transform_range(
::boost::as_literal(Input),
::boost::algorithm::detail::to_lowerF<
typename range_value<WritableRangeT>::type >(Loc));
}
// to_upper -----------------------------------------------//
//! Convert to upper case
/*!
Each element of the input sequence is converted to upper
case. The result is a copy of the input converted to upper case.
It is returned as a sequence or copied to the output iterator
\param Output An output iterator to which the result will be copied
\param Input An input range
\param Loc A locale used for conversion
\return
An output iterator pointing just after the last inserted character or
a copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<typename OutputIteratorT, typename RangeT>
inline OutputIteratorT
to_upper_copy(
OutputIteratorT Output,
const RangeT& Input,
const std::locale& Loc=std::locale())
{
return ::boost::algorithm::detail::transform_range_copy(
Output,
::boost::as_literal(Input),
::boost::algorithm::detail::to_upperF<
typename range_value<RangeT>::type >(Loc));
}
//! Convert to upper case
/*!
\overload
*/
template<typename SequenceT>
inline SequenceT to_upper_copy(
const SequenceT& Input,
const std::locale& Loc=std::locale())
{
return ::boost::algorithm::detail::transform_range_copy<SequenceT>(
Input,
::boost::algorithm::detail::to_upperF<
typename range_value<SequenceT>::type >(Loc));
}
//! Convert to upper case
/*!
Each element of the input sequence is converted to upper
case. The input sequence is modified in-place.
\param Input An input range
\param Loc a locale used for conversion
*/
template<typename WritableRangeT>
inline void to_upper(
WritableRangeT& Input,
const std::locale& Loc=std::locale())
{
::boost::algorithm::detail::transform_range(
::boost::as_literal(Input),
::boost::algorithm::detail::to_upperF<
typename range_value<WritableRangeT>::type >(Loc));
}
} // namespace algorithm
// pull names to the boost namespace
using algorithm::to_lower;
using algorithm::to_lower_copy;
using algorithm::to_upper;
using algorithm::to_upper_copy;
} // namespace boost
#endif // BOOST_STRING_CASE_CONV_HPP

View File

@@ -0,0 +1,312 @@
// Boost string_algo library classification.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_CLASSIFICATION_HPP
#define BOOST_STRING_CLASSIFICATION_HPP
#include <algorithm>
#include <locale>
#include <boost/range/value_type.hpp>
#include <boost/range/as_literal.hpp>
#include <boost/algorithm/string/detail/classification.hpp>
#include <boost/algorithm/string/predicate_facade.hpp>
/*! \file
Classification predicates are included in the library to give
some more convenience when using algorithms like \c trim() and \c all().
They wrap functionality of STL classification functions ( e.g. \c std::isspace() )
into generic functors.
*/
namespace boost {
namespace algorithm {
// classification functor generator -------------------------------------//
//! is_classified predicate
/*!
Construct the \c is_classified predicate. This predicate holds if the input is
of specified \c std::ctype category.
\param Type A \c std::ctype category
\param Loc A locale used for classification
\return An instance of the \c is_classified predicate
*/
inline detail::is_classifiedF
is_classified(std::ctype_base::mask Type, const std::locale& Loc=std::locale())
{
return detail::is_classifiedF(Type, Loc);
}
//! is_space predicate
/*!
Construct the \c is_classified predicate for the \c ctype_base::space category.
\param Loc A locale used for classification
\return An instance of the \c is_classified predicate
*/
inline detail::is_classifiedF
is_space(const std::locale& Loc=std::locale())
{
return detail::is_classifiedF(std::ctype_base::space, Loc);
}
//! is_alnum predicate
/*!
Construct the \c is_classified predicate for the \c ctype_base::alnum category.
\param Loc A locale used for classification
\return An instance of the \c is_classified predicate
*/
inline detail::is_classifiedF
is_alnum(const std::locale& Loc=std::locale())
{
return detail::is_classifiedF(std::ctype_base::alnum, Loc);
}
//! is_alpha predicate
/*!
Construct the \c is_classified predicate for the \c ctype_base::alpha category.
\param Loc A locale used for classification
\return An instance of the \c is_classified predicate
*/
inline detail::is_classifiedF
is_alpha(const std::locale& Loc=std::locale())
{
return detail::is_classifiedF(std::ctype_base::alpha, Loc);
}
//! is_cntrl predicate
/*!
Construct the \c is_classified predicate for the \c ctype_base::cntrl category.
\param Loc A locale used for classification
\return An instance of the \c is_classified predicate
*/
inline detail::is_classifiedF
is_cntrl(const std::locale& Loc=std::locale())
{
return detail::is_classifiedF(std::ctype_base::cntrl, Loc);
}
//! is_digit predicate
/*!
Construct the \c is_classified predicate for the \c ctype_base::digit category.
\param Loc A locale used for classification
\return An instance of the \c is_classified predicate
*/
inline detail::is_classifiedF
is_digit(const std::locale& Loc=std::locale())
{
return detail::is_classifiedF(std::ctype_base::digit, Loc);
}
//! is_graph predicate
/*!
Construct the \c is_classified predicate for the \c ctype_base::graph category.
\param Loc A locale used for classification
\return An instance of the \c is_classified predicate
*/
inline detail::is_classifiedF
is_graph(const std::locale& Loc=std::locale())
{
return detail::is_classifiedF(std::ctype_base::graph, Loc);
}
//! is_lower predicate
/*!
Construct the \c is_classified predicate for the \c ctype_base::lower category.
\param Loc A locale used for classification
\return An instance of \c is_classified predicate
*/
inline detail::is_classifiedF
is_lower(const std::locale& Loc=std::locale())
{
return detail::is_classifiedF(std::ctype_base::lower, Loc);
}
//! is_print predicate
/*!
Construct the \c is_classified predicate for the \c ctype_base::print category.
\param Loc A locale used for classification
\return An instance of the \c is_classified predicate
*/
inline detail::is_classifiedF
is_print(const std::locale& Loc=std::locale())
{
return detail::is_classifiedF(std::ctype_base::print, Loc);
}
//! is_punct predicate
/*!
Construct the \c is_classified predicate for the \c ctype_base::punct category.
\param Loc A locale used for classification
\return An instance of the \c is_classified predicate
*/
inline detail::is_classifiedF
is_punct(const std::locale& Loc=std::locale())
{
return detail::is_classifiedF(std::ctype_base::punct, Loc);
}
//! is_upper predicate
/*!
Construct the \c is_classified predicate for the \c ctype_base::upper category.
\param Loc A locale used for classification
\return An instance of the \c is_classified predicate
*/
inline detail::is_classifiedF
is_upper(const std::locale& Loc=std::locale())
{
return detail::is_classifiedF(std::ctype_base::upper, Loc);
}
//! is_xdigit predicate
/*!
Construct the \c is_classified predicate for the \c ctype_base::xdigit category.
\param Loc A locale used for classification
\return An instance of the \c is_classified predicate
*/
inline detail::is_classifiedF
is_xdigit(const std::locale& Loc=std::locale())
{
return detail::is_classifiedF(std::ctype_base::xdigit, Loc);
}
//! is_any_of predicate
/*!
Construct the \c is_any_of predicate. The predicate holds if the input
is included in the specified set of characters.
\param Set A set of characters to be recognized
\return An instance of the \c is_any_of predicate
*/
template<typename RangeT>
inline detail::is_any_ofF<
BOOST_STRING_TYPENAME range_value<RangeT>::type>
is_any_of( const RangeT& Set )
{
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> lit_set(boost::as_literal(Set));
return detail::is_any_ofF<BOOST_STRING_TYPENAME range_value<RangeT>::type>(lit_set);
}
//! is_from_range predicate
/*!
Construct the \c is_from_range predicate. The predicate holds if the input
is included in the specified range. (i.e. From <= Ch <= To )
\param From The start of the range
\param To The end of the range
\return An instance of the \c is_from_range predicate
*/
template<typename CharT>
inline detail::is_from_rangeF<CharT> is_from_range(CharT From, CharT To)
{
return detail::is_from_rangeF<CharT>(From,To);
}
// predicate combinators ---------------------------------------------------//
//! predicate 'and' composition predicate
/*!
Construct the \c class_and predicate. This predicate can be used
to logically combine two classification predicates. \c class_and holds,
if both predicates return true.
\param Pred1 The first predicate
\param Pred2 The second predicate
\return An instance of the \c class_and predicate
*/
template<typename Pred1T, typename Pred2T>
inline detail::pred_andF<Pred1T, Pred2T>
operator&&(
const predicate_facade<Pred1T>& Pred1,
const predicate_facade<Pred2T>& Pred2 )
{
// Doing the static_cast with the pointer instead of the reference
// is a workaround for some compilers which have problems with
// static_cast's of template references, i.e. CW8. /grafik/
return detail::pred_andF<Pred1T,Pred2T>(
*static_cast<const Pred1T*>(&Pred1),
*static_cast<const Pred2T*>(&Pred2) );
}
//! predicate 'or' composition predicate
/*!
Construct the \c class_or predicate. This predicate can be used
to logically combine two classification predicates. \c class_or holds,
if one of the predicates return true.
\param Pred1 The first predicate
\param Pred2 The second predicate
\return An instance of the \c class_or predicate
*/
template<typename Pred1T, typename Pred2T>
inline detail::pred_orF<Pred1T, Pred2T>
operator||(
const predicate_facade<Pred1T>& Pred1,
const predicate_facade<Pred2T>& Pred2 )
{
// Doing the static_cast with the pointer instead of the reference
// is a workaround for some compilers which have problems with
// static_cast's of template references, i.e. CW8. /grafik/
return detail::pred_orF<Pred1T,Pred2T>(
*static_cast<const Pred1T*>(&Pred1),
*static_cast<const Pred2T*>(&Pred2));
}
//! predicate negation operator
/*!
Construct the \c class_not predicate. This predicate represents a negation.
\c class_or holds if of the predicates return false.
\param Pred The predicate to be negated
\return An instance of the \c class_not predicate
*/
template<typename PredT>
inline detail::pred_notF<PredT>
operator!( const predicate_facade<PredT>& Pred )
{
// Doing the static_cast with the pointer instead of the reference
// is a workaround for some compilers which have problems with
// static_cast's of template references, i.e. CW8. /grafik/
return detail::pred_notF<PredT>(*static_cast<const PredT*>(&Pred));
}
} // namespace algorithm
// pull names to the boost namespace
using algorithm::is_classified;
using algorithm::is_space;
using algorithm::is_alnum;
using algorithm::is_alpha;
using algorithm::is_cntrl;
using algorithm::is_digit;
using algorithm::is_graph;
using algorithm::is_lower;
using algorithm::is_upper;
using algorithm::is_print;
using algorithm::is_punct;
using algorithm::is_xdigit;
using algorithm::is_any_of;
using algorithm::is_from_range;
} // namespace boost
#endif // BOOST_STRING_PREDICATE_HPP

View File

@@ -0,0 +1,199 @@
// Boost string_algo library compare.hpp header file -------------------------//
// Copyright Pavol Droba 2002-2006.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_COMPARE_HPP
#define BOOST_STRING_COMPARE_HPP
#include <boost/algorithm/string/config.hpp>
#include <locale>
/*! \file
Defines element comparison predicates. Many algorithms in this library can
take an additional argument with a predicate used to compare elements.
This makes it possible, for instance, to have case insensitive versions
of the algorithms.
*/
namespace boost {
namespace algorithm {
// is_equal functor -----------------------------------------------//
//! is_equal functor
/*!
Standard STL equal_to only handle comparison between arguments
of the same type. This is a less restrictive version which wraps operator ==.
*/
struct is_equal
{
//! Function operator
/*!
Compare two operands for equality
*/
template< typename T1, typename T2 >
bool operator()( const T1& Arg1, const T2& Arg2 ) const
{
return Arg1==Arg2;
}
};
//! case insensitive version of is_equal
/*!
Case insensitive comparison predicate. Comparison is done using
specified locales.
*/
struct is_iequal
{
//! Constructor
/*!
\param Loc locales used for comparison
*/
is_iequal( const std::locale& Loc=std::locale() ) :
m_Loc( Loc ) {}
//! Function operator
/*!
Compare two operands. Case is ignored.
*/
template< typename T1, typename T2 >
bool operator()( const T1& Arg1, const T2& Arg2 ) const
{
#if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL)
return std::toupper(Arg1)==std::toupper(Arg2);
#else
return std::toupper<T1>(Arg1,m_Loc)==std::toupper<T2>(Arg2,m_Loc);
#endif
}
private:
std::locale m_Loc;
};
// is_less functor -----------------------------------------------//
//! is_less functor
/*!
Convenient version of standard std::less. Operation is templated, therefore it is
not required to specify the exact types upon the construction
*/
struct is_less
{
//! Functor operation
/*!
Compare two operands using > operator
*/
template< typename T1, typename T2 >
bool operator()( const T1& Arg1, const T2& Arg2 ) const
{
return Arg1<Arg2;
}
};
//! case insensitive version of is_less
/*!
Case insensitive comparison predicate. Comparison is done using
specified locales.
*/
struct is_iless
{
//! Constructor
/*!
\param Loc locales used for comparison
*/
is_iless( const std::locale& Loc=std::locale() ) :
m_Loc( Loc ) {}
//! Function operator
/*!
Compare two operands. Case is ignored.
*/
template< typename T1, typename T2 >
bool operator()( const T1& Arg1, const T2& Arg2 ) const
{
#if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL)
return std::toupper(Arg1)<std::toupper(Arg2);
#else
return std::toupper<T1>(Arg1,m_Loc)<std::toupper<T2>(Arg2,m_Loc);
#endif
}
private:
std::locale m_Loc;
};
// is_not_greater functor -----------------------------------------------//
//! is_not_greater functor
/*!
Convenient version of standard std::not_greater_to. Operation is templated, therefore it is
not required to specify the exact types upon the construction
*/
struct is_not_greater
{
//! Functor operation
/*!
Compare two operands using > operator
*/
template< typename T1, typename T2 >
bool operator()( const T1& Arg1, const T2& Arg2 ) const
{
return Arg1<=Arg2;
}
};
//! case insensitive version of is_not_greater
/*!
Case insensitive comparison predicate. Comparison is done using
specified locales.
*/
struct is_not_igreater
{
//! Constructor
/*!
\param Loc locales used for comparison
*/
is_not_igreater( const std::locale& Loc=std::locale() ) :
m_Loc( Loc ) {}
//! Function operator
/*!
Compare two operands. Case is ignored.
*/
template< typename T1, typename T2 >
bool operator()( const T1& Arg1, const T2& Arg2 ) const
{
#if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL)
return std::toupper(Arg1)<=std::toupper(Arg2);
#else
return std::toupper<T1>(Arg1,m_Loc)<=std::toupper<T2>(Arg2,m_Loc);
#endif
}
private:
std::locale m_Loc;
};
} // namespace algorithm
// pull names to the boost namespace
using algorithm::is_equal;
using algorithm::is_iequal;
using algorithm::is_less;
using algorithm::is_iless;
using algorithm::is_not_greater;
using algorithm::is_not_igreater;
} // namespace boost
#endif // BOOST_STRING_COMPARE_HPP

View File

@@ -0,0 +1,83 @@
// Boost string_algo library concept.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_CONCEPT_HPP
#define BOOST_STRING_CONCEPT_HPP
#include <boost/concept_check.hpp>
#include <boost/range/iterator_range_core.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
/*! \file
Defines concepts used in string_algo library
*/
namespace boost {
namespace algorithm {
//! Finder concept
/*!
Defines the Finder concept. Finder is a functor which selects
an arbitrary part of a string. Search is performed on
the range specified by starting and ending iterators.
Result of the find operation must be convertible to iterator_range.
*/
template<typename FinderT, typename IteratorT>
struct FinderConcept
{
private:
typedef iterator_range<IteratorT> range;
public:
void constraints()
{
// Operation
r=(*pF)(i,i);
}
private:
range r;
IteratorT i;
FinderT* pF;
}; // Finder_concept
//! Formatter concept
/*!
Defines the Formatter concept. Formatter is a functor, which
takes a result from a finder operation and transforms it
in a specific way.
Result must be a container supported by container_traits,
or a reference to it.
*/
template<typename FormatterT, typename FinderT, typename IteratorT>
struct FormatterConcept
{
public:
void constraints()
{
// Operation
::boost::begin((*pFo)( (*pF)(i,i) ));
::boost::end((*pFo)( (*pF)(i,i) ));
}
private:
IteratorT i;
FinderT* pF;
FormatterT *pFo;
}; // FormatterConcept;
} // namespace algorithm
} // namespace boost
#endif // BOOST_STRING_CONCEPT_HPP

View File

@@ -0,0 +1,28 @@
// Boost string_algo library config.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_CONFIG_HPP
#define BOOST_STRING_CONFIG_HPP
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
#ifdef BOOST_STRING_DEDUCED_TYPENAME
# error "macro already defined!"
#endif
#define BOOST_STRING_TYPENAME BOOST_DEDUCED_TYPENAME
// Metrowerks workaround
#if BOOST_WORKAROUND(__MWERKS__, <= 0x3003) // 8.x
#pragma parse_func_templ off
#endif
#endif // BOOST_STRING_CONFIG_HPP

View File

@@ -0,0 +1,36 @@
// Boost string_algo library constants.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_CONSTANTS_HPP
#define BOOST_STRING_CONSTANTS_HPP
namespace boost {
namespace algorithm {
//! Token compression mode
/*!
Specifies token compression mode for the token_finder.
*/
enum token_compress_mode_type
{
token_compress_on, //!< Compress adjacent tokens
token_compress_off //!< Do not compress adjacent tokens
};
} // namespace algorithm
// pull the names to the boost namespace
using algorithm::token_compress_on;
using algorithm::token_compress_off;
} // namespace boost
#endif // BOOST_STRING_CONSTANTS_HPP

View File

@@ -0,0 +1,123 @@
// Boost string_algo library string_funct.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_CASE_CONV_DETAIL_HPP
#define BOOST_STRING_CASE_CONV_DETAIL_HPP
#include <boost/algorithm/string/config.hpp>
#include <locale>
#include <functional>
#include <boost/type_traits/make_unsigned.hpp>
namespace boost {
namespace algorithm {
namespace detail {
// case conversion functors -----------------------------------------------//
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
#pragma warning(push)
#pragma warning(disable:4512) //assignment operator could not be generated
#endif
// a tolower functor
template<typename CharT>
struct to_lowerF : public std::unary_function<CharT, CharT>
{
// Constructor
to_lowerF( const std::locale& Loc ) : m_Loc( &Loc ) {}
// Operation
CharT operator ()( CharT Ch ) const
{
#if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL)
return std::tolower( static_cast<typename boost::make_unsigned <CharT>::type> ( Ch ));
#else
return std::tolower<CharT>( Ch, *m_Loc );
#endif
}
private:
const std::locale* m_Loc;
};
// a toupper functor
template<typename CharT>
struct to_upperF : public std::unary_function<CharT, CharT>
{
// Constructor
to_upperF( const std::locale& Loc ) : m_Loc( &Loc ) {}
// Operation
CharT operator ()( CharT Ch ) const
{
#if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL)
return std::toupper( static_cast<typename boost::make_unsigned <CharT>::type> ( Ch ));
#else
return std::toupper<CharT>( Ch, *m_Loc );
#endif
}
private:
const std::locale* m_Loc;
};
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
#pragma warning(pop)
#endif
// algorithm implementation -------------------------------------------------------------------------
// Transform a range
template<typename OutputIteratorT, typename RangeT, typename FunctorT>
OutputIteratorT transform_range_copy(
OutputIteratorT Output,
const RangeT& Input,
FunctorT Functor)
{
return std::transform(
::boost::begin(Input),
::boost::end(Input),
Output,
Functor);
}
// Transform a range (in-place)
template<typename RangeT, typename FunctorT>
void transform_range(
const RangeT& Input,
FunctorT Functor)
{
std::transform(
::boost::begin(Input),
::boost::end(Input),
::boost::begin(Input),
Functor);
}
template<typename SequenceT, typename RangeT, typename FunctorT>
inline SequenceT transform_range_copy(
const RangeT& Input,
FunctorT Functor)
{
return SequenceT(
::boost::make_transform_iterator(
::boost::begin(Input),
Functor),
::boost::make_transform_iterator(
::boost::end(Input),
Functor));
}
} // namespace detail
} // namespace algorithm
} // namespace boost
#endif // BOOST_STRING_CASE_CONV_DETAIL_HPP

View File

@@ -0,0 +1,353 @@
// Boost string_algo library classification.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_CLASSIFICATION_DETAIL_HPP
#define BOOST_STRING_CLASSIFICATION_DETAIL_HPP
#include <boost/algorithm/string/config.hpp>
#include <algorithm>
#include <functional>
#include <locale>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/algorithm/string/predicate_facade.hpp>
#include <boost/type_traits/remove_const.hpp>
namespace boost {
namespace algorithm {
namespace detail {
// classification functors -----------------------------------------------//
// is_classified functor
struct is_classifiedF :
public predicate_facade<is_classifiedF>
{
// Boost.ResultOf support
typedef bool result_type;
// Constructor from a locale
is_classifiedF(std::ctype_base::mask Type, std::locale const & Loc = std::locale()) :
m_Type(Type), m_Locale(Loc) {}
// Operation
template<typename CharT>
bool operator()( CharT Ch ) const
{
return std::use_facet< std::ctype<CharT> >(m_Locale).is( m_Type, Ch );
}
#if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x582) && !defined(_USE_OLD_RW_STL)
template<>
bool operator()( char const Ch ) const
{
return std::use_facet< std::ctype<char> >(m_Locale).is( m_Type, Ch );
}
#endif
private:
std::ctype_base::mask m_Type;
std::locale m_Locale;
};
// is_any_of functor
/*
returns true if the value is from the specified set
*/
template<typename CharT>
struct is_any_ofF :
public predicate_facade<is_any_ofF<CharT> >
{
private:
// set cannot operate on const value-type
typedef typename ::boost::remove_const<CharT>::type set_value_type;
public:
// Boost.ResultOf support
typedef bool result_type;
// Constructor
template<typename RangeT>
is_any_ofF( const RangeT& Range ) : m_Size(0)
{
// Prepare storage
m_Storage.m_dynSet=0;
std::size_t Size=::boost::distance(Range);
m_Size=Size;
set_value_type* Storage=0;
if(use_fixed_storage(m_Size))
{
// Use fixed storage
Storage=&m_Storage.m_fixSet[0];
}
else
{
// Use dynamic storage
m_Storage.m_dynSet=new set_value_type[m_Size];
Storage=m_Storage.m_dynSet;
}
// Use fixed storage
::std::copy(::boost::begin(Range), ::boost::end(Range), Storage);
::std::sort(Storage, Storage+m_Size);
}
// Copy constructor
is_any_ofF(const is_any_ofF& Other) : m_Size(Other.m_Size)
{
// Prepare storage
m_Storage.m_dynSet=0;
const set_value_type* SrcStorage=0;
set_value_type* DestStorage=0;
if(use_fixed_storage(m_Size))
{
// Use fixed storage
DestStorage=&m_Storage.m_fixSet[0];
SrcStorage=&Other.m_Storage.m_fixSet[0];
}
else
{
// Use dynamic storage
m_Storage.m_dynSet=new set_value_type[m_Size];
DestStorage=m_Storage.m_dynSet;
SrcStorage=Other.m_Storage.m_dynSet;
}
// Use fixed storage
::std::memcpy(DestStorage, SrcStorage, sizeof(set_value_type)*m_Size);
}
// Destructor
~is_any_ofF()
{
if(!use_fixed_storage(m_Size) && m_Storage.m_dynSet!=0)
{
delete [] m_Storage.m_dynSet;
}
}
// Assignment
is_any_ofF& operator=(const is_any_ofF& Other)
{
// Handle self assignment
if(this==&Other) return *this;
// Prepare storage
const set_value_type* SrcStorage;
set_value_type* DestStorage;
if(use_fixed_storage(Other.m_Size))
{
// Use fixed storage
DestStorage=&m_Storage.m_fixSet[0];
SrcStorage=&Other.m_Storage.m_fixSet[0];
// Delete old storage if was present
if(!use_fixed_storage(m_Size) && m_Storage.m_dynSet!=0)
{
delete [] m_Storage.m_dynSet;
}
// Set new size
m_Size=Other.m_Size;
}
else
{
// Other uses dynamic storage
SrcStorage=Other.m_Storage.m_dynSet;
// Check what kind of storage are we using right now
if(use_fixed_storage(m_Size))
{
// Using fixed storage, allocate new
set_value_type* pTemp=new set_value_type[Other.m_Size];
DestStorage=pTemp;
m_Storage.m_dynSet=pTemp;
m_Size=Other.m_Size;
}
else
{
// Using dynamic storage, check if can reuse
if(m_Storage.m_dynSet!=0 && m_Size>=Other.m_Size && m_Size<Other.m_Size*2)
{
// Reuse the current storage
DestStorage=m_Storage.m_dynSet;
m_Size=Other.m_Size;
}
else
{
// Allocate the new one
set_value_type* pTemp=new set_value_type[Other.m_Size];
DestStorage=pTemp;
// Delete old storage if necessary
if(m_Storage.m_dynSet!=0)
{
delete [] m_Storage.m_dynSet;
}
// Store the new storage
m_Storage.m_dynSet=pTemp;
// Set new size
m_Size=Other.m_Size;
}
}
}
// Copy the data
::std::memcpy(DestStorage, SrcStorage, sizeof(set_value_type)*m_Size);
return *this;
}
// Operation
template<typename Char2T>
bool operator()( Char2T Ch ) const
{
const set_value_type* Storage=
(use_fixed_storage(m_Size))
? &m_Storage.m_fixSet[0]
: m_Storage.m_dynSet;
return ::std::binary_search(Storage, Storage+m_Size, Ch);
}
private:
// check if the size is eligible for fixed storage
static bool use_fixed_storage(std::size_t size)
{
return size<=sizeof(set_value_type*)*2;
}
private:
// storage
// The actual used storage is selected on the type
union
{
set_value_type* m_dynSet;
set_value_type m_fixSet[sizeof(set_value_type*)*2];
}
m_Storage;
// storage size
::std::size_t m_Size;
};
// is_from_range functor
/*
returns true if the value is from the specified range.
(i.e. x>=From && x>=To)
*/
template<typename CharT>
struct is_from_rangeF :
public predicate_facade< is_from_rangeF<CharT> >
{
// Boost.ResultOf support
typedef bool result_type;
// Constructor
is_from_rangeF( CharT From, CharT To ) : m_From(From), m_To(To) {}
// Operation
template<typename Char2T>
bool operator()( Char2T Ch ) const
{
return ( m_From <= Ch ) && ( Ch <= m_To );
}
private:
CharT m_From;
CharT m_To;
};
// class_and composition predicate
template<typename Pred1T, typename Pred2T>
struct pred_andF :
public predicate_facade< pred_andF<Pred1T,Pred2T> >
{
public:
// Boost.ResultOf support
typedef bool result_type;
// Constructor
pred_andF( Pred1T Pred1, Pred2T Pred2 ) :
m_Pred1(Pred1), m_Pred2(Pred2) {}
// Operation
template<typename CharT>
bool operator()( CharT Ch ) const
{
return m_Pred1(Ch) && m_Pred2(Ch);
}
private:
Pred1T m_Pred1;
Pred2T m_Pred2;
};
// class_or composition predicate
template<typename Pred1T, typename Pred2T>
struct pred_orF :
public predicate_facade< pred_orF<Pred1T,Pred2T> >
{
public:
// Boost.ResultOf support
typedef bool result_type;
// Constructor
pred_orF( Pred1T Pred1, Pred2T Pred2 ) :
m_Pred1(Pred1), m_Pred2(Pred2) {}
// Operation
template<typename CharT>
bool operator()( CharT Ch ) const
{
return m_Pred1(Ch) || m_Pred2(Ch);
}
private:
Pred1T m_Pred1;
Pred2T m_Pred2;
};
// class_not composition predicate
template< typename PredT >
struct pred_notF :
public predicate_facade< pred_notF<PredT> >
{
public:
// Boost.ResultOf support
typedef bool result_type;
// Constructor
pred_notF( PredT Pred ) : m_Pred(Pred) {}
// Operation
template<typename CharT>
bool operator()( CharT Ch ) const
{
return !m_Pred(Ch);
}
private:
PredT m_Pred;
};
} // namespace detail
} // namespace algorithm
} // namespace boost
#endif // BOOST_STRING_CLASSIFICATION_DETAIL_HPP

View File

@@ -0,0 +1,204 @@
// Boost string_algo library find_format.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_FIND_FORMAT_DETAIL_HPP
#define BOOST_STRING_FIND_FORMAT_DETAIL_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/range/iterator_range_core.hpp>
#include <boost/range/const_iterator.hpp>
#include <boost/range/iterator.hpp>
#include <boost/algorithm/string/detail/find_format_store.hpp>
#include <boost/algorithm/string/detail/replace_storage.hpp>
namespace boost {
namespace algorithm {
namespace detail {
// find_format_copy (iterator variant) implementation -------------------------------//
template<
typename OutputIteratorT,
typename InputT,
typename FormatterT,
typename FindResultT,
typename FormatResultT >
inline OutputIteratorT find_format_copy_impl2(
OutputIteratorT Output,
const InputT& Input,
FormatterT Formatter,
const FindResultT& FindResult,
const FormatResultT& FormatResult )
{
typedef find_format_store<
BOOST_STRING_TYPENAME
range_const_iterator<InputT>::type,
FormatterT,
FormatResultT > store_type;
// Create store for the find result
store_type M( FindResult, FormatResult, Formatter );
if ( !M )
{
// Match not found - return original sequence
Output = std::copy( ::boost::begin(Input), ::boost::end(Input), Output );
return Output;
}
// Copy the beginning of the sequence
Output = std::copy( ::boost::begin(Input), ::boost::begin(M), Output );
// Format find result
// Copy formatted result
Output = std::copy( ::boost::begin(M.format_result()), ::boost::end(M.format_result()), Output );
// Copy the rest of the sequence
Output = std::copy( M.end(), ::boost::end(Input), Output );
return Output;
}
template<
typename OutputIteratorT,
typename InputT,
typename FormatterT,
typename FindResultT >
inline OutputIteratorT find_format_copy_impl(
OutputIteratorT Output,
const InputT& Input,
FormatterT Formatter,
const FindResultT& FindResult )
{
if( ::boost::algorithm::detail::check_find_result(Input, FindResult) ) {
return ::boost::algorithm::detail::find_format_copy_impl2(
Output,
Input,
Formatter,
FindResult,
Formatter(FindResult) );
} else {
return std::copy( ::boost::begin(Input), ::boost::end(Input), Output );
}
}
// find_format_copy implementation --------------------------------------------------//
template<
typename InputT,
typename FormatterT,
typename FindResultT,
typename FormatResultT >
inline InputT find_format_copy_impl2(
const InputT& Input,
FormatterT Formatter,
const FindResultT& FindResult,
const FormatResultT& FormatResult)
{
typedef find_format_store<
BOOST_STRING_TYPENAME
range_const_iterator<InputT>::type,
FormatterT,
FormatResultT > store_type;
// Create store for the find result
store_type M( FindResult, FormatResult, Formatter );
if ( !M )
{
// Match not found - return original sequence
return InputT( Input );
}
InputT Output;
// Copy the beginning of the sequence
boost::algorithm::detail::insert( Output, ::boost::end(Output), ::boost::begin(Input), M.begin() );
// Copy formatted result
boost::algorithm::detail::insert( Output, ::boost::end(Output), M.format_result() );
// Copy the rest of the sequence
boost::algorithm::detail::insert( Output, ::boost::end(Output), M.end(), ::boost::end(Input) );
return Output;
}
template<
typename InputT,
typename FormatterT,
typename FindResultT >
inline InputT find_format_copy_impl(
const InputT& Input,
FormatterT Formatter,
const FindResultT& FindResult)
{
if( ::boost::algorithm::detail::check_find_result(Input, FindResult) ) {
return ::boost::algorithm::detail::find_format_copy_impl2(
Input,
Formatter,
FindResult,
Formatter(FindResult) );
} else {
return Input;
}
}
// replace implementation ----------------------------------------------------//
template<
typename InputT,
typename FormatterT,
typename FindResultT,
typename FormatResultT >
inline void find_format_impl2(
InputT& Input,
FormatterT Formatter,
const FindResultT& FindResult,
const FormatResultT& FormatResult)
{
typedef find_format_store<
BOOST_STRING_TYPENAME
range_iterator<InputT>::type,
FormatterT,
FormatResultT > store_type;
// Create store for the find result
store_type M( FindResult, FormatResult, Formatter );
if ( !M )
{
// Search not found - return original sequence
return;
}
// Replace match
::boost::algorithm::detail::replace( Input, M.begin(), M.end(), M.format_result() );
}
template<
typename InputT,
typename FormatterT,
typename FindResultT >
inline void find_format_impl(
InputT& Input,
FormatterT Formatter,
const FindResultT& FindResult)
{
if( ::boost::algorithm::detail::check_find_result(Input, FindResult) ) {
::boost::algorithm::detail::find_format_impl2(
Input,
Formatter,
FindResult,
Formatter(FindResult) );
}
}
} // namespace detail
} // namespace algorithm
} // namespace boost
#endif // BOOST_STRING_FIND_FORMAT_DETAIL_HPP

View File

@@ -0,0 +1,273 @@
// Boost string_algo library find_format_all.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_FIND_FORMAT_ALL_DETAIL_HPP
#define BOOST_STRING_FIND_FORMAT_ALL_DETAIL_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/range/iterator_range_core.hpp>
#include <boost/range/const_iterator.hpp>
#include <boost/range/value_type.hpp>
#include <boost/algorithm/string/detail/find_format_store.hpp>
#include <boost/algorithm/string/detail/replace_storage.hpp>
namespace boost {
namespace algorithm {
namespace detail {
// find_format_all_copy (iterator variant) implementation ---------------------------//
template<
typename OutputIteratorT,
typename InputT,
typename FinderT,
typename FormatterT,
typename FindResultT,
typename FormatResultT >
inline OutputIteratorT find_format_all_copy_impl2(
OutputIteratorT Output,
const InputT& Input,
FinderT Finder,
FormatterT Formatter,
const FindResultT& FindResult,
const FormatResultT& FormatResult )
{
typedef BOOST_STRING_TYPENAME
range_const_iterator<InputT>::type input_iterator_type;
typedef find_format_store<
input_iterator_type,
FormatterT,
FormatResultT > store_type;
// Create store for the find result
store_type M( FindResult, FormatResult, Formatter );
// Initialize last match
input_iterator_type LastMatch=::boost::begin(Input);
// Iterate through all matches
while( M )
{
// Copy the beginning of the sequence
Output = std::copy( LastMatch, M.begin(), Output );
// Copy formatted result
Output = std::copy( ::boost::begin(M.format_result()), ::boost::end(M.format_result()), Output );
// Proceed to the next match
LastMatch=M.end();
M=Finder( LastMatch, ::boost::end(Input) );
}
// Copy the rest of the sequence
Output = std::copy( LastMatch, ::boost::end(Input), Output );
return Output;
}
template<
typename OutputIteratorT,
typename InputT,
typename FinderT,
typename FormatterT,
typename FindResultT >
inline OutputIteratorT find_format_all_copy_impl(
OutputIteratorT Output,
const InputT& Input,
FinderT Finder,
FormatterT Formatter,
const FindResultT& FindResult )
{
if( ::boost::algorithm::detail::check_find_result(Input, FindResult) ) {
return ::boost::algorithm::detail::find_format_all_copy_impl2(
Output,
Input,
Finder,
Formatter,
FindResult,
Formatter(FindResult) );
} else {
return std::copy( ::boost::begin(Input), ::boost::end(Input), Output );
}
}
// find_format_all_copy implementation ----------------------------------------------//
template<
typename InputT,
typename FinderT,
typename FormatterT,
typename FindResultT,
typename FormatResultT >
inline InputT find_format_all_copy_impl2(
const InputT& Input,
FinderT Finder,
FormatterT Formatter,
const FindResultT& FindResult,
const FormatResultT& FormatResult)
{
typedef BOOST_STRING_TYPENAME
range_const_iterator<InputT>::type input_iterator_type;
typedef find_format_store<
input_iterator_type,
FormatterT,
FormatResultT > store_type;
// Create store for the find result
store_type M( FindResult, FormatResult, Formatter );
// Initialize last match
input_iterator_type LastMatch=::boost::begin(Input);
// Output temporary
InputT Output;
// Iterate through all matches
while( M )
{
// Copy the beginning of the sequence
boost::algorithm::detail::insert( Output, ::boost::end(Output), LastMatch, M.begin() );
// Copy formatted result
boost::algorithm::detail::insert( Output, ::boost::end(Output), M.format_result() );
// Proceed to the next match
LastMatch=M.end();
M=Finder( LastMatch, ::boost::end(Input) );
}
// Copy the rest of the sequence
::boost::algorithm::detail::insert( Output, ::boost::end(Output), LastMatch, ::boost::end(Input) );
return Output;
}
template<
typename InputT,
typename FinderT,
typename FormatterT,
typename FindResultT >
inline InputT find_format_all_copy_impl(
const InputT& Input,
FinderT Finder,
FormatterT Formatter,
const FindResultT& FindResult)
{
if( ::boost::algorithm::detail::check_find_result(Input, FindResult) ) {
return ::boost::algorithm::detail::find_format_all_copy_impl2(
Input,
Finder,
Formatter,
FindResult,
Formatter(FindResult) );
} else {
return Input;
}
}
// find_format_all implementation ------------------------------------------------//
template<
typename InputT,
typename FinderT,
typename FormatterT,
typename FindResultT,
typename FormatResultT >
inline void find_format_all_impl2(
InputT& Input,
FinderT Finder,
FormatterT Formatter,
FindResultT FindResult,
FormatResultT FormatResult)
{
typedef BOOST_STRING_TYPENAME
range_iterator<InputT>::type input_iterator_type;
typedef find_format_store<
input_iterator_type,
FormatterT,
FormatResultT > store_type;
// Create store for the find result
store_type M( FindResult, FormatResult, Formatter );
// Instantiate replacement storage
std::deque<
BOOST_STRING_TYPENAME range_value<InputT>::type> Storage;
// Initialize replacement iterators
input_iterator_type InsertIt=::boost::begin(Input);
input_iterator_type SearchIt=::boost::begin(Input);
while( M )
{
// process the segment
InsertIt=process_segment(
Storage,
Input,
InsertIt,
SearchIt,
M.begin() );
// Adjust search iterator
SearchIt=M.end();
// Copy formatted replace to the storage
::boost::algorithm::detail::copy_to_storage( Storage, M.format_result() );
// Find range for a next match
M=Finder( SearchIt, ::boost::end(Input) );
}
// process the last segment
InsertIt=::boost::algorithm::detail::process_segment(
Storage,
Input,
InsertIt,
SearchIt,
::boost::end(Input) );
if ( Storage.empty() )
{
// Truncate input
::boost::algorithm::detail::erase( Input, InsertIt, ::boost::end(Input) );
}
else
{
// Copy remaining data to the end of input
::boost::algorithm::detail::insert( Input, ::boost::end(Input), Storage.begin(), Storage.end() );
}
}
template<
typename InputT,
typename FinderT,
typename FormatterT,
typename FindResultT >
inline void find_format_all_impl(
InputT& Input,
FinderT Finder,
FormatterT Formatter,
FindResultT FindResult)
{
if( ::boost::algorithm::detail::check_find_result(Input, FindResult) ) {
::boost::algorithm::detail::find_format_all_impl2(
Input,
Finder,
Formatter,
FindResult,
Formatter(FindResult) );
}
}
} // namespace detail
} // namespace algorithm
} // namespace boost
#endif // BOOST_STRING_FIND_FORMAT_ALL_DETAIL_HPP

View File

@@ -0,0 +1,89 @@
// Boost string_algo library find_format_store.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_FIND_FORMAT_STORE_DETAIL_HPP
#define BOOST_STRING_FIND_FORMAT_STORE_DETAIL_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/range/iterator_range_core.hpp>
namespace boost {
namespace algorithm {
namespace detail {
// temporary format and find result storage --------------------------------//
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
#pragma warning(push)
#pragma warning(disable:4512) //assignment operator could not be generated
#endif
template<
typename ForwardIteratorT,
typename FormatterT,
typename FormatResultT >
class find_format_store :
public iterator_range<ForwardIteratorT>
{
public:
// typedefs
typedef iterator_range<ForwardIteratorT> base_type;
typedef FormatterT formatter_type;
typedef FormatResultT format_result_type;
public:
// Construction
find_format_store(
const base_type& FindResult,
const format_result_type& FormatResult,
const formatter_type& Formatter ) :
base_type(FindResult),
m_FormatResult(FormatResult),
m_Formatter(Formatter) {}
// Assignment
template< typename FindResultT >
find_format_store& operator=( FindResultT FindResult )
{
iterator_range<ForwardIteratorT>::operator=(FindResult);
if( !this->empty() ) {
m_FormatResult=m_Formatter(FindResult);
}
return *this;
}
// Retrieve format result
const format_result_type& format_result()
{
return m_FormatResult;
}
private:
format_result_type m_FormatResult;
const formatter_type& m_Formatter;
};
template<typename InputT, typename FindResultT>
bool check_find_result(InputT&, FindResultT& FindResult)
{
typedef BOOST_STRING_TYPENAME
range_const_iterator<InputT>::type input_iterator_type;
iterator_range<input_iterator_type> ResultRange(FindResult);
return !ResultRange.empty();
}
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
#pragma warning(pop)
#endif
} // namespace detail
} // namespace algorithm
} // namespace boost
#endif // BOOST_STRING_FIND_FORMAT_STORE_DETAIL_HPP

View File

@@ -0,0 +1,87 @@
// Boost string_algo library find_iterator.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_FIND_ITERATOR_DETAIL_HPP
#define BOOST_STRING_FIND_ITERATOR_DETAIL_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/range/iterator_range_core.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/iterator/iterator_categories.hpp>
#include <boost/function.hpp>
namespace boost {
namespace algorithm {
namespace detail {
// find_iterator base -----------------------------------------------//
// Find iterator base
template<typename IteratorT>
class find_iterator_base
{
protected:
// typedefs
typedef IteratorT input_iterator_type;
typedef iterator_range<IteratorT> match_type;
typedef function2<
match_type,
input_iterator_type,
input_iterator_type> finder_type;
protected:
// Protected construction/destruction
// Default constructor
find_iterator_base() {};
// Copy construction
find_iterator_base( const find_iterator_base& Other ) :
m_Finder(Other.m_Finder) {}
// Constructor
template<typename FinderT>
find_iterator_base( FinderT Finder, int ) :
m_Finder(Finder) {}
// Destructor
~find_iterator_base() {}
// Find operation
match_type do_find(
input_iterator_type Begin,
input_iterator_type End ) const
{
if (!m_Finder.empty())
{
return m_Finder(Begin,End);
}
else
{
return match_type(End,End);
}
}
// Check
bool is_null() const
{
return m_Finder.empty();
}
private:
// Finder
finder_type m_Finder;
};
} // namespace detail
} // namespace algorithm
} // namespace boost
#endif // BOOST_STRING_FIND_ITERATOR_DETAIL_HPP

View File

@@ -0,0 +1,639 @@
// Boost string_algo library finder.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2006.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_FINDER_DETAIL_HPP
#define BOOST_STRING_FINDER_DETAIL_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/algorithm/string/constants.hpp>
#include <boost/detail/iterator.hpp>
#include <boost/range/iterator_range_core.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/empty.hpp>
#include <boost/range/as_literal.hpp>
namespace boost {
namespace algorithm {
namespace detail {
// find first functor -----------------------------------------------//
// find a subsequence in the sequence ( functor )
/*
Returns a pair <begin,end> marking the subsequence in the sequence.
If the find fails, functor returns <End,End>
*/
template<typename SearchIteratorT,typename PredicateT>
struct first_finderF
{
typedef SearchIteratorT search_iterator_type;
// Construction
template< typename SearchT >
first_finderF( const SearchT& Search, PredicateT Comp ) :
m_Search(::boost::begin(Search), ::boost::end(Search)), m_Comp(Comp) {}
first_finderF(
search_iterator_type SearchBegin,
search_iterator_type SearchEnd,
PredicateT Comp ) :
m_Search(SearchBegin, SearchEnd), m_Comp(Comp) {}
// Operation
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
operator()(
ForwardIteratorT Begin,
ForwardIteratorT End ) const
{
typedef iterator_range<ForwardIteratorT> result_type;
typedef ForwardIteratorT input_iterator_type;
// Outer loop
for(input_iterator_type OuterIt=Begin;
OuterIt!=End;
++OuterIt)
{
// Sanity check
if( boost::empty(m_Search) )
return result_type( End, End );
input_iterator_type InnerIt=OuterIt;
search_iterator_type SubstrIt=m_Search.begin();
for(;
InnerIt!=End && SubstrIt!=m_Search.end();
++InnerIt,++SubstrIt)
{
if( !( m_Comp(*InnerIt,*SubstrIt) ) )
break;
}
// Substring matching succeeded
if ( SubstrIt==m_Search.end() )
return result_type( OuterIt, InnerIt );
}
return result_type( End, End );
}
private:
iterator_range<search_iterator_type> m_Search;
PredicateT m_Comp;
};
// find last functor -----------------------------------------------//
// find the last match a subsequence in the sequence ( functor )
/*
Returns a pair <begin,end> marking the subsequence in the sequence.
If the find fails, returns <End,End>
*/
template<typename SearchIteratorT, typename PredicateT>
struct last_finderF
{
typedef SearchIteratorT search_iterator_type;
typedef first_finderF<
search_iterator_type,
PredicateT> first_finder_type;
// Construction
template< typename SearchT >
last_finderF( const SearchT& Search, PredicateT Comp ) :
m_Search(::boost::begin(Search), ::boost::end(Search)), m_Comp(Comp) {}
last_finderF(
search_iterator_type SearchBegin,
search_iterator_type SearchEnd,
PredicateT Comp ) :
m_Search(SearchBegin, SearchEnd), m_Comp(Comp) {}
// Operation
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
operator()(
ForwardIteratorT Begin,
ForwardIteratorT End ) const
{
typedef iterator_range<ForwardIteratorT> result_type;
if( boost::empty(m_Search) )
return result_type( End, End );
typedef BOOST_STRING_TYPENAME boost::detail::
iterator_traits<ForwardIteratorT>::iterator_category category;
return findit( Begin, End, category() );
}
private:
// forward iterator
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
findit(
ForwardIteratorT Begin,
ForwardIteratorT End,
std::forward_iterator_tag ) const
{
typedef iterator_range<ForwardIteratorT> result_type;
first_finder_type first_finder(
m_Search.begin(), m_Search.end(), m_Comp );
result_type M=first_finder( Begin, End );
result_type Last=M;
while( M )
{
Last=M;
M=first_finder( ::boost::end(M), End );
}
return Last;
}
// bidirectional iterator
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
findit(
ForwardIteratorT Begin,
ForwardIteratorT End,
std::bidirectional_iterator_tag ) const
{
typedef iterator_range<ForwardIteratorT> result_type;
typedef ForwardIteratorT input_iterator_type;
// Outer loop
for(input_iterator_type OuterIt=End;
OuterIt!=Begin; )
{
input_iterator_type OuterIt2=--OuterIt;
input_iterator_type InnerIt=OuterIt2;
search_iterator_type SubstrIt=m_Search.begin();
for(;
InnerIt!=End && SubstrIt!=m_Search.end();
++InnerIt,++SubstrIt)
{
if( !( m_Comp(*InnerIt,*SubstrIt) ) )
break;
}
// Substring matching succeeded
if( SubstrIt==m_Search.end() )
return result_type( OuterIt2, InnerIt );
}
return result_type( End, End );
}
private:
iterator_range<search_iterator_type> m_Search;
PredicateT m_Comp;
};
// find n-th functor -----------------------------------------------//
// find the n-th match of a subsequence in the sequence ( functor )
/*
Returns a pair <begin,end> marking the subsequence in the sequence.
If the find fails, returns <End,End>
*/
template<typename SearchIteratorT, typename PredicateT>
struct nth_finderF
{
typedef SearchIteratorT search_iterator_type;
typedef first_finderF<
search_iterator_type,
PredicateT> first_finder_type;
typedef last_finderF<
search_iterator_type,
PredicateT> last_finder_type;
// Construction
template< typename SearchT >
nth_finderF(
const SearchT& Search,
int Nth,
PredicateT Comp) :
m_Search(::boost::begin(Search), ::boost::end(Search)),
m_Nth(Nth),
m_Comp(Comp) {}
nth_finderF(
search_iterator_type SearchBegin,
search_iterator_type SearchEnd,
int Nth,
PredicateT Comp) :
m_Search(SearchBegin, SearchEnd),
m_Nth(Nth),
m_Comp(Comp) {}
// Operation
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
operator()(
ForwardIteratorT Begin,
ForwardIteratorT End ) const
{
if(m_Nth>=0)
{
return find_forward(Begin, End, m_Nth);
}
else
{
return find_backward(Begin, End, -m_Nth);
}
}
private:
// Implementation helpers
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
find_forward(
ForwardIteratorT Begin,
ForwardIteratorT End,
unsigned int N) const
{
typedef iterator_range<ForwardIteratorT> result_type;
// Sanity check
if( boost::empty(m_Search) )
return result_type( End, End );
// Instantiate find functor
first_finder_type first_finder(
m_Search.begin(), m_Search.end(), m_Comp );
result_type M( Begin, Begin );
for( unsigned int n=0; n<=N; ++n )
{
// find next match
M=first_finder( ::boost::end(M), End );
if ( !M )
{
// Subsequence not found, return
return M;
}
}
return M;
}
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
find_backward(
ForwardIteratorT Begin,
ForwardIteratorT End,
unsigned int N) const
{
typedef iterator_range<ForwardIteratorT> result_type;
// Sanity check
if( boost::empty(m_Search) )
return result_type( End, End );
// Instantiate find functor
last_finder_type last_finder(
m_Search.begin(), m_Search.end(), m_Comp );
result_type M( End, End );
for( unsigned int n=1; n<=N; ++n )
{
// find next match
M=last_finder( Begin, ::boost::begin(M) );
if ( !M )
{
// Subsequence not found, return
return M;
}
}
return M;
}
private:
iterator_range<search_iterator_type> m_Search;
int m_Nth;
PredicateT m_Comp;
};
// find head/tail implementation helpers ---------------------------//
template<typename ForwardIteratorT>
iterator_range<ForwardIteratorT>
find_head_impl(
ForwardIteratorT Begin,
ForwardIteratorT End,
unsigned int N,
std::forward_iterator_tag )
{
typedef ForwardIteratorT input_iterator_type;
typedef iterator_range<ForwardIteratorT> result_type;
input_iterator_type It=Begin;
for(
unsigned int Index=0;
Index<N && It!=End; ++Index,++It ) {};
return result_type( Begin, It );
}
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
find_head_impl(
ForwardIteratorT Begin,
ForwardIteratorT End,
unsigned int N,
std::random_access_iterator_tag )
{
typedef iterator_range<ForwardIteratorT> result_type;
if ( (End<=Begin) || ( static_cast<unsigned int>(End-Begin) < N ) )
return result_type( Begin, End );
return result_type(Begin,Begin+N);
}
// Find head implementation
template<typename ForwardIteratorT>
iterator_range<ForwardIteratorT>
find_head_impl(
ForwardIteratorT Begin,
ForwardIteratorT End,
unsigned int N )
{
typedef BOOST_STRING_TYPENAME boost::detail::
iterator_traits<ForwardIteratorT>::iterator_category category;
return ::boost::algorithm::detail::find_head_impl( Begin, End, N, category() );
}
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
find_tail_impl(
ForwardIteratorT Begin,
ForwardIteratorT End,
unsigned int N,
std::forward_iterator_tag )
{
typedef ForwardIteratorT input_iterator_type;
typedef iterator_range<ForwardIteratorT> result_type;
unsigned int Index=0;
input_iterator_type It=Begin;
input_iterator_type It2=Begin;
// Advance It2 by N increments
for( Index=0; Index<N && It2!=End; ++Index,++It2 ) {};
// Advance It, It2 to the end
for(; It2!=End; ++It,++It2 ) {};
return result_type( It, It2 );
}
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
find_tail_impl(
ForwardIteratorT Begin,
ForwardIteratorT End,
unsigned int N,
std::bidirectional_iterator_tag )
{
typedef ForwardIteratorT input_iterator_type;
typedef iterator_range<ForwardIteratorT> result_type;
input_iterator_type It=End;
for(
unsigned int Index=0;
Index<N && It!=Begin; ++Index,--It ) {};
return result_type( It, End );
}
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
find_tail_impl(
ForwardIteratorT Begin,
ForwardIteratorT End,
unsigned int N,
std::random_access_iterator_tag )
{
typedef iterator_range<ForwardIteratorT> result_type;
if ( (End<=Begin) || ( static_cast<unsigned int>(End-Begin) < N ) )
return result_type( Begin, End );
return result_type( End-N, End );
}
// Operation
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
find_tail_impl(
ForwardIteratorT Begin,
ForwardIteratorT End,
unsigned int N )
{
typedef BOOST_STRING_TYPENAME boost::detail::
iterator_traits<ForwardIteratorT>::iterator_category category;
return ::boost::algorithm::detail::find_tail_impl( Begin, End, N, category() );
}
// find head functor -----------------------------------------------//
// find a head in the sequence ( functor )
/*
This functor find a head of the specified range. For
a specified N, the head is a subsequence of N starting
elements of the range.
*/
struct head_finderF
{
// Construction
head_finderF( int N ) : m_N(N) {}
// Operation
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
operator()(
ForwardIteratorT Begin,
ForwardIteratorT End ) const
{
if(m_N>=0)
{
return ::boost::algorithm::detail::find_head_impl( Begin, End, m_N );
}
else
{
iterator_range<ForwardIteratorT> Res=
::boost::algorithm::detail::find_tail_impl( Begin, End, -m_N );
return ::boost::make_iterator_range(Begin, Res.begin());
}
}
private:
int m_N;
};
// find tail functor -----------------------------------------------//
// find a tail in the sequence ( functor )
/*
This functor find a tail of the specified range. For
a specified N, the head is a subsequence of N starting
elements of the range.
*/
struct tail_finderF
{
// Construction
tail_finderF( int N ) : m_N(N) {}
// Operation
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
operator()(
ForwardIteratorT Begin,
ForwardIteratorT End ) const
{
if(m_N>=0)
{
return ::boost::algorithm::detail::find_tail_impl( Begin, End, m_N );
}
else
{
iterator_range<ForwardIteratorT> Res=
::boost::algorithm::detail::find_head_impl( Begin, End, -m_N );
return ::boost::make_iterator_range(Res.end(), End);
}
}
private:
int m_N;
};
// find token functor -----------------------------------------------//
// find a token in a sequence ( functor )
/*
This find functor finds a token specified be a predicate
in a sequence. It is equivalent of std::find algorithm,
with an exception that it return range instead of a single
iterator.
If bCompress is set to true, adjacent matching tokens are
concatenated into one match.
*/
template< typename PredicateT >
struct token_finderF
{
// Construction
token_finderF(
PredicateT Pred,
token_compress_mode_type eCompress=token_compress_off ) :
m_Pred(Pred), m_eCompress(eCompress) {}
// Operation
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
operator()(
ForwardIteratorT Begin,
ForwardIteratorT End ) const
{
typedef iterator_range<ForwardIteratorT> result_type;
ForwardIteratorT It=std::find_if( Begin, End, m_Pred );
if( It==End )
{
return result_type( End, End );
}
else
{
ForwardIteratorT It2=It;
if( m_eCompress==token_compress_on )
{
// Find first non-matching character
while( It2!=End && m_Pred(*It2) ) ++It2;
}
else
{
// Advance by one position
++It2;
}
return result_type( It, It2 );
}
}
private:
PredicateT m_Pred;
token_compress_mode_type m_eCompress;
};
// find range functor -----------------------------------------------//
// find a range in the sequence ( functor )
/*
This functor actually does not perform any find operation.
It always returns given iterator range as a result.
*/
template<typename ForwardIterator1T>
struct range_finderF
{
typedef ForwardIterator1T input_iterator_type;
typedef iterator_range<input_iterator_type> result_type;
// Construction
range_finderF(
input_iterator_type Begin,
input_iterator_type End ) : m_Range(Begin, End) {}
range_finderF(const iterator_range<input_iterator_type>& Range) :
m_Range(Range) {}
// Operation
template< typename ForwardIterator2T >
iterator_range<ForwardIterator2T>
operator()(
ForwardIterator2T,
ForwardIterator2T ) const
{
#if BOOST_WORKAROUND( __MWERKS__, <= 0x3003 )
return iterator_range<const ForwardIterator2T>(this->m_Range);
#else
return m_Range;
#endif
}
private:
iterator_range<input_iterator_type> m_Range;
};
} // namespace detail
} // namespace algorithm
} // namespace boost
#endif // BOOST_STRING_FINDER_DETAIL_HPP

View File

@@ -0,0 +1,122 @@
// Boost string_algo library find_regex.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_FINDER_REGEX_DETAIL_HPP
#define BOOST_STRING_FINDER_REGEX_DETAIL_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/regex.hpp>
#include <boost/range/iterator_range_core.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
namespace boost {
namespace algorithm {
namespace detail {
// regex find functor -----------------------------------------------//
// regex search result
template<typename IteratorT>
struct regex_search_result :
public iterator_range<IteratorT>
{
typedef regex_search_result<IteratorT> type;
typedef iterator_range<IteratorT> base_type;
typedef BOOST_STRING_TYPENAME base_type::value_type value_type;
typedef BOOST_STRING_TYPENAME base_type::difference_type difference_type;
typedef BOOST_STRING_TYPENAME base_type::const_iterator const_iterator;
typedef BOOST_STRING_TYPENAME base_type::iterator iterator;
typedef boost::match_results<iterator> match_results_type;
// Construction
// Construction from the match result
regex_search_result( const match_results_type& MatchResults ) :
base_type( MatchResults[0].first, MatchResults[0].second ),
m_MatchResults( MatchResults ) {}
// Construction of empty match. End iterator has to be specified
regex_search_result( IteratorT End ) :
base_type( End, End ) {}
regex_search_result( const regex_search_result& Other ) :
base_type( Other.begin(), Other.end() ),
m_MatchResults( Other.m_MatchResults ) {}
// Assignment
regex_search_result& operator=( const regex_search_result& Other )
{
base_type::operator=( Other );
m_MatchResults=Other.m_MatchResults;
return *this;
}
// Match result retrieval
const match_results_type& match_results() const
{
return m_MatchResults;
}
private:
// Saved match result
match_results_type m_MatchResults;
};
// find_regex
/*
Regex based search functor
*/
template<typename RegExT>
struct find_regexF
{
typedef RegExT regex_type;
typedef const RegExT& regex_reference_type;
// Construction
find_regexF( regex_reference_type Rx, match_flag_type MatchFlags = match_default ) :
m_Rx(Rx), m_MatchFlags(MatchFlags) {}
// Operation
template< typename ForwardIteratorT >
regex_search_result<ForwardIteratorT>
operator()(
ForwardIteratorT Begin,
ForwardIteratorT End ) const
{
typedef ForwardIteratorT input_iterator_type;
typedef regex_search_result<ForwardIteratorT> result_type;
// instantiate match result
match_results<input_iterator_type> result;
// search for a match
if ( ::boost::regex_search( Begin, End, result, m_Rx, m_MatchFlags ) )
{
// construct a result
return result_type( result );
}
else
{
// empty result
return result_type( End );
}
}
private:
regex_reference_type m_Rx; // Regexp
match_flag_type m_MatchFlags; // match flags
};
} // namespace detail
} // namespace algorithm
} // namespace boost
#endif // BOOST_STRING_FIND_DETAIL_HPP

View File

@@ -0,0 +1,119 @@
// Boost string_algo library formatter.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
#ifndef BOOST_STRING_FORMATTER_DETAIL_HPP
#define BOOST_STRING_FORMATTER_DETAIL_HPP
#include <boost/range/iterator_range_core.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/const_iterator.hpp>
#include <boost/algorithm/string/detail/util.hpp>
// generic replace functors -----------------------------------------------//
namespace boost {
namespace algorithm {
namespace detail {
// const format functor ----------------------------------------------------//
// constant format functor
template<typename RangeT>
struct const_formatF
{
private:
typedef BOOST_STRING_TYPENAME
range_const_iterator<RangeT>::type format_iterator;
typedef iterator_range<format_iterator> result_type;
public:
// Construction
const_formatF(const RangeT& Format) :
m_Format(::boost::begin(Format), ::boost::end(Format)) {}
// Operation
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
template<typename Range2T>
result_type& operator()(const Range2T&)
{
return m_Format;
}
#endif
template<typename Range2T>
const result_type& operator()(const Range2T&) const
{
return m_Format;
}
private:
result_type m_Format;
};
// identity format functor ----------------------------------------------------//
// identity format functor
template<typename RangeT>
struct identity_formatF
{
// Operation
template< typename Range2T >
const RangeT& operator()(const Range2T& Replace) const
{
return RangeT(::boost::begin(Replace), ::boost::end(Replace));
}
};
// empty format functor ( used by erase ) ------------------------------------//
// empty format functor
template< typename CharT >
struct empty_formatF
{
template< typename ReplaceT >
empty_container<CharT> operator()(const ReplaceT&) const
{
return empty_container<CharT>();
}
};
// dissect format functor ----------------------------------------------------//
// dissect format functor
template<typename FinderT>
struct dissect_formatF
{
public:
// Construction
dissect_formatF(FinderT Finder) :
m_Finder(Finder) {}
// Operation
template<typename RangeT>
inline iterator_range<
BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type>
operator()(const RangeT& Replace) const
{
return m_Finder(::boost::begin(Replace), ::boost::end(Replace));
}
private:
FinderT m_Finder;
};
} // namespace detail
} // namespace algorithm
} // namespace boost
#endif // BOOST_STRING_FORMATTER_DETAIL_HPP

View File

@@ -0,0 +1,61 @@
// Boost string_algo library formatter_regex.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_FORMATTER_REGEX_DETAIL_HPP
#define BOOST_STRING_FORMATTER_REGEX_DETAIL_HPP
#include <boost/algorithm/string/config.hpp>
#include <string>
#include <boost/regex.hpp>
#include <boost/algorithm/string/detail/finder_regex.hpp>
namespace boost {
namespace algorithm {
namespace detail {
// regex format functor -----------------------------------------//
// regex format functor
template<typename StringT>
struct regex_formatF
{
private:
typedef StringT result_type;
typedef BOOST_STRING_TYPENAME StringT::value_type char_type;
public:
// Construction
regex_formatF( const StringT& Fmt, match_flag_type Flags=format_default ) :
m_Fmt(Fmt), m_Flags( Flags ) {}
template<typename InputIteratorT>
result_type operator()(
const regex_search_result<InputIteratorT>& Replace ) const
{
if ( Replace.empty() )
{
return result_type();
}
else
{
return Replace.match_results().format( m_Fmt, m_Flags );
}
}
private:
const StringT& m_Fmt;
match_flag_type m_Flags;
};
} // namespace detail
} // namespace algorithm
} // namespace boost
#endif // BOOST_STRING_FORMATTER_DETAIL_HPP

View File

@@ -0,0 +1,77 @@
// Boost string_algo library predicate.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_PREDICATE_DETAIL_HPP
#define BOOST_STRING_PREDICATE_DETAIL_HPP
#include <iterator>
#include <boost/algorithm/string/find.hpp>
namespace boost {
namespace algorithm {
namespace detail {
// ends_with predicate implementation ----------------------------------//
template<
typename ForwardIterator1T,
typename ForwardIterator2T,
typename PredicateT>
inline bool ends_with_iter_select(
ForwardIterator1T Begin,
ForwardIterator1T End,
ForwardIterator2T SubBegin,
ForwardIterator2T SubEnd,
PredicateT Comp,
std::bidirectional_iterator_tag)
{
ForwardIterator1T it=End;
ForwardIterator2T pit=SubEnd;
for(;it!=Begin && pit!=SubBegin;)
{
if( !(Comp(*(--it),*(--pit))) )
return false;
}
return pit==SubBegin;
}
template<
typename ForwardIterator1T,
typename ForwardIterator2T,
typename PredicateT>
inline bool ends_with_iter_select(
ForwardIterator1T Begin,
ForwardIterator1T End,
ForwardIterator2T SubBegin,
ForwardIterator2T SubEnd,
PredicateT Comp,
std::forward_iterator_tag)
{
if ( SubBegin==SubEnd )
{
// empty subsequence check
return true;
}
iterator_range<ForwardIterator1T> Result
=last_finder(
::boost::make_iterator_range(SubBegin, SubEnd),
Comp)(Begin, End);
return !Result.empty() && Result.end()==End;
}
} // namespace detail
} // namespace algorithm
} // namespace boost
#endif // BOOST_STRING_PREDICATE_DETAIL_HPP

View File

@@ -0,0 +1,159 @@
// Boost string_algo library replace_storage.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_REPLACE_STORAGE_DETAIL_HPP
#define BOOST_STRING_REPLACE_STORAGE_DETAIL_HPP
#include <boost/algorithm/string/config.hpp>
#include <algorithm>
#include <boost/mpl/bool.hpp>
#include <boost/algorithm/string/sequence_traits.hpp>
#include <boost/algorithm/string/detail/sequence.hpp>
namespace boost {
namespace algorithm {
namespace detail {
// storage handling routines -----------------------------------------------//
template< typename StorageT, typename OutputIteratorT >
inline OutputIteratorT move_from_storage(
StorageT& Storage,
OutputIteratorT DestBegin,
OutputIteratorT DestEnd )
{
OutputIteratorT OutputIt=DestBegin;
while( !Storage.empty() && OutputIt!=DestEnd )
{
*OutputIt=Storage.front();
Storage.pop_front();
++OutputIt;
}
return OutputIt;
}
template< typename StorageT, typename WhatT >
inline void copy_to_storage(
StorageT& Storage,
const WhatT& What )
{
Storage.insert( Storage.end(), ::boost::begin(What), ::boost::end(What) );
}
// process segment routine -----------------------------------------------//
template< bool HasStableIterators >
struct process_segment_helper
{
// Optimized version of process_segment for generic sequence
template<
typename StorageT,
typename InputT,
typename ForwardIteratorT >
ForwardIteratorT operator()(
StorageT& Storage,
InputT& /*Input*/,
ForwardIteratorT InsertIt,
ForwardIteratorT SegmentBegin,
ForwardIteratorT SegmentEnd )
{
// Copy data from the storage until the beginning of the segment
ForwardIteratorT It=::boost::algorithm::detail::move_from_storage( Storage, InsertIt, SegmentBegin );
// 3 cases are possible :
// a) Storage is empty, It==SegmentBegin
// b) Storage is empty, It!=SegmentBegin
// c) Storage is not empty
if( Storage.empty() )
{
if( It==SegmentBegin )
{
// Case a) everything is grand, just return end of segment
return SegmentEnd;
}
else
{
// Case b) move the segment backwards
return std::copy( SegmentBegin, SegmentEnd, It );
}
}
else
{
// Case c) -> shift the segment to the left and keep the overlap in the storage
while( It!=SegmentEnd )
{
// Store value into storage
Storage.push_back( *It );
// Get the top from the storage and put it here
*It=Storage.front();
Storage.pop_front();
// Advance
++It;
}
return It;
}
}
};
template<>
struct process_segment_helper< true >
{
// Optimized version of process_segment for list-like sequence
template<
typename StorageT,
typename InputT,
typename ForwardIteratorT >
ForwardIteratorT operator()(
StorageT& Storage,
InputT& Input,
ForwardIteratorT InsertIt,
ForwardIteratorT SegmentBegin,
ForwardIteratorT SegmentEnd )
{
// Call replace to do the job
::boost::algorithm::detail::replace( Input, InsertIt, SegmentBegin, Storage );
// Empty the storage
Storage.clear();
// Iterators were not changed, simply return the end of segment
return SegmentEnd;
}
};
// Process one segment in the replace_all algorithm
template<
typename StorageT,
typename InputT,
typename ForwardIteratorT >
inline ForwardIteratorT process_segment(
StorageT& Storage,
InputT& Input,
ForwardIteratorT InsertIt,
ForwardIteratorT SegmentBegin,
ForwardIteratorT SegmentEnd )
{
return
process_segment_helper<
has_stable_iterators<InputT>::value>()(
Storage, Input, InsertIt, SegmentBegin, SegmentEnd );
}
} // namespace detail
} // namespace algorithm
} // namespace boost
#endif // BOOST_STRING_REPLACE_STORAGE_DETAIL_HPP

View File

@@ -0,0 +1,200 @@
// Boost string_algo library sequence.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_DETAIL_SEQUENCE_HPP
#define BOOST_STRING_DETAIL_SEQUENCE_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/logical.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/algorithm/string/sequence_traits.hpp>
namespace boost {
namespace algorithm {
namespace detail {
// insert helpers -------------------------------------------------//
template< typename InputT, typename ForwardIteratorT >
inline void insert(
InputT& Input,
BOOST_STRING_TYPENAME InputT::iterator At,
ForwardIteratorT Begin,
ForwardIteratorT End )
{
Input.insert( At, Begin, End );
}
template< typename InputT, typename InsertT >
inline void insert(
InputT& Input,
BOOST_STRING_TYPENAME InputT::iterator At,
const InsertT& Insert )
{
::boost::algorithm::detail::insert( Input, At, ::boost::begin(Insert), ::boost::end(Insert) );
}
// erase helper ---------------------------------------------------//
// Erase a range in the sequence
/*
Returns the iterator pointing just after the erase subrange
*/
template< typename InputT >
inline typename InputT::iterator erase(
InputT& Input,
BOOST_STRING_TYPENAME InputT::iterator From,
BOOST_STRING_TYPENAME InputT::iterator To )
{
return Input.erase( From, To );
}
// replace helper implementation ----------------------------------//
// Optimized version of replace for generic sequence containers
// Assumption: insert and erase are expensive
template< bool HasConstTimeOperations >
struct replace_const_time_helper
{
template< typename InputT, typename ForwardIteratorT >
void operator()(
InputT& Input,
BOOST_STRING_TYPENAME InputT::iterator From,
BOOST_STRING_TYPENAME InputT::iterator To,
ForwardIteratorT Begin,
ForwardIteratorT End )
{
// Copy data to the container ( as much as possible )
ForwardIteratorT InsertIt=Begin;
BOOST_STRING_TYPENAME InputT::iterator InputIt=From;
for(; InsertIt!=End && InputIt!=To; InsertIt++, InputIt++ )
{
*InputIt=*InsertIt;
}
if ( InsertIt!=End )
{
// Replace sequence is longer, insert it
Input.insert( InputIt, InsertIt, End );
}
else
{
if ( InputIt!=To )
{
// Replace sequence is shorter, erase the rest
Input.erase( InputIt, To );
}
}
}
};
template<>
struct replace_const_time_helper< true >
{
// Const-time erase and insert methods -> use them
template< typename InputT, typename ForwardIteratorT >
void operator()(
InputT& Input,
BOOST_STRING_TYPENAME InputT::iterator From,
BOOST_STRING_TYPENAME InputT::iterator To,
ForwardIteratorT Begin,
ForwardIteratorT End )
{
BOOST_STRING_TYPENAME InputT::iterator At=Input.erase( From, To );
if ( Begin!=End )
{
if(!Input.empty())
{
Input.insert( At, Begin, End );
}
else
{
Input.insert( Input.begin(), Begin, End );
}
}
}
};
// No native replace method
template< bool HasNative >
struct replace_native_helper
{
template< typename InputT, typename ForwardIteratorT >
void operator()(
InputT& Input,
BOOST_STRING_TYPENAME InputT::iterator From,
BOOST_STRING_TYPENAME InputT::iterator To,
ForwardIteratorT Begin,
ForwardIteratorT End )
{
replace_const_time_helper<
boost::mpl::and_<
has_const_time_insert<InputT>,
has_const_time_erase<InputT> >::value >()(
Input, From, To, Begin, End );
}
};
// Container has native replace method
template<>
struct replace_native_helper< true >
{
template< typename InputT, typename ForwardIteratorT >
void operator()(
InputT& Input,
BOOST_STRING_TYPENAME InputT::iterator From,
BOOST_STRING_TYPENAME InputT::iterator To,
ForwardIteratorT Begin,
ForwardIteratorT End )
{
Input.replace( From, To, Begin, End );
}
};
// replace helper -------------------------------------------------//
template< typename InputT, typename ForwardIteratorT >
inline void replace(
InputT& Input,
BOOST_STRING_TYPENAME InputT::iterator From,
BOOST_STRING_TYPENAME InputT::iterator To,
ForwardIteratorT Begin,
ForwardIteratorT End )
{
replace_native_helper< has_native_replace<InputT>::value >()(
Input, From, To, Begin, End );
}
template< typename InputT, typename InsertT >
inline void replace(
InputT& Input,
BOOST_STRING_TYPENAME InputT::iterator From,
BOOST_STRING_TYPENAME InputT::iterator To,
const InsertT& Insert )
{
if(From!=To)
{
::boost::algorithm::detail::replace( Input, From, To, ::boost::begin(Insert), ::boost::end(Insert) );
}
else
{
::boost::algorithm::detail::insert( Input, From, ::boost::begin(Insert), ::boost::end(Insert) );
}
}
} // namespace detail
} // namespace algorithm
} // namespace boost
#endif // BOOST_STRING_DETAIL_SEQUENCE_HPP

View File

@@ -0,0 +1,95 @@
// Boost string_algo library trim.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_TRIM_DETAIL_HPP
#define BOOST_STRING_TRIM_DETAIL_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/detail/iterator.hpp>
namespace boost {
namespace algorithm {
namespace detail {
// trim iterator helper -----------------------------------------------//
template< typename ForwardIteratorT, typename PredicateT >
inline ForwardIteratorT trim_end_iter_select(
ForwardIteratorT InBegin,
ForwardIteratorT InEnd,
PredicateT IsSpace,
std::forward_iterator_tag )
{
ForwardIteratorT TrimIt=InBegin;
for( ForwardIteratorT It=InBegin; It!=InEnd; ++It )
{
if ( !IsSpace(*It) )
{
TrimIt=It;
++TrimIt;
}
}
return TrimIt;
}
template< typename ForwardIteratorT, typename PredicateT >
inline ForwardIteratorT trim_end_iter_select(
ForwardIteratorT InBegin,
ForwardIteratorT InEnd,
PredicateT IsSpace,
std::bidirectional_iterator_tag )
{
for( ForwardIteratorT It=InEnd; It!=InBegin; )
{
if ( !IsSpace(*(--It)) )
return ++It;
}
return InBegin;
}
// Search for first non matching character from the beginning of the sequence
template< typename ForwardIteratorT, typename PredicateT >
inline ForwardIteratorT trim_begin(
ForwardIteratorT InBegin,
ForwardIteratorT InEnd,
PredicateT IsSpace )
{
ForwardIteratorT It=InBegin;
for(; It!=InEnd; ++It )
{
if (!IsSpace(*It))
return It;
}
return It;
}
// Search for first non matching character from the end of the sequence
template< typename ForwardIteratorT, typename PredicateT >
inline ForwardIteratorT trim_end(
ForwardIteratorT InBegin,
ForwardIteratorT InEnd,
PredicateT IsSpace )
{
typedef BOOST_STRING_TYPENAME boost::detail::
iterator_traits<ForwardIteratorT>::iterator_category category;
return ::boost::algorithm::detail::trim_end_iter_select( InBegin, InEnd, IsSpace, category() );
}
} // namespace detail
} // namespace algorithm
} // namespace boost
#endif // BOOST_STRING_TRIM_DETAIL_HPP

View File

@@ -0,0 +1,106 @@
// Boost string_algo library util.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_UTIL_DETAIL_HPP
#define BOOST_STRING_UTIL_DETAIL_HPP
#include <boost/algorithm/string/config.hpp>
#include <functional>
#include <boost/range/iterator_range_core.hpp>
namespace boost {
namespace algorithm {
namespace detail {
// empty container -----------------------------------------------//
// empty_container
/*
This class represents always empty container,
containing elements of type CharT.
It is supposed to be used in a const version only
*/
template< typename CharT >
struct empty_container
{
typedef empty_container<CharT> type;
typedef CharT value_type;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef const value_type& reference;
typedef const value_type& const_reference;
typedef const value_type* iterator;
typedef const value_type* const_iterator;
// Operations
const_iterator begin() const
{
return reinterpret_cast<const_iterator>(0);
}
const_iterator end() const
{
return reinterpret_cast<const_iterator>(0);
}
bool empty() const
{
return false;
}
size_type size() const
{
return 0;
}
};
// bounded copy algorithm -----------------------------------------------//
// Bounded version of the std::copy algorithm
template<typename InputIteratorT, typename OutputIteratorT>
inline OutputIteratorT bounded_copy(
InputIteratorT First,
InputIteratorT Last,
OutputIteratorT DestFirst,
OutputIteratorT DestLast )
{
InputIteratorT InputIt=First;
OutputIteratorT OutputIt=DestFirst;
for(; InputIt!=Last && OutputIt!=DestLast; InputIt++, OutputIt++ )
{
*OutputIt=*InputIt;
}
return OutputIt;
}
// iterator range utilities -----------------------------------------//
// copy range functor
template<
typename SeqT,
typename IteratorT=BOOST_STRING_TYPENAME SeqT::const_iterator >
struct copy_iterator_rangeF :
public std::unary_function< iterator_range<IteratorT>, SeqT >
{
SeqT operator()( const iterator_range<IteratorT>& Range ) const
{
return copy_range<SeqT>(Range);
}
};
} // namespace detail
} // namespace algorithm
} // namespace boost
#endif // BOOST_STRING_UTIL_DETAIL_HPP

View File

@@ -0,0 +1,844 @@
// Boost string_algo library erase.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2006.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_ERASE_HPP
#define BOOST_STRING_ERASE_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/range/iterator_range_core.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/iterator.hpp>
#include <boost/range/const_iterator.hpp>
#include <boost/algorithm/string/find_format.hpp>
#include <boost/algorithm/string/finder.hpp>
#include <boost/algorithm/string/formatter.hpp>
/*! \file
Defines various erase algorithms. Each algorithm removes
part(s) of the input according to a searching criteria.
*/
namespace boost {
namespace algorithm {
// erase_range -------------------------------------------------------//
//! Erase range algorithm
/*!
Remove the given range from the input. The result is a modified copy of
the input. It is returned as a sequence or copied to the output iterator.
\param Output An output iterator to which the result will be copied
\param Input An input sequence
\param SearchRange A range in the input to be removed
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<typename OutputIteratorT, typename RangeT>
inline OutputIteratorT erase_range_copy(
OutputIteratorT Output,
const RangeT& Input,
const iterator_range<
BOOST_STRING_TYPENAME
range_const_iterator<RangeT>::type>& SearchRange )
{
return ::boost::algorithm::find_format_copy(
Output,
Input,
::boost::algorithm::range_finder(SearchRange),
::boost::algorithm::empty_formatter(Input) );
}
//! Erase range algorithm
/*!
\overload
*/
template<typename SequenceT>
inline SequenceT erase_range_copy(
const SequenceT& Input,
const iterator_range<
BOOST_STRING_TYPENAME
range_const_iterator<SequenceT>::type>& SearchRange )
{
return ::boost::algorithm::find_format_copy(
Input,
::boost::algorithm::range_finder(SearchRange),
::boost::algorithm::empty_formatter(Input) );
}
//! Erase range algorithm
/*!
Remove the given range from the input.
The input sequence is modified in-place.
\param Input An input sequence
\param SearchRange A range in the input to be removed
*/
template<typename SequenceT>
inline void erase_range(
SequenceT& Input,
const iterator_range<
BOOST_STRING_TYPENAME
range_iterator<SequenceT>::type>& SearchRange )
{
::boost::algorithm::find_format(
Input,
::boost::algorithm::range_finder(SearchRange),
::boost::algorithm::empty_formatter(Input) );
}
// erase_first --------------------------------------------------------//
//! Erase first algorithm
/*!
Remove the first occurrence of the substring from the input.
The result is a modified copy of the input. It is returned as a sequence
or copied to the output iterator.
\param Output An output iterator to which the result will be copied
\param Input An input string
\param Search A substring to be searched for
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<
typename OutputIteratorT,
typename Range1T,
typename Range2T>
inline OutputIteratorT erase_first_copy(
OutputIteratorT Output,
const Range1T& Input,
const Range2T& Search )
{
return ::boost::algorithm::find_format_copy(
Output,
Input,
::boost::algorithm::first_finder(Search),
::boost::algorithm::empty_formatter(Input) );
}
//! Erase first algorithm
/*!
\overload
*/
template<typename SequenceT, typename RangeT>
inline SequenceT erase_first_copy(
const SequenceT& Input,
const RangeT& Search )
{
return ::boost::algorithm::find_format_copy(
Input,
::boost::algorithm::first_finder(Search),
::boost::algorithm::empty_formatter(Input) );
}
//! Erase first algorithm
/*!
Remove the first occurrence of the substring from the input.
The input sequence is modified in-place.
\param Input An input string
\param Search A substring to be searched for.
*/
template<typename SequenceT, typename RangeT>
inline void erase_first(
SequenceT& Input,
const RangeT& Search )
{
::boost::algorithm::find_format(
Input,
::boost::algorithm::first_finder(Search),
::boost::algorithm::empty_formatter(Input) );
}
// erase_first ( case insensitive ) ------------------------------------//
//! Erase first algorithm ( case insensitive )
/*!
Remove the first occurrence of the substring from the input.
The result is a modified copy of the input. It is returned as a sequence
or copied to the output iterator.
Searching is case insensitive.
\param Output An output iterator to which the result will be copied
\param Input An input string
\param Search A substring to be searched for
\param Loc A locale used for case insensitive comparison
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<
typename OutputIteratorT,
typename Range1T,
typename Range2T>
inline OutputIteratorT ierase_first_copy(
OutputIteratorT Output,
const Range1T& Input,
const Range2T& Search,
const std::locale& Loc=std::locale() )
{
return ::boost::algorithm::find_format_copy(
Output,
Input,
::boost::algorithm::first_finder(Search, is_iequal(Loc)),
::boost::algorithm::empty_formatter(Input) );
}
//! Erase first algorithm ( case insensitive )
/*!
\overload
*/
template<typename SequenceT, typename RangeT>
inline SequenceT ierase_first_copy(
const SequenceT& Input,
const RangeT& Search,
const std::locale& Loc=std::locale() )
{
return ::boost::algorithm::find_format_copy(
Input,
::boost::algorithm::first_finder(Search, is_iequal(Loc)),
::boost::algorithm::empty_formatter(Input) );
}
//! Erase first algorithm ( case insensitive )
/*!
Remove the first occurrence of the substring from the input.
The input sequence is modified in-place. Searching is case insensitive.
\param Input An input string
\param Search A substring to be searched for
\param Loc A locale used for case insensitive comparison
*/
template<typename SequenceT, typename RangeT>
inline void ierase_first(
SequenceT& Input,
const RangeT& Search,
const std::locale& Loc=std::locale() )
{
::boost::algorithm::find_format(
Input,
::boost::algorithm::first_finder(Search, is_iequal(Loc)),
::boost::algorithm::empty_formatter(Input) );
}
// erase_last --------------------------------------------------------//
//! Erase last algorithm
/*!
Remove the last occurrence of the substring from the input.
The result is a modified copy of the input. It is returned as a sequence
or copied to the output iterator.
\param Output An output iterator to which the result will be copied
\param Input An input string
\param Search A substring to be searched for.
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<
typename OutputIteratorT,
typename Range1T,
typename Range2T>
inline OutputIteratorT erase_last_copy(
OutputIteratorT Output,
const Range1T& Input,
const Range2T& Search )
{
return ::boost::algorithm::find_format_copy(
Output,
Input,
::boost::algorithm::last_finder(Search),
::boost::algorithm::empty_formatter(Input) );
}
//! Erase last algorithm
/*!
\overload
*/
template<typename SequenceT, typename RangeT>
inline SequenceT erase_last_copy(
const SequenceT& Input,
const RangeT& Search )
{
return ::boost::algorithm::find_format_copy(
Input,
::boost::algorithm::last_finder(Search),
::boost::algorithm::empty_formatter(Input) );
}
//! Erase last algorithm
/*!
Remove the last occurrence of the substring from the input.
The input sequence is modified in-place.
\param Input An input string
\param Search A substring to be searched for
*/
template<typename SequenceT, typename RangeT>
inline void erase_last(
SequenceT& Input,
const RangeT& Search )
{
::boost::algorithm::find_format(
Input,
::boost::algorithm::last_finder(Search),
::boost::algorithm::empty_formatter(Input) );
}
// erase_last ( case insensitive ) ------------------------------------//
//! Erase last algorithm ( case insensitive )
/*!
Remove the last occurrence of the substring from the input.
The result is a modified copy of the input. It is returned as a sequence
or copied to the output iterator.
Searching is case insensitive.
\param Output An output iterator to which the result will be copied
\param Input An input string
\param Search A substring to be searched for
\param Loc A locale used for case insensitive comparison
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<
typename OutputIteratorT,
typename Range1T,
typename Range2T>
inline OutputIteratorT ierase_last_copy(
OutputIteratorT Output,
const Range1T& Input,
const Range2T& Search,
const std::locale& Loc=std::locale() )
{
return ::boost::algorithm::find_format_copy(
Output,
Input,
::boost::algorithm::last_finder(Search, is_iequal(Loc)),
::boost::algorithm::empty_formatter(Input) );
}
//! Erase last algorithm ( case insensitive )
/*!
\overload
*/
template<typename SequenceT, typename RangeT>
inline SequenceT ierase_last_copy(
const SequenceT& Input,
const RangeT& Search,
const std::locale& Loc=std::locale() )
{
return ::boost::algorithm::find_format_copy(
Input,
::boost::algorithm::last_finder(Search, is_iequal(Loc)),
::boost::algorithm::empty_formatter(Input) );
}
//! Erase last algorithm ( case insensitive )
/*!
Remove the last occurrence of the substring from the input.
The input sequence is modified in-place. Searching is case insensitive.
\param Input An input string
\param Search A substring to be searched for
\param Loc A locale used for case insensitive comparison
*/
template<typename SequenceT, typename RangeT>
inline void ierase_last(
SequenceT& Input,
const RangeT& Search,
const std::locale& Loc=std::locale() )
{
::boost::algorithm::find_format(
Input,
::boost::algorithm::last_finder(Search, is_iequal(Loc)),
::boost::algorithm::empty_formatter(Input) );
}
// erase_nth --------------------------------------------------------------------//
//! Erase nth algorithm
/*!
Remove the Nth occurrence of the substring in the input.
The result is a modified copy of the input. It is returned as a sequence
or copied to the output iterator.
\param Output An output iterator to which the result will be copied
\param Input An input string
\param Search A substring to be searched for
\param Nth An index of the match to be replaced. The index is 0-based.
For negative N, matches are counted from the end of string.
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<
typename OutputIteratorT,
typename Range1T,
typename Range2T>
inline OutputIteratorT erase_nth_copy(
OutputIteratorT Output,
const Range1T& Input,
const Range2T& Search,
int Nth )
{
return ::boost::algorithm::find_format_copy(
Output,
Input,
::boost::algorithm::nth_finder(Search, Nth),
::boost::algorithm::empty_formatter(Input) );
}
//! Erase nth algorithm
/*!
\overload
*/
template<typename SequenceT, typename RangeT>
inline SequenceT erase_nth_copy(
const SequenceT& Input,
const RangeT& Search,
int Nth )
{
return ::boost::algorithm::find_format_copy(
Input,
::boost::algorithm::nth_finder(Search, Nth),
::boost::algorithm::empty_formatter(Input) );
}
//! Erase nth algorithm
/*!
Remove the Nth occurrence of the substring in the input.
The input sequence is modified in-place.
\param Input An input string
\param Search A substring to be searched for.
\param Nth An index of the match to be replaced. The index is 0-based.
For negative N, matches are counted from the end of string.
*/
template<typename SequenceT, typename RangeT>
inline void erase_nth(
SequenceT& Input,
const RangeT& Search,
int Nth )
{
::boost::algorithm::find_format(
Input,
::boost::algorithm::nth_finder(Search, Nth),
::boost::algorithm::empty_formatter(Input) );
}
// erase_nth ( case insensitive ) ---------------------------------------------//
//! Erase nth algorithm ( case insensitive )
/*!
Remove the Nth occurrence of the substring in the input.
The result is a modified copy of the input. It is returned as a sequence
or copied to the output iterator.
Searching is case insensitive.
\param Output An output iterator to which the result will be copied
\param Input An input string
\param Search A substring to be searched for.
\param Nth An index of the match to be replaced. The index is 0-based.
For negative N, matches are counted from the end of string.
\param Loc A locale used for case insensitive comparison
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<
typename OutputIteratorT,
typename Range1T,
typename Range2T>
inline OutputIteratorT ierase_nth_copy(
OutputIteratorT Output,
const Range1T& Input,
const Range2T& Search,
int Nth,
const std::locale& Loc=std::locale() )
{
return ::boost::algorithm::find_format_copy(
Output,
Input,
::boost::algorithm::nth_finder(Search, Nth, is_iequal(Loc)),
::boost::algorithm::empty_formatter(Input) );
}
//! Erase nth algorithm
/*!
\overload
*/
template<typename SequenceT, typename RangeT>
inline SequenceT ierase_nth_copy(
const SequenceT& Input,
const RangeT& Search,
int Nth,
const std::locale& Loc=std::locale() )
{
return ::boost::algorithm::find_format_copy(
Input,
::boost::algorithm::nth_finder(Search, Nth, is_iequal(Loc)),
empty_formatter(Input) );
}
//! Erase nth algorithm
/*!
Remove the Nth occurrence of the substring in the input.
The input sequence is modified in-place. Searching is case insensitive.
\param Input An input string
\param Search A substring to be searched for.
\param Nth An index of the match to be replaced. The index is 0-based.
For negative N, matches are counted from the end of string.
\param Loc A locale used for case insensitive comparison
*/
template<typename SequenceT, typename RangeT>
inline void ierase_nth(
SequenceT& Input,
const RangeT& Search,
int Nth,
const std::locale& Loc=std::locale() )
{
::boost::algorithm::find_format(
Input,
::boost::algorithm::nth_finder(Search, Nth, is_iequal(Loc)),
::boost::algorithm::empty_formatter(Input) );
}
// erase_all --------------------------------------------------------//
//! Erase all algorithm
/*!
Remove all the occurrences of the string from the input.
The result is a modified copy of the input. It is returned as a sequence
or copied to the output iterator.
\param Output An output iterator to which the result will be copied
\param Input An input sequence
\param Search A substring to be searched for.
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<
typename OutputIteratorT,
typename Range1T,
typename Range2T>
inline OutputIteratorT erase_all_copy(
OutputIteratorT Output,
const Range1T& Input,
const Range2T& Search )
{
return ::boost::algorithm::find_format_all_copy(
Output,
Input,
::boost::algorithm::first_finder(Search),
::boost::algorithm::empty_formatter(Input) );
}
//! Erase all algorithm
/*!
\overload
*/
template<typename SequenceT, typename RangeT>
inline SequenceT erase_all_copy(
const SequenceT& Input,
const RangeT& Search )
{
return ::boost::algorithm::find_format_all_copy(
Input,
::boost::algorithm::first_finder(Search),
::boost::algorithm::empty_formatter(Input) );
}
//! Erase all algorithm
/*!
Remove all the occurrences of the string from the input.
The input sequence is modified in-place.
\param Input An input string
\param Search A substring to be searched for.
*/
template<typename SequenceT, typename RangeT>
inline void erase_all(
SequenceT& Input,
const RangeT& Search )
{
::boost::algorithm::find_format_all(
Input,
::boost::algorithm::first_finder(Search),
::boost::algorithm::empty_formatter(Input) );
}
// erase_all ( case insensitive ) ------------------------------------//
//! Erase all algorithm ( case insensitive )
/*!
Remove all the occurrences of the string from the input.
The result is a modified copy of the input. It is returned as a sequence
or copied to the output iterator.
Searching is case insensitive.
\param Output An output iterator to which the result will be copied
\param Input An input string
\param Search A substring to be searched for
\param Loc A locale used for case insensitive comparison
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<
typename OutputIteratorT,
typename Range1T,
typename Range2T>
inline OutputIteratorT ierase_all_copy(
OutputIteratorT Output,
const Range1T& Input,
const Range2T& Search,
const std::locale& Loc=std::locale() )
{
return ::boost::algorithm::find_format_all_copy(
Output,
Input,
::boost::algorithm::first_finder(Search, is_iequal(Loc)),
::boost::algorithm::empty_formatter(Input) );
}
//! Erase all algorithm ( case insensitive )
/*!
\overload
*/
template<typename SequenceT, typename RangeT>
inline SequenceT ierase_all_copy(
const SequenceT& Input,
const RangeT& Search,
const std::locale& Loc=std::locale() )
{
return ::boost::algorithm::find_format_all_copy(
Input,
::boost::algorithm::first_finder(Search, is_iequal(Loc)),
::boost::algorithm::empty_formatter(Input) );
}
//! Erase all algorithm ( case insensitive )
/*!
Remove all the occurrences of the string from the input.
The input sequence is modified in-place. Searching is case insensitive.
\param Input An input string
\param Search A substring to be searched for.
\param Loc A locale used for case insensitive comparison
*/
template<typename SequenceT, typename RangeT>
inline void ierase_all(
SequenceT& Input,
const RangeT& Search,
const std::locale& Loc=std::locale() )
{
::boost::algorithm::find_format_all(
Input,
::boost::algorithm::first_finder(Search, is_iequal(Loc)),
::boost::algorithm::empty_formatter(Input) );
}
// erase_head --------------------------------------------------------------------//
//! Erase head algorithm
/*!
Remove the head from the input. The head is a prefix of a sequence of given size.
If the sequence is shorter then required, the whole string is
considered to be the head. The result is a modified copy of the input.
It is returned as a sequence or copied to the output iterator.
\param Output An output iterator to which the result will be copied
\param Input An input string
\param N Length of the head.
For N>=0, at most N characters are extracted.
For N<0, size(Input)-|N| characters are extracted.
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<
typename OutputIteratorT,
typename RangeT>
inline OutputIteratorT erase_head_copy(
OutputIteratorT Output,
const RangeT& Input,
int N )
{
return ::boost::algorithm::find_format_copy(
Output,
Input,
::boost::algorithm::head_finder(N),
::boost::algorithm::empty_formatter( Input ) );
}
//! Erase head algorithm
/*!
\overload
*/
template<typename SequenceT>
inline SequenceT erase_head_copy(
const SequenceT& Input,
int N )
{
return ::boost::algorithm::find_format_copy(
Input,
::boost::algorithm::head_finder(N),
::boost::algorithm::empty_formatter( Input ) );
}
//! Erase head algorithm
/*!
Remove the head from the input. The head is a prefix of a sequence of given size.
If the sequence is shorter then required, the whole string is
considered to be the head. The input sequence is modified in-place.
\param Input An input string
\param N Length of the head
For N>=0, at most N characters are extracted.
For N<0, size(Input)-|N| characters are extracted.
*/
template<typename SequenceT>
inline void erase_head(
SequenceT& Input,
int N )
{
::boost::algorithm::find_format(
Input,
::boost::algorithm::head_finder(N),
::boost::algorithm::empty_formatter( Input ) );
}
// erase_tail --------------------------------------------------------------------//
//! Erase tail algorithm
/*!
Remove the tail from the input. The tail is a suffix of a sequence of given size.
If the sequence is shorter then required, the whole string is
considered to be the tail.
The result is a modified copy of the input. It is returned as a sequence
or copied to the output iterator.
\param Output An output iterator to which the result will be copied
\param Input An input string
\param N Length of the tail.
For N>=0, at most N characters are extracted.
For N<0, size(Input)-|N| characters are extracted.
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<
typename OutputIteratorT,
typename RangeT>
inline OutputIteratorT erase_tail_copy(
OutputIteratorT Output,
const RangeT& Input,
int N )
{
return ::boost::algorithm::find_format_copy(
Output,
Input,
::boost::algorithm::tail_finder(N),
::boost::algorithm::empty_formatter( Input ) );
}
//! Erase tail algorithm
/*!
\overload
*/
template<typename SequenceT>
inline SequenceT erase_tail_copy(
const SequenceT& Input,
int N )
{
return ::boost::algorithm::find_format_copy(
Input,
::boost::algorithm::tail_finder(N),
::boost::algorithm::empty_formatter( Input ) );
}
//! Erase tail algorithm
/*!
Remove the tail from the input. The tail is a suffix of a sequence of given size.
If the sequence is shorter then required, the whole string is
considered to be the tail. The input sequence is modified in-place.
\param Input An input string
\param N Length of the tail
For N>=0, at most N characters are extracted.
For N<0, size(Input)-|N| characters are extracted.
*/
template<typename SequenceT>
inline void erase_tail(
SequenceT& Input,
int N )
{
::boost::algorithm::find_format(
Input,
::boost::algorithm::tail_finder(N),
::boost::algorithm::empty_formatter( Input ) );
}
} // namespace algorithm
// pull names into the boost namespace
using algorithm::erase_range_copy;
using algorithm::erase_range;
using algorithm::erase_first_copy;
using algorithm::erase_first;
using algorithm::ierase_first_copy;
using algorithm::ierase_first;
using algorithm::erase_last_copy;
using algorithm::erase_last;
using algorithm::ierase_last_copy;
using algorithm::ierase_last;
using algorithm::erase_nth_copy;
using algorithm::erase_nth;
using algorithm::ierase_nth_copy;
using algorithm::ierase_nth;
using algorithm::erase_all_copy;
using algorithm::erase_all;
using algorithm::ierase_all_copy;
using algorithm::ierase_all;
using algorithm::erase_head_copy;
using algorithm::erase_head;
using algorithm::erase_tail_copy;
using algorithm::erase_tail;
} // namespace boost
#endif // BOOST_ERASE_HPP

View File

@@ -0,0 +1,334 @@
// Boost string_algo library find.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_FIND_HPP
#define BOOST_STRING_FIND_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/range/iterator_range_core.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/iterator.hpp>
#include <boost/range/as_literal.hpp>
#include <boost/algorithm/string/finder.hpp>
#include <boost/algorithm/string/compare.hpp>
#include <boost/algorithm/string/constants.hpp>
/*! \file
Defines a set of find algorithms. The algorithms are searching
for a substring of the input. The result is given as an \c iterator_range
delimiting the substring.
*/
namespace boost {
namespace algorithm {
// Generic find -----------------------------------------------//
//! Generic find algorithm
/*!
Search the input using the given finder.
\param Input A string which will be searched.
\param Finder Finder object used for searching.
\return
An \c iterator_range delimiting the match.
Returned iterator is either \c RangeT::iterator or
\c RangeT::const_iterator, depending on the constness of
the input parameter.
*/
template<typename RangeT, typename FinderT>
inline iterator_range<
BOOST_STRING_TYPENAME range_iterator<RangeT>::type>
find(
RangeT& Input,
const FinderT& Finder)
{
iterator_range<BOOST_STRING_TYPENAME range_iterator<RangeT>::type> lit_input(::boost::as_literal(Input));
return Finder(::boost::begin(lit_input),::boost::end(lit_input));
}
// find_first -----------------------------------------------//
//! Find first algorithm
/*!
Search for the first occurrence of the substring in the input.
\param Input A string which will be searched.
\param Search A substring to be searched for.
\return
An \c iterator_range delimiting the match.
Returned iterator is either \c RangeT::iterator or
\c RangeT::const_iterator, depending on the constness of
the input parameter.
\note This function provides the strong exception-safety guarantee
*/
template<typename Range1T, typename Range2T>
inline iterator_range<
BOOST_STRING_TYPENAME range_iterator<Range1T>::type>
find_first(
Range1T& Input,
const Range2T& Search)
{
return ::boost::algorithm::find(Input, ::boost::algorithm::first_finder(Search));
}
//! Find first algorithm ( case insensitive )
/*!
Search for the first occurrence of the substring in the input.
Searching is case insensitive.
\param Input A string which will be searched.
\param Search A substring to be searched for.
\param Loc A locale used for case insensitive comparison
\return
An \c iterator_range delimiting the match.
Returned iterator is either \c Range1T::iterator or
\c Range1T::const_iterator, depending on the constness of
the input parameter.
\note This function provides the strong exception-safety guarantee
*/
template<typename Range1T, typename Range2T>
inline iterator_range<
BOOST_STRING_TYPENAME range_iterator<Range1T>::type>
ifind_first(
Range1T& Input,
const Range2T& Search,
const std::locale& Loc=std::locale())
{
return ::boost::algorithm::find(Input, ::boost::algorithm::first_finder(Search,is_iequal(Loc)));
}
// find_last -----------------------------------------------//
//! Find last algorithm
/*!
Search for the last occurrence of the substring in the input.
\param Input A string which will be searched.
\param Search A substring to be searched for.
\return
An \c iterator_range delimiting the match.
Returned iterator is either \c Range1T::iterator or
\c Range1T::const_iterator, depending on the constness of
the input parameter.
\note This function provides the strong exception-safety guarantee
*/
template<typename Range1T, typename Range2T>
inline iterator_range<
BOOST_STRING_TYPENAME range_iterator<Range1T>::type>
find_last(
Range1T& Input,
const Range2T& Search)
{
return ::boost::algorithm::find(Input, ::boost::algorithm::last_finder(Search));
}
//! Find last algorithm ( case insensitive )
/*!
Search for the last match a string in the input.
Searching is case insensitive.
\param Input A string which will be searched.
\param Search A substring to be searched for.
\param Loc A locale used for case insensitive comparison
\return
An \c iterator_range delimiting the match.
Returned iterator is either \c Range1T::iterator or
\c Range1T::const_iterator, depending on the constness of
the input parameter.
\note This function provides the strong exception-safety guarantee
*/
template<typename Range1T, typename Range2T>
inline iterator_range<
BOOST_STRING_TYPENAME range_iterator<Range1T>::type>
ifind_last(
Range1T& Input,
const Range2T& Search,
const std::locale& Loc=std::locale())
{
return ::boost::algorithm::find(Input, ::boost::algorithm::last_finder(Search, is_iequal(Loc)));
}
// find_nth ----------------------------------------------------------------------//
//! Find n-th algorithm
/*!
Search for the n-th (zero-indexed) occurrence of the substring in the
input.
\param Input A string which will be searched.
\param Search A substring to be searched for.
\param Nth An index (zero-indexed) of the match to be found.
For negative N, the matches are counted from the end of string.
\return
An \c iterator_range delimiting the match.
Returned iterator is either \c Range1T::iterator or
\c Range1T::const_iterator, depending on the constness of
the input parameter.
*/
template<typename Range1T, typename Range2T>
inline iterator_range<
BOOST_STRING_TYPENAME range_iterator<Range1T>::type>
find_nth(
Range1T& Input,
const Range2T& Search,
int Nth)
{
return ::boost::algorithm::find(Input, ::boost::algorithm::nth_finder(Search,Nth));
}
//! Find n-th algorithm ( case insensitive ).
/*!
Search for the n-th (zero-indexed) occurrence of the substring in the
input. Searching is case insensitive.
\param Input A string which will be searched.
\param Search A substring to be searched for.
\param Nth An index (zero-indexed) of the match to be found.
For negative N, the matches are counted from the end of string.
\param Loc A locale used for case insensitive comparison
\return
An \c iterator_range delimiting the match.
Returned iterator is either \c Range1T::iterator or
\c Range1T::const_iterator, depending on the constness of
the input parameter.
\note This function provides the strong exception-safety guarantee
*/
template<typename Range1T, typename Range2T>
inline iterator_range<
BOOST_STRING_TYPENAME range_iterator<Range1T>::type>
ifind_nth(
Range1T& Input,
const Range2T& Search,
int Nth,
const std::locale& Loc=std::locale())
{
return ::boost::algorithm::find(Input, ::boost::algorithm::nth_finder(Search,Nth,is_iequal(Loc)));
}
// find_head ----------------------------------------------------------------------//
//! Find head algorithm
/*!
Get the head of the input. Head is a prefix of the string of the
given size. If the input is shorter then required, whole input is considered
to be the head.
\param Input An input string
\param N Length of the head
For N>=0, at most N characters are extracted.
For N<0, at most size(Input)-|N| characters are extracted.
\return
An \c iterator_range delimiting the match.
Returned iterator is either \c Range1T::iterator or
\c Range1T::const_iterator, depending on the constness of
the input parameter.
\note This function provides the strong exception-safety guarantee
*/
template<typename RangeT>
inline iterator_range<
BOOST_STRING_TYPENAME range_iterator<RangeT>::type>
find_head(
RangeT& Input,
int N)
{
return ::boost::algorithm::find(Input, ::boost::algorithm::head_finder(N));
}
// find_tail ----------------------------------------------------------------------//
//! Find tail algorithm
/*!
Get the tail of the input. Tail is a suffix of the string of the
given size. If the input is shorter then required, whole input is considered
to be the tail.
\param Input An input string
\param N Length of the tail.
For N>=0, at most N characters are extracted.
For N<0, at most size(Input)-|N| characters are extracted.
\return
An \c iterator_range delimiting the match.
Returned iterator is either \c RangeT::iterator or
\c RangeT::const_iterator, depending on the constness of
the input parameter.
\note This function provides the strong exception-safety guarantee
*/
template<typename RangeT>
inline iterator_range<
BOOST_STRING_TYPENAME range_iterator<RangeT>::type>
find_tail(
RangeT& Input,
int N)
{
return ::boost::algorithm::find(Input, ::boost::algorithm::tail_finder(N));
}
// find_token --------------------------------------------------------------------//
//! Find token algorithm
/*!
Look for a given token in the string. Token is a character that matches the
given predicate.
If the "token compress mode" is enabled, adjacent tokens are considered to be one match.
\param Input A input string.
\param Pred A unary predicate to identify a token
\param eCompress Enable/Disable compressing of adjacent tokens
\return
An \c iterator_range delimiting the match.
Returned iterator is either \c RangeT::iterator or
\c RangeT::const_iterator, depending on the constness of
the input parameter.
\note This function provides the strong exception-safety guarantee
*/
template<typename RangeT, typename PredicateT>
inline iterator_range<
BOOST_STRING_TYPENAME range_iterator<RangeT>::type>
find_token(
RangeT& Input,
PredicateT Pred,
token_compress_mode_type eCompress=token_compress_off)
{
return ::boost::algorithm::find(Input, ::boost::algorithm::token_finder(Pred, eCompress));
}
} // namespace algorithm
// pull names to the boost namespace
using algorithm::find;
using algorithm::find_first;
using algorithm::ifind_first;
using algorithm::find_last;
using algorithm::ifind_last;
using algorithm::find_nth;
using algorithm::ifind_nth;
using algorithm::find_head;
using algorithm::find_tail;
using algorithm::find_token;
} // namespace boost
#endif // BOOST_STRING_FIND_HPP

View File

@@ -0,0 +1,287 @@
// Boost string_algo library find_format.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_FIND_FORMAT_HPP
#define BOOST_STRING_FIND_FORMAT_HPP
#include <deque>
#include <boost/detail/iterator.hpp>
#include <boost/range/iterator_range_core.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/const_iterator.hpp>
#include <boost/range/as_literal.hpp>
#include <boost/algorithm/string/concept.hpp>
#include <boost/algorithm/string/detail/find_format.hpp>
#include <boost/algorithm/string/detail/find_format_all.hpp>
/*! \file
Defines generic replace algorithms. Each algorithm replaces
part(s) of the input. The part to be replaced is looked up using a Finder object.
Result of finding is then used by a Formatter object to generate the replacement.
*/
namespace boost {
namespace algorithm {
// generic replace -----------------------------------------------------------------//
//! Generic replace algorithm
/*!
Use the Finder to search for a substring. Use the Formatter to format
this substring and replace it in the input.
The result is a modified copy of the input. It is returned as a sequence
or copied to the output iterator.
\param Output An output iterator to which the result will be copied
\param Input An input sequence
\param Finder A Finder object used to search for a match to be replaced
\param Formatter A Formatter object used to format a match
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<
typename OutputIteratorT,
typename RangeT,
typename FinderT,
typename FormatterT>
inline OutputIteratorT find_format_copy(
OutputIteratorT Output,
const RangeT& Input,
FinderT Finder,
FormatterT Formatter )
{
// Concept check
BOOST_CONCEPT_ASSERT((
FinderConcept<
FinderT,
BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type>
));
BOOST_CONCEPT_ASSERT((
FormatterConcept<
FormatterT,
FinderT,BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type>
));
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> lit_input(::boost::as_literal(Input));
return detail::find_format_copy_impl(
Output,
lit_input,
Formatter,
Finder( ::boost::begin(lit_input), ::boost::end(lit_input) ) );
}
//! Generic replace algorithm
/*!
\overload
*/
template<
typename SequenceT,
typename FinderT,
typename FormatterT>
inline SequenceT find_format_copy(
const SequenceT& Input,
FinderT Finder,
FormatterT Formatter )
{
// Concept check
BOOST_CONCEPT_ASSERT((
FinderConcept<
FinderT,
BOOST_STRING_TYPENAME range_const_iterator<SequenceT>::type>
));
BOOST_CONCEPT_ASSERT((
FormatterConcept<
FormatterT,
FinderT,BOOST_STRING_TYPENAME range_const_iterator<SequenceT>::type>
));
return detail::find_format_copy_impl(
Input,
Formatter,
Finder(::boost::begin(Input), ::boost::end(Input)));
}
//! Generic replace algorithm
/*!
Use the Finder to search for a substring. Use the Formatter to format
this substring and replace it in the input. The input is modified in-place.
\param Input An input sequence
\param Finder A Finder object used to search for a match to be replaced
\param Formatter A Formatter object used to format a match
*/
template<
typename SequenceT,
typename FinderT,
typename FormatterT>
inline void find_format(
SequenceT& Input,
FinderT Finder,
FormatterT Formatter)
{
// Concept check
BOOST_CONCEPT_ASSERT((
FinderConcept<
FinderT,
BOOST_STRING_TYPENAME range_const_iterator<SequenceT>::type>
));
BOOST_CONCEPT_ASSERT((
FormatterConcept<
FormatterT,
FinderT,BOOST_STRING_TYPENAME range_const_iterator<SequenceT>::type>
));
detail::find_format_impl(
Input,
Formatter,
Finder(::boost::begin(Input), ::boost::end(Input)));
}
// find_format_all generic ----------------------------------------------------------------//
//! Generic replace all algorithm
/*!
Use the Finder to search for a substring. Use the Formatter to format
this substring and replace it in the input. Repeat this for all matching
substrings.
The result is a modified copy of the input. It is returned as a sequence
or copied to the output iterator.
\param Output An output iterator to which the result will be copied
\param Input An input sequence
\param Finder A Finder object used to search for a match to be replaced
\param Formatter A Formatter object used to format a match
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<
typename OutputIteratorT,
typename RangeT,
typename FinderT,
typename FormatterT>
inline OutputIteratorT find_format_all_copy(
OutputIteratorT Output,
const RangeT& Input,
FinderT Finder,
FormatterT Formatter)
{
// Concept check
BOOST_CONCEPT_ASSERT((
FinderConcept<
FinderT,
BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type>
));
BOOST_CONCEPT_ASSERT((
FormatterConcept<
FormatterT,
FinderT,BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type>
));
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> lit_input(::boost::as_literal(Input));
return detail::find_format_all_copy_impl(
Output,
lit_input,
Finder,
Formatter,
Finder(::boost::begin(lit_input), ::boost::end(lit_input)));
}
//! Generic replace all algorithm
/*!
\overload
*/
template<
typename SequenceT,
typename FinderT,
typename FormatterT >
inline SequenceT find_format_all_copy(
const SequenceT& Input,
FinderT Finder,
FormatterT Formatter )
{
// Concept check
BOOST_CONCEPT_ASSERT((
FinderConcept<
FinderT,
BOOST_STRING_TYPENAME range_const_iterator<SequenceT>::type>
));
BOOST_CONCEPT_ASSERT((
FormatterConcept<
FormatterT,
FinderT,BOOST_STRING_TYPENAME range_const_iterator<SequenceT>::type>
));
return detail::find_format_all_copy_impl(
Input,
Finder,
Formatter,
Finder( ::boost::begin(Input), ::boost::end(Input) ) );
}
//! Generic replace all algorithm
/*!
Use the Finder to search for a substring. Use the Formatter to format
this substring and replace it in the input. Repeat this for all matching
substrings.The input is modified in-place.
\param Input An input sequence
\param Finder A Finder object used to search for a match to be replaced
\param Formatter A Formatter object used to format a match
*/
template<
typename SequenceT,
typename FinderT,
typename FormatterT >
inline void find_format_all(
SequenceT& Input,
FinderT Finder,
FormatterT Formatter )
{
// Concept check
BOOST_CONCEPT_ASSERT((
FinderConcept<
FinderT,
BOOST_STRING_TYPENAME range_const_iterator<SequenceT>::type>
));
BOOST_CONCEPT_ASSERT((
FormatterConcept<
FormatterT,
FinderT,BOOST_STRING_TYPENAME range_const_iterator<SequenceT>::type>
));
detail::find_format_all_impl(
Input,
Finder,
Formatter,
Finder(::boost::begin(Input), ::boost::end(Input)));
}
} // namespace algorithm
// pull the names to the boost namespace
using algorithm::find_format_copy;
using algorithm::find_format;
using algorithm::find_format_all_copy;
using algorithm::find_format_all;
} // namespace boost
#endif // BOOST_STRING_FIND_FORMAT_HPP

View File

@@ -0,0 +1,388 @@
// Boost string_algo library find_iterator.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2004.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_FIND_ITERATOR_HPP
#define BOOST_STRING_FIND_ITERATOR_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/iterator/iterator_categories.hpp>
#include <boost/range/iterator_range_core.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/iterator.hpp>
#include <boost/range/as_literal.hpp>
#include <boost/algorithm/string/detail/find_iterator.hpp>
/*! \file
Defines find iterator classes. Find iterator repeatedly applies a Finder
to the specified input string to search for matches. Dereferencing
the iterator yields the current match or a range between the last and the current
match depending on the iterator used.
*/
namespace boost {
namespace algorithm {
// find_iterator -----------------------------------------------//
//! find_iterator
/*!
Find iterator encapsulates a Finder and allows
for incremental searching in a string.
Each increment moves the iterator to the next match.
Find iterator is a readable forward traversal iterator.
Dereferencing the iterator yields an iterator_range delimiting
the current match.
*/
template<typename IteratorT>
class find_iterator :
public iterator_facade<
find_iterator<IteratorT>,
const iterator_range<IteratorT>,
forward_traversal_tag >,
private detail::find_iterator_base<IteratorT>
{
private:
// facade support
friend class ::boost::iterator_core_access;
private:
// typedefs
typedef detail::find_iterator_base<IteratorT> base_type;
typedef BOOST_STRING_TYPENAME
base_type::input_iterator_type input_iterator_type;
typedef BOOST_STRING_TYPENAME
base_type::match_type match_type;
public:
//! Default constructor
/*!
Construct null iterator. All null iterators are equal.
\post eof()==true
*/
find_iterator() {}
//! Copy constructor
/*!
Construct a copy of the find_iterator
*/
find_iterator( const find_iterator& Other ) :
base_type(Other),
m_Match(Other.m_Match),
m_End(Other.m_End) {}
//! Constructor
/*!
Construct new find_iterator for a given finder
and a range.
*/
template<typename FinderT>
find_iterator(
IteratorT Begin,
IteratorT End,
FinderT Finder ) :
detail::find_iterator_base<IteratorT>(Finder,0),
m_Match(Begin,Begin),
m_End(End)
{
increment();
}
//! Constructor
/*!
Construct new find_iterator for a given finder
and a range.
*/
template<typename FinderT, typename RangeT>
find_iterator(
RangeT& Col,
FinderT Finder ) :
detail::find_iterator_base<IteratorT>(Finder,0)
{
iterator_range<BOOST_STRING_TYPENAME range_iterator<RangeT>::type> lit_col(::boost::as_literal(Col));
m_Match=::boost::make_iterator_range(::boost::begin(lit_col), ::boost::begin(lit_col));
m_End=::boost::end(lit_col);
increment();
}
private:
// iterator operations
// dereference
const match_type& dereference() const
{
return m_Match;
}
// increment
void increment()
{
m_Match=this->do_find(m_Match.end(),m_End);
}
// comparison
bool equal( const find_iterator& Other ) const
{
bool bEof=eof();
bool bOtherEof=Other.eof();
return bEof || bOtherEof ? bEof==bOtherEof :
(
m_Match==Other.m_Match &&
m_End==Other.m_End
);
}
public:
// operations
//! Eof check
/*!
Check the eof condition. Eof condition means that
there is nothing more to be searched i.e. find_iterator
is after the last match.
*/
bool eof() const
{
return
this->is_null() ||
(
m_Match.begin() == m_End &&
m_Match.end() == m_End
);
}
private:
// Attributes
match_type m_Match;
input_iterator_type m_End;
};
//! find iterator construction helper
/*!
* Construct a find iterator to iterate through the specified string
*/
template<typename RangeT, typename FinderT>
inline find_iterator<
BOOST_STRING_TYPENAME range_iterator<RangeT>::type>
make_find_iterator(
RangeT& Collection,
FinderT Finder)
{
return find_iterator<BOOST_STRING_TYPENAME range_iterator<RangeT>::type>(
Collection, Finder);
}
// split iterator -----------------------------------------------//
//! split_iterator
/*!
Split iterator encapsulates a Finder and allows
for incremental searching in a string.
Unlike the find iterator, split iterator iterates
through gaps between matches.
Find iterator is a readable forward traversal iterator.
Dereferencing the iterator yields an iterator_range delimiting
the current match.
*/
template<typename IteratorT>
class split_iterator :
public iterator_facade<
split_iterator<IteratorT>,
const iterator_range<IteratorT>,
forward_traversal_tag >,
private detail::find_iterator_base<IteratorT>
{
private:
// facade support
friend class ::boost::iterator_core_access;
private:
// typedefs
typedef detail::find_iterator_base<IteratorT> base_type;
typedef BOOST_STRING_TYPENAME
base_type::input_iterator_type input_iterator_type;
typedef BOOST_STRING_TYPENAME
base_type::match_type match_type;
public:
//! Default constructor
/*!
Construct null iterator. All null iterators are equal.
\post eof()==true
*/
split_iterator() :
m_Next(),
m_End(),
m_bEof(true)
{}
//! Copy constructor
/*!
Construct a copy of the split_iterator
*/
split_iterator( const split_iterator& Other ) :
base_type(Other),
m_Match(Other.m_Match),
m_Next(Other.m_Next),
m_End(Other.m_End),
m_bEof(Other.m_bEof)
{}
//! Constructor
/*!
Construct new split_iterator for a given finder
and a range.
*/
template<typename FinderT>
split_iterator(
IteratorT Begin,
IteratorT End,
FinderT Finder ) :
detail::find_iterator_base<IteratorT>(Finder,0),
m_Match(Begin,Begin),
m_Next(Begin),
m_End(End),
m_bEof(false)
{
// force the correct behavior for empty sequences and yield at least one token
if(Begin!=End)
{
increment();
}
}
//! Constructor
/*!
Construct new split_iterator for a given finder
and a collection.
*/
template<typename FinderT, typename RangeT>
split_iterator(
RangeT& Col,
FinderT Finder ) :
detail::find_iterator_base<IteratorT>(Finder,0),
m_bEof(false)
{
iterator_range<BOOST_STRING_TYPENAME range_iterator<RangeT>::type> lit_col(::boost::as_literal(Col));
m_Match=make_iterator_range(::boost::begin(lit_col), ::boost::begin(lit_col));
m_Next=::boost::begin(lit_col);
m_End=::boost::end(lit_col);
// force the correct behavior for empty sequences and yield at least one token
if(m_Next!=m_End)
{
increment();
}
}
private:
// iterator operations
// dereference
const match_type& dereference() const
{
return m_Match;
}
// increment
void increment()
{
match_type FindMatch=this->do_find( m_Next, m_End );
if(FindMatch.begin()==m_End && FindMatch.end()==m_End)
{
if(m_Match.end()==m_End)
{
// Mark iterator as eof
m_bEof=true;
}
}
m_Match=match_type( m_Next, FindMatch.begin() );
m_Next=FindMatch.end();
}
// comparison
bool equal( const split_iterator& Other ) const
{
bool bEof=eof();
bool bOtherEof=Other.eof();
return bEof || bOtherEof ? bEof==bOtherEof :
(
m_Match==Other.m_Match &&
m_Next==Other.m_Next &&
m_End==Other.m_End
);
}
public:
// operations
//! Eof check
/*!
Check the eof condition. Eof condition means that
there is nothing more to be searched i.e. find_iterator
is after the last match.
*/
bool eof() const
{
return this->is_null() || m_bEof;
}
private:
// Attributes
match_type m_Match;
input_iterator_type m_Next;
input_iterator_type m_End;
bool m_bEof;
};
//! split iterator construction helper
/*!
* Construct a split iterator to iterate through the specified collection
*/
template<typename RangeT, typename FinderT>
inline split_iterator<
BOOST_STRING_TYPENAME range_iterator<RangeT>::type>
make_split_iterator(
RangeT& Collection,
FinderT Finder)
{
return split_iterator<BOOST_STRING_TYPENAME range_iterator<RangeT>::type>(
Collection, Finder);
}
} // namespace algorithm
// pull names to the boost namespace
using algorithm::find_iterator;
using algorithm::make_find_iterator;
using algorithm::split_iterator;
using algorithm::make_split_iterator;
} // namespace boost
#endif // BOOST_STRING_FIND_ITERATOR_HPP

View File

@@ -0,0 +1,270 @@
// Boost string_algo library finder.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2006.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_FINDER_HPP
#define BOOST_STRING_FINDER_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/range/iterator_range_core.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/iterator.hpp>
#include <boost/range/const_iterator.hpp>
#include <boost/algorithm/string/constants.hpp>
#include <boost/algorithm/string/detail/finder.hpp>
#include <boost/algorithm/string/compare.hpp>
/*! \file
Defines Finder generators. Finder object is a functor which is able to
find a substring matching a specific criteria in the input.
Finders are used as a pluggable components for replace, find
and split facilities. This header contains generator functions
for finders provided in this library.
*/
namespace boost {
namespace algorithm {
// Finder generators ------------------------------------------//
//! "First" finder
/*!
Construct the \c first_finder. The finder searches for the first
occurrence of the string in a given input.
The result is given as an \c iterator_range delimiting the match.
\param Search A substring to be searched for.
\param Comp An element comparison predicate
\return An instance of the \c first_finder object
*/
template<typename RangeT>
inline detail::first_finderF<
BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type,
is_equal>
first_finder( const RangeT& Search )
{
return
detail::first_finderF<
BOOST_STRING_TYPENAME
range_const_iterator<RangeT>::type,
is_equal>( ::boost::as_literal(Search), is_equal() ) ;
}
//! "First" finder
/*!
\overload
*/
template<typename RangeT,typename PredicateT>
inline detail::first_finderF<
BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type,
PredicateT>
first_finder(
const RangeT& Search, PredicateT Comp )
{
return
detail::first_finderF<
BOOST_STRING_TYPENAME
range_const_iterator<RangeT>::type,
PredicateT>( ::boost::as_literal(Search), Comp );
}
//! "Last" finder
/*!
Construct the \c last_finder. The finder searches for the last
occurrence of the string in a given input.
The result is given as an \c iterator_range delimiting the match.
\param Search A substring to be searched for.
\param Comp An element comparison predicate
\return An instance of the \c last_finder object
*/
template<typename RangeT>
inline detail::last_finderF<
BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type,
is_equal>
last_finder( const RangeT& Search )
{
return
detail::last_finderF<
BOOST_STRING_TYPENAME
range_const_iterator<RangeT>::type,
is_equal>( ::boost::as_literal(Search), is_equal() );
}
//! "Last" finder
/*!
\overload
*/
template<typename RangeT, typename PredicateT>
inline detail::last_finderF<
BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type,
PredicateT>
last_finder( const RangeT& Search, PredicateT Comp )
{
return
detail::last_finderF<
BOOST_STRING_TYPENAME
range_const_iterator<RangeT>::type,
PredicateT>( ::boost::as_literal(Search), Comp ) ;
}
//! "Nth" finder
/*!
Construct the \c nth_finder. The finder searches for the n-th (zero-indexed)
occurrence of the string in a given input.
The result is given as an \c iterator_range delimiting the match.
\param Search A substring to be searched for.
\param Nth An index of the match to be find
\param Comp An element comparison predicate
\return An instance of the \c nth_finder object
*/
template<typename RangeT>
inline detail::nth_finderF<
BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type,
is_equal>
nth_finder(
const RangeT& Search,
int Nth)
{
return
detail::nth_finderF<
BOOST_STRING_TYPENAME
range_const_iterator<RangeT>::type,
is_equal>( ::boost::as_literal(Search), Nth, is_equal() ) ;
}
//! "Nth" finder
/*!
\overload
*/
template<typename RangeT, typename PredicateT>
inline detail::nth_finderF<
BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type,
PredicateT>
nth_finder(
const RangeT& Search,
int Nth,
PredicateT Comp )
{
return
detail::nth_finderF<
BOOST_STRING_TYPENAME
range_const_iterator<RangeT>::type,
PredicateT>( ::boost::as_literal(Search), Nth, Comp );
}
//! "Head" finder
/*!
Construct the \c head_finder. The finder returns a head of a given
input. The head is a prefix of a string up to n elements in
size. If an input has less then n elements, whole input is
considered a head.
The result is given as an \c iterator_range delimiting the match.
\param N The size of the head
\return An instance of the \c head_finder object
*/
inline detail::head_finderF
head_finder( int N )
{
return detail::head_finderF(N);
}
//! "Tail" finder
/*!
Construct the \c tail_finder. The finder returns a tail of a given
input. The tail is a suffix of a string up to n elements in
size. If an input has less then n elements, whole input is
considered a head.
The result is given as an \c iterator_range delimiting the match.
\param N The size of the head
\return An instance of the \c tail_finder object
*/
inline detail::tail_finderF
tail_finder( int N )
{
return detail::tail_finderF(N);
}
//! "Token" finder
/*!
Construct the \c token_finder. The finder searches for a token
specified by a predicate. It is similar to std::find_if
algorithm, with an exception that it return a range of
instead of a single iterator.
If "compress token mode" is enabled, adjacent matching tokens are
concatenated into one match. Thus the finder can be used to
search for continuous segments of characters satisfying the
given predicate.
The result is given as an \c iterator_range delimiting the match.
\param Pred An element selection predicate
\param eCompress Compress flag
\return An instance of the \c token_finder object
*/
template< typename PredicateT >
inline detail::token_finderF<PredicateT>
token_finder(
PredicateT Pred,
token_compress_mode_type eCompress=token_compress_off )
{
return detail::token_finderF<PredicateT>( Pred, eCompress );
}
//! "Range" finder
/*!
Construct the \c range_finder. The finder does not perform
any operation. It simply returns the given range for
any input.
\param Begin Beginning of the range
\param End End of the range
\param Range The range.
\return An instance of the \c range_finger object
*/
template< typename ForwardIteratorT >
inline detail::range_finderF<ForwardIteratorT>
range_finder(
ForwardIteratorT Begin,
ForwardIteratorT End )
{
return detail::range_finderF<ForwardIteratorT>( Begin, End );
}
//! "Range" finder
/*!
\overload
*/
template< typename ForwardIteratorT >
inline detail::range_finderF<ForwardIteratorT>
range_finder( iterator_range<ForwardIteratorT> Range )
{
return detail::range_finderF<ForwardIteratorT>( Range );
}
} // namespace algorithm
// pull the names to the boost namespace
using algorithm::first_finder;
using algorithm::last_finder;
using algorithm::nth_finder;
using algorithm::head_finder;
using algorithm::tail_finder;
using algorithm::token_finder;
using algorithm::range_finder;
} // namespace boost
#endif // BOOST_STRING_FINDER_HPP

View File

@@ -0,0 +1,120 @@
// Boost string_algo library formatter.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_FORMATTER_HPP
#define BOOST_STRING_FORMATTER_HPP
#include <boost/detail/iterator.hpp>
#include <boost/range/value_type.hpp>
#include <boost/range/iterator_range_core.hpp>
#include <boost/range/as_literal.hpp>
#include <boost/algorithm/string/detail/formatter.hpp>
/*! \file
Defines Formatter generators. Formatter is a functor which formats
a string according to given parameters. A Formatter works
in conjunction with a Finder. A Finder can provide additional information
for a specific Formatter. An example of such a cooperation is regex_finder
and regex_formatter.
Formatters are used as pluggable components for replace facilities.
This header contains generator functions for the Formatters provided in this library.
*/
namespace boost {
namespace algorithm {
// generic formatters ---------------------------------------------------------------//
//! Constant formatter
/*!
Constructs a \c const_formatter. Const formatter always returns
the same value, regardless of the parameter.
\param Format A predefined value used as a result for formatting
\return An instance of the \c const_formatter object.
*/
template<typename RangeT>
inline detail::const_formatF<
iterator_range<
BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> >
const_formatter(const RangeT& Format)
{
return detail::const_formatF<
iterator_range<
BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> >(::boost::as_literal(Format));
}
//! Identity formatter
/*!
Constructs an \c identity_formatter. Identity formatter always returns
the parameter.
\return An instance of the \c identity_formatter object.
*/
template<typename RangeT>
inline detail::identity_formatF<
iterator_range<
BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> >
identity_formatter()
{
return detail::identity_formatF<
iterator_range<
BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> >();
}
//! Empty formatter
/*!
Constructs an \c empty_formatter. Empty formatter always returns an empty
sequence.
\param Input container used to select a correct value_type for the
resulting empty_container<>.
\return An instance of the \c empty_formatter object.
*/
template<typename RangeT>
inline detail::empty_formatF<
BOOST_STRING_TYPENAME range_value<RangeT>::type>
empty_formatter(const RangeT&)
{
return detail::empty_formatF<
BOOST_STRING_TYPENAME range_value<RangeT>::type>();
}
//! Empty formatter
/*!
Constructs a \c dissect_formatter. Dissect formatter uses a specified finder
to extract a portion of the formatted sequence. The first finder's match is returned
as a result
\param Finder a finder used to select a portion of the formatted sequence
\return An instance of the \c dissect_formatter object.
*/
template<typename FinderT>
inline detail::dissect_formatF< FinderT >
dissect_formatter(const FinderT& Finder)
{
return detail::dissect_formatF<FinderT>(Finder);
}
} // namespace algorithm
// pull the names to the boost namespace
using algorithm::const_formatter;
using algorithm::identity_formatter;
using algorithm::empty_formatter;
using algorithm::dissect_formatter;
} // namespace boost
#endif // BOOST_FORMATTER_HPP

View File

@@ -0,0 +1,193 @@
// Boost string_algo library iter_find.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_ITER_FIND_HPP
#define BOOST_STRING_ITER_FIND_HPP
#include <boost/algorithm/string/config.hpp>
#include <algorithm>
#include <iterator>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/range/iterator_range_core.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/iterator.hpp>
#include <boost/range/value_type.hpp>
#include <boost/range/as_literal.hpp>
#include <boost/algorithm/string/concept.hpp>
#include <boost/algorithm/string/find_iterator.hpp>
#include <boost/algorithm/string/detail/util.hpp>
/*! \file
Defines generic split algorithms. Split algorithms can be
used to divide a sequence into several part according
to a given criteria. Result is given as a 'container
of containers' where elements are copies or references
to extracted parts.
There are two algorithms provided. One iterates over matching
substrings, the other one over the gaps between these matches.
*/
namespace boost {
namespace algorithm {
// iterate find ---------------------------------------------------//
//! Iter find algorithm
/*!
This algorithm executes a given finder in iteration on the input,
until the end of input is reached, or no match is found.
Iteration is done using built-in find_iterator, so the real
searching is performed only when needed.
In each iteration new match is found and added to the result.
\param Result A 'container container' to contain the result of search.
Both outer and inner container must have constructor taking a pair
of iterators as an argument.
Typical type of the result is
\c std::vector<boost::iterator_range<iterator>>
(each element of such a vector will container a range delimiting
a match).
\param Input A container which will be searched.
\param Finder A Finder object used for searching
\return A reference to the result
\note Prior content of the result will be overwritten.
*/
template<
typename SequenceSequenceT,
typename RangeT,
typename FinderT >
inline SequenceSequenceT&
iter_find(
SequenceSequenceT& Result,
RangeT& Input,
FinderT Finder )
{
BOOST_CONCEPT_ASSERT((
FinderConcept<
FinderT,
BOOST_STRING_TYPENAME range_iterator<RangeT>::type>
));
iterator_range<BOOST_STRING_TYPENAME range_iterator<RangeT>::type> lit_input(::boost::as_literal(Input));
typedef BOOST_STRING_TYPENAME
range_iterator<RangeT>::type input_iterator_type;
typedef find_iterator<input_iterator_type> find_iterator_type;
typedef detail::copy_iterator_rangeF<
BOOST_STRING_TYPENAME
range_value<SequenceSequenceT>::type,
input_iterator_type> copy_range_type;
input_iterator_type InputEnd=::boost::end(lit_input);
typedef transform_iterator<copy_range_type, find_iterator_type>
transform_iter_type;
transform_iter_type itBegin=
::boost::make_transform_iterator(
find_iterator_type( ::boost::begin(lit_input), InputEnd, Finder ),
copy_range_type());
transform_iter_type itEnd=
::boost::make_transform_iterator(
find_iterator_type(),
copy_range_type());
SequenceSequenceT Tmp(itBegin, itEnd);
Result.swap(Tmp);
return Result;
}
// iterate split ---------------------------------------------------//
//! Split find algorithm
/*!
This algorithm executes a given finder in iteration on the input,
until the end of input is reached, or no match is found.
Iteration is done using built-in find_iterator, so the real
searching is performed only when needed.
Each match is used as a separator of segments. These segments are then
returned in the result.
\param Result A 'container container' to contain the result of search.
Both outer and inner container must have constructor taking a pair
of iterators as an argument.
Typical type of the result is
\c std::vector<boost::iterator_range<iterator>>
(each element of such a vector will container a range delimiting
a match).
\param Input A container which will be searched.
\param Finder A finder object used for searching
\return A reference to the result
\note Prior content of the result will be overwritten.
*/
template<
typename SequenceSequenceT,
typename RangeT,
typename FinderT >
inline SequenceSequenceT&
iter_split(
SequenceSequenceT& Result,
RangeT& Input,
FinderT Finder )
{
BOOST_CONCEPT_ASSERT((
FinderConcept<FinderT,
BOOST_STRING_TYPENAME range_iterator<RangeT>::type>
));
iterator_range<BOOST_STRING_TYPENAME range_iterator<RangeT>::type> lit_input(::boost::as_literal(Input));
typedef BOOST_STRING_TYPENAME
range_iterator<RangeT>::type input_iterator_type;
typedef split_iterator<input_iterator_type> find_iterator_type;
typedef detail::copy_iterator_rangeF<
BOOST_STRING_TYPENAME
range_value<SequenceSequenceT>::type,
input_iterator_type> copy_range_type;
input_iterator_type InputEnd=::boost::end(lit_input);
typedef transform_iterator<copy_range_type, find_iterator_type>
transform_iter_type;
transform_iter_type itBegin=
::boost::make_transform_iterator(
find_iterator_type( ::boost::begin(lit_input), InputEnd, Finder ),
copy_range_type() );
transform_iter_type itEnd=
::boost::make_transform_iterator(
find_iterator_type(),
copy_range_type() );
SequenceSequenceT Tmp(itBegin, itEnd);
Result.swap(Tmp);
return Result;
}
} // namespace algorithm
// pull names to the boost namespace
using algorithm::iter_find;
using algorithm::iter_split;
} // namespace boost
#endif // BOOST_STRING_ITER_FIND_HPP

View File

@@ -0,0 +1,145 @@
// Boost string_algo library join.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2006.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_JOIN_HPP
#define BOOST_STRING_JOIN_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/algorithm/string/detail/sequence.hpp>
#include <boost/range/value_type.hpp>
#include <boost/range/as_literal.hpp>
/*! \file
Defines join algorithm.
Join algorithm is a counterpart to split algorithms.
It joins strings from a 'list' by adding user defined separator.
Additionally there is a version that allows simple filtering
by providing a predicate.
*/
namespace boost {
namespace algorithm {
// join --------------------------------------------------------------//
//! Join algorithm
/*!
This algorithm joins all strings in a 'list' into one long string.
Segments are concatenated by given separator.
\param Input A container that holds the input strings. It must be a container-of-containers.
\param Separator A string that will separate the joined segments.
\return Concatenated string.
\note This function provides the strong exception-safety guarantee
*/
template< typename SequenceSequenceT, typename Range1T>
inline typename range_value<SequenceSequenceT>::type
join(
const SequenceSequenceT& Input,
const Range1T& Separator)
{
// Define working types
typedef typename range_value<SequenceSequenceT>::type ResultT;
typedef typename range_const_iterator<SequenceSequenceT>::type InputIteratorT;
// Parse input
InputIteratorT itBegin=::boost::begin(Input);
InputIteratorT itEnd=::boost::end(Input);
// Construct container to hold the result
ResultT Result;
// Append first element
if(itBegin!=itEnd)
{
detail::insert(Result, ::boost::end(Result), *itBegin);
++itBegin;
}
for(;itBegin!=itEnd; ++itBegin)
{
// Add separator
detail::insert(Result, ::boost::end(Result), ::boost::as_literal(Separator));
// Add element
detail::insert(Result, ::boost::end(Result), *itBegin);
}
return Result;
}
// join_if ----------------------------------------------------------//
//! Conditional join algorithm
/*!
This algorithm joins all strings in a 'list' into one long string.
Segments are concatenated by given separator. Only segments that
satisfy the predicate will be added to the result.
\param Input A container that holds the input strings. It must be a container-of-containers.
\param Separator A string that will separate the joined segments.
\param Pred A segment selection predicate
\return Concatenated string.
\note This function provides the strong exception-safety guarantee
*/
template< typename SequenceSequenceT, typename Range1T, typename PredicateT>
inline typename range_value<SequenceSequenceT>::type
join_if(
const SequenceSequenceT& Input,
const Range1T& Separator,
PredicateT Pred)
{
// Define working types
typedef typename range_value<SequenceSequenceT>::type ResultT;
typedef typename range_const_iterator<SequenceSequenceT>::type InputIteratorT;
// Parse input
InputIteratorT itBegin=::boost::begin(Input);
InputIteratorT itEnd=::boost::end(Input);
// Construct container to hold the result
ResultT Result;
// Roll to the first element that will be added
while(itBegin!=itEnd && !Pred(*itBegin)) ++itBegin;
// Add this element
if(itBegin!=itEnd)
{
detail::insert(Result, ::boost::end(Result), *itBegin);
++itBegin;
}
for(;itBegin!=itEnd; ++itBegin)
{
if(Pred(*itBegin))
{
// Add separator
detail::insert(Result, ::boost::end(Result), ::boost::as_literal(Separator));
// Add element
detail::insert(Result, ::boost::end(Result), *itBegin);
}
}
return Result;
}
} // namespace algorithm
// pull names to the boost namespace
using algorithm::join;
using algorithm::join_if;
} // namespace boost
#endif // BOOST_STRING_JOIN_HPP

View File

@@ -0,0 +1,475 @@
// Boost string_algo library predicate.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_PREDICATE_HPP
#define BOOST_STRING_PREDICATE_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/iterator.hpp>
#include <boost/range/const_iterator.hpp>
#include <boost/range/as_literal.hpp>
#include <boost/range/iterator_range_core.hpp>
#include <boost/algorithm/string/compare.hpp>
#include <boost/algorithm/string/find.hpp>
#include <boost/algorithm/string/detail/predicate.hpp>
/*! \file boost/algorithm/string/predicate.hpp
Defines string-related predicates.
The predicates determine whether a substring is contained in the input string
under various conditions: a string starts with the substring, ends with the
substring, simply contains the substring or if both strings are equal.
Additionaly the algorithm \c all() checks all elements of a container to satisfy a
condition.
All predicates provide the strong exception guarantee.
*/
namespace boost {
namespace algorithm {
// starts_with predicate -----------------------------------------------//
//! 'Starts with' predicate
/*!
This predicate holds when the test string is a prefix of the Input.
In other words, if the input starts with the test.
When the optional predicate is specified, it is used for character-wise
comparison.
\param Input An input sequence
\param Test A test sequence
\param Comp An element comparison predicate
\return The result of the test
\note This function provides the strong exception-safety guarantee
*/
template<typename Range1T, typename Range2T, typename PredicateT>
inline bool starts_with(
const Range1T& Input,
const Range2T& Test,
PredicateT Comp)
{
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range1T>::type> lit_input(::boost::as_literal(Input));
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range2T>::type> lit_test(::boost::as_literal(Test));
typedef BOOST_STRING_TYPENAME
range_const_iterator<Range1T>::type Iterator1T;
typedef BOOST_STRING_TYPENAME
range_const_iterator<Range2T>::type Iterator2T;
Iterator1T InputEnd=::boost::end(lit_input);
Iterator2T TestEnd=::boost::end(lit_test);
Iterator1T it=::boost::begin(lit_input);
Iterator2T pit=::boost::begin(lit_test);
for(;
it!=InputEnd && pit!=TestEnd;
++it,++pit)
{
if( !(Comp(*it,*pit)) )
return false;
}
return pit==TestEnd;
}
//! 'Starts with' predicate
/*!
\overload
*/
template<typename Range1T, typename Range2T>
inline bool starts_with(
const Range1T& Input,
const Range2T& Test)
{
return ::boost::algorithm::starts_with(Input, Test, is_equal());
}
//! 'Starts with' predicate ( case insensitive )
/*!
This predicate holds when the test string is a prefix of the Input.
In other words, if the input starts with the test.
Elements are compared case insensitively.
\param Input An input sequence
\param Test A test sequence
\param Loc A locale used for case insensitive comparison
\return The result of the test
\note This function provides the strong exception-safety guarantee
*/
template<typename Range1T, typename Range2T>
inline bool istarts_with(
const Range1T& Input,
const Range2T& Test,
const std::locale& Loc=std::locale())
{
return ::boost::algorithm::starts_with(Input, Test, is_iequal(Loc));
}
// ends_with predicate -----------------------------------------------//
//! 'Ends with' predicate
/*!
This predicate holds when the test string is a suffix of the Input.
In other words, if the input ends with the test.
When the optional predicate is specified, it is used for character-wise
comparison.
\param Input An input sequence
\param Test A test sequence
\param Comp An element comparison predicate
\return The result of the test
\note This function provides the strong exception-safety guarantee
*/
template<typename Range1T, typename Range2T, typename PredicateT>
inline bool ends_with(
const Range1T& Input,
const Range2T& Test,
PredicateT Comp)
{
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range1T>::type> lit_input(::boost::as_literal(Input));
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range2T>::type> lit_test(::boost::as_literal(Test));
typedef BOOST_STRING_TYPENAME
range_const_iterator<Range1T>::type Iterator1T;
typedef BOOST_STRING_TYPENAME boost::detail::
iterator_traits<Iterator1T>::iterator_category category;
return detail::
ends_with_iter_select(
::boost::begin(lit_input),
::boost::end(lit_input),
::boost::begin(lit_test),
::boost::end(lit_test),
Comp,
category());
}
//! 'Ends with' predicate
/*!
\overload
*/
template<typename Range1T, typename Range2T>
inline bool ends_with(
const Range1T& Input,
const Range2T& Test)
{
return ::boost::algorithm::ends_with(Input, Test, is_equal());
}
//! 'Ends with' predicate ( case insensitive )
/*!
This predicate holds when the test container is a suffix of the Input.
In other words, if the input ends with the test.
Elements are compared case insensitively.
\param Input An input sequence
\param Test A test sequence
\param Loc A locale used for case insensitive comparison
\return The result of the test
\note This function provides the strong exception-safety guarantee
*/
template<typename Range1T, typename Range2T>
inline bool iends_with(
const Range1T& Input,
const Range2T& Test,
const std::locale& Loc=std::locale())
{
return ::boost::algorithm::ends_with(Input, Test, is_iequal(Loc));
}
// contains predicate -----------------------------------------------//
//! 'Contains' predicate
/*!
This predicate holds when the test container is contained in the Input.
When the optional predicate is specified, it is used for character-wise
comparison.
\param Input An input sequence
\param Test A test sequence
\param Comp An element comparison predicate
\return The result of the test
\note This function provides the strong exception-safety guarantee
*/
template<typename Range1T, typename Range2T, typename PredicateT>
inline bool contains(
const Range1T& Input,
const Range2T& Test,
PredicateT Comp)
{
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range1T>::type> lit_input(::boost::as_literal(Input));
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range2T>::type> lit_test(::boost::as_literal(Test));
if (::boost::empty(lit_test))
{
// Empty range is contained always
return true;
}
// Use the temporary variable to make VACPP happy
bool bResult=(::boost::algorithm::first_finder(lit_test,Comp)(::boost::begin(lit_input), ::boost::end(lit_input)));
return bResult;
}
//! 'Contains' predicate
/*!
\overload
*/
template<typename Range1T, typename Range2T>
inline bool contains(
const Range1T& Input,
const Range2T& Test)
{
return ::boost::algorithm::contains(Input, Test, is_equal());
}
//! 'Contains' predicate ( case insensitive )
/*!
This predicate holds when the test container is contained in the Input.
Elements are compared case insensitively.
\param Input An input sequence
\param Test A test sequence
\param Loc A locale used for case insensitive comparison
\return The result of the test
\note This function provides the strong exception-safety guarantee
*/
template<typename Range1T, typename Range2T>
inline bool icontains(
const Range1T& Input,
const Range2T& Test,
const std::locale& Loc=std::locale())
{
return ::boost::algorithm::contains(Input, Test, is_iequal(Loc));
}
// equals predicate -----------------------------------------------//
//! 'Equals' predicate
/*!
This predicate holds when the test container is equal to the
input container i.e. all elements in both containers are same.
When the optional predicate is specified, it is used for character-wise
comparison.
\param Input An input sequence
\param Test A test sequence
\param Comp An element comparison predicate
\return The result of the test
\note This is a two-way version of \c std::equal algorithm
\note This function provides the strong exception-safety guarantee
*/
template<typename Range1T, typename Range2T, typename PredicateT>
inline bool equals(
const Range1T& Input,
const Range2T& Test,
PredicateT Comp)
{
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range1T>::type> lit_input(::boost::as_literal(Input));
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range2T>::type> lit_test(::boost::as_literal(Test));
typedef BOOST_STRING_TYPENAME
range_const_iterator<Range1T>::type Iterator1T;
typedef BOOST_STRING_TYPENAME
range_const_iterator<Range2T>::type Iterator2T;
Iterator1T InputEnd=::boost::end(lit_input);
Iterator2T TestEnd=::boost::end(lit_test);
Iterator1T it=::boost::begin(lit_input);
Iterator2T pit=::boost::begin(lit_test);
for(;
it!=InputEnd && pit!=TestEnd;
++it,++pit)
{
if( !(Comp(*it,*pit)) )
return false;
}
return (pit==TestEnd) && (it==InputEnd);
}
//! 'Equals' predicate
/*!
\overload
*/
template<typename Range1T, typename Range2T>
inline bool equals(
const Range1T& Input,
const Range2T& Test)
{
return ::boost::algorithm::equals(Input, Test, is_equal());
}
//! 'Equals' predicate ( case insensitive )
/*!
This predicate holds when the test container is equal to the
input container i.e. all elements in both containers are same.
Elements are compared case insensitively.
\param Input An input sequence
\param Test A test sequence
\param Loc A locale used for case insensitive comparison
\return The result of the test
\note This is a two-way version of \c std::equal algorithm
\note This function provides the strong exception-safety guarantee
*/
template<typename Range1T, typename Range2T>
inline bool iequals(
const Range1T& Input,
const Range2T& Test,
const std::locale& Loc=std::locale())
{
return ::boost::algorithm::equals(Input, Test, is_iequal(Loc));
}
// lexicographical_compare predicate -----------------------------//
//! Lexicographical compare predicate
/*!
This predicate is an overload of std::lexicographical_compare
for range arguments
It check whether the first argument is lexicographically less
then the second one.
If the optional predicate is specified, it is used for character-wise
comparison
\param Arg1 First argument
\param Arg2 Second argument
\param Pred Comparison predicate
\return The result of the test
\note This function provides the strong exception-safety guarantee
*/
template<typename Range1T, typename Range2T, typename PredicateT>
inline bool lexicographical_compare(
const Range1T& Arg1,
const Range2T& Arg2,
PredicateT Pred)
{
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range1T>::type> lit_arg1(::boost::as_literal(Arg1));
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range2T>::type> lit_arg2(::boost::as_literal(Arg2));
return std::lexicographical_compare(
::boost::begin(lit_arg1),
::boost::end(lit_arg1),
::boost::begin(lit_arg2),
::boost::end(lit_arg2),
Pred);
}
//! Lexicographical compare predicate
/*!
\overload
*/
template<typename Range1T, typename Range2T>
inline bool lexicographical_compare(
const Range1T& Arg1,
const Range2T& Arg2)
{
return ::boost::algorithm::lexicographical_compare(Arg1, Arg2, is_less());
}
//! Lexicographical compare predicate (case-insensitive)
/*!
This predicate is an overload of std::lexicographical_compare
for range arguments.
It check whether the first argument is lexicographically less
then the second one.
Elements are compared case insensitively
\param Arg1 First argument
\param Arg2 Second argument
\param Loc A locale used for case insensitive comparison
\return The result of the test
\note This function provides the strong exception-safety guarantee
*/
template<typename Range1T, typename Range2T>
inline bool ilexicographical_compare(
const Range1T& Arg1,
const Range2T& Arg2,
const std::locale& Loc=std::locale())
{
return ::boost::algorithm::lexicographical_compare(Arg1, Arg2, is_iless(Loc));
}
// all predicate -----------------------------------------------//
//! 'All' predicate
/*!
This predicate holds it all its elements satisfy a given
condition, represented by the predicate.
\param Input An input sequence
\param Pred A predicate
\return The result of the test
\note This function provides the strong exception-safety guarantee
*/
template<typename RangeT, typename PredicateT>
inline bool all(
const RangeT& Input,
PredicateT Pred)
{
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> lit_input(::boost::as_literal(Input));
typedef BOOST_STRING_TYPENAME
range_const_iterator<RangeT>::type Iterator1T;
Iterator1T InputEnd=::boost::end(lit_input);
for( Iterator1T It=::boost::begin(lit_input); It!=InputEnd; ++It)
{
if (!Pred(*It))
return false;
}
return true;
}
} // namespace algorithm
// pull names to the boost namespace
using algorithm::starts_with;
using algorithm::istarts_with;
using algorithm::ends_with;
using algorithm::iends_with;
using algorithm::contains;
using algorithm::icontains;
using algorithm::equals;
using algorithm::iequals;
using algorithm::all;
using algorithm::lexicographical_compare;
using algorithm::ilexicographical_compare;
} // namespace boost
#endif // BOOST_STRING_PREDICATE_HPP

View File

@@ -0,0 +1,42 @@
// Boost string_algo library predicate_facade.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_PREDICATE_FACADE_HPP
#define BOOST_STRING_PREDICATE_FACADE_HPP
#include <boost/algorithm/string/config.hpp>
/*
\file boost/algorith/string/predicate_facade.hpp
This file contains predicate_facade definition. This template class is used
to identify classification predicates, so they can be combined using
composition operators.
*/
namespace boost {
namespace algorithm {
// predicate facade ------------------------------------------------------//
//! Predicate facade
/*!
This class allows to recognize classification
predicates, so that they can be combined using
composition operators.
Every classification predicate must be derived from this class.
*/
template<typename Derived>
struct predicate_facade {};
} // namespace algorithm
} // namespace boost
#endif // BOOST_STRING_CLASSIFICATION_DETAIL_HPP

View File

@@ -0,0 +1,646 @@
// Boost string_algo library regex.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_REGEX_HPP
#define BOOST_STRING_REGEX_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/regex.hpp>
#include <boost/range/iterator_range_core.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/iterator.hpp>
#include <boost/range/as_literal.hpp>
#include <boost/algorithm/string/find_format.hpp>
#include <boost/algorithm/string/regex_find_format.hpp>
#include <boost/algorithm/string/formatter.hpp>
#include <boost/algorithm/string/iter_find.hpp>
/*! \file
Defines regex variants of the algorithms.
*/
namespace boost {
namespace algorithm {
// find_regex -----------------------------------------------//
//! Find regex algorithm
/*!
Search for a substring matching the given regex in the input.
\param Input A container which will be searched.
\param Rx A regular expression
\param Flags Regex options
\return
An \c iterator_range delimiting the match.
Returned iterator is either \c RangeT::iterator or
\c RangeT::const_iterator, depending on the constness of
the input parameter.
\note This function provides the strong exception-safety guarantee
*/
template<
typename RangeT,
typename CharT,
typename RegexTraitsT>
inline iterator_range<
BOOST_STRING_TYPENAME range_iterator<RangeT>::type >
find_regex(
RangeT& Input,
const basic_regex<CharT, RegexTraitsT>& Rx,
match_flag_type Flags=match_default )
{
iterator_range<BOOST_STRING_TYPENAME range_iterator<RangeT>::type> lit_input(::boost::as_literal(Input));
return ::boost::algorithm::regex_finder(Rx,Flags)(
::boost::begin(lit_input), ::boost::end(lit_input) );
}
// replace_regex --------------------------------------------------------------------//
//! Replace regex algorithm
/*!
Search for a substring matching given regex and format it with
the specified format.
The result is a modified copy of the input. It is returned as a sequence
or copied to the output iterator.
\param Output An output iterator to which the result will be copied
\param Input An input string
\param Rx A regular expression
\param Format Regex format definition
\param Flags Regex options
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<
typename OutputIteratorT,
typename RangeT,
typename CharT,
typename RegexTraitsT,
typename FormatStringTraitsT, typename FormatStringAllocatorT >
inline OutputIteratorT replace_regex_copy(
OutputIteratorT Output,
const RangeT& Input,
const basic_regex<CharT, RegexTraitsT>& Rx,
const std::basic_string<CharT, FormatStringTraitsT, FormatStringAllocatorT>& Format,
match_flag_type Flags=match_default | format_default )
{
return ::boost::algorithm::find_format_copy(
Output,
Input,
::boost::algorithm::regex_finder( Rx, Flags ),
::boost::algorithm::regex_formatter( Format, Flags ) );
}
//! Replace regex algorithm
/*!
\overload
*/
template<
typename SequenceT,
typename CharT,
typename RegexTraitsT,
typename FormatStringTraitsT, typename FormatStringAllocatorT >
inline SequenceT replace_regex_copy(
const SequenceT& Input,
const basic_regex<CharT, RegexTraitsT>& Rx,
const std::basic_string<CharT, FormatStringTraitsT, FormatStringAllocatorT>& Format,
match_flag_type Flags=match_default | format_default )
{
return ::boost::algorithm::find_format_copy(
Input,
::boost::algorithm::regex_finder( Rx, Flags ),
::boost::algorithm::regex_formatter( Format, Flags ) );
}
//! Replace regex algorithm
/*!
Search for a substring matching given regex and format it with
the specified format. The input string is modified in-place.
\param Input An input string
\param Rx A regular expression
\param Format Regex format definition
\param Flags Regex options
*/
template<
typename SequenceT,
typename CharT,
typename RegexTraitsT,
typename FormatStringTraitsT, typename FormatStringAllocatorT >
inline void replace_regex(
SequenceT& Input,
const basic_regex<CharT, RegexTraitsT>& Rx,
const std::basic_string<CharT, FormatStringTraitsT, FormatStringAllocatorT>& Format,
match_flag_type Flags=match_default | format_default )
{
::boost::algorithm::find_format(
Input,
::boost::algorithm::regex_finder( Rx, Flags ),
::boost::algorithm::regex_formatter( Format, Flags ) );
}
// replace_all_regex --------------------------------------------------------------------//
//! Replace all regex algorithm
/*!
Format all substrings, matching given regex, with the specified format.
The result is a modified copy of the input. It is returned as a sequence
or copied to the output iterator.
\param Output An output iterator to which the result will be copied
\param Input An input string
\param Rx A regular expression
\param Format Regex format definition
\param Flags Regex options
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<
typename OutputIteratorT,
typename RangeT,
typename CharT,
typename RegexTraitsT,
typename FormatStringTraitsT, typename FormatStringAllocatorT >
inline OutputIteratorT replace_all_regex_copy(
OutputIteratorT Output,
const RangeT& Input,
const basic_regex<CharT, RegexTraitsT>& Rx,
const std::basic_string<CharT, FormatStringTraitsT, FormatStringAllocatorT>& Format,
match_flag_type Flags=match_default | format_default )
{
return ::boost::algorithm::find_format_all_copy(
Output,
Input,
::boost::algorithm::regex_finder( Rx, Flags ),
::boost::algorithm::regex_formatter( Format, Flags ) );
}
//! Replace all regex algorithm
/*!
\overload
*/
template<
typename SequenceT,
typename CharT,
typename RegexTraitsT,
typename FormatStringTraitsT, typename FormatStringAllocatorT >
inline SequenceT replace_all_regex_copy(
const SequenceT& Input,
const basic_regex<CharT, RegexTraitsT>& Rx,
const std::basic_string<CharT, FormatStringTraitsT, FormatStringAllocatorT>& Format,
match_flag_type Flags=match_default | format_default )
{
return ::boost::algorithm::find_format_all_copy(
Input,
::boost::algorithm::regex_finder( Rx, Flags ),
::boost::algorithm::regex_formatter( Format, Flags ) );
}
//! Replace all regex algorithm
/*!
Format all substrings, matching given regex, with the specified format.
The input string is modified in-place.
\param Input An input string
\param Rx A regular expression
\param Format Regex format definition
\param Flags Regex options
*/
template<
typename SequenceT,
typename CharT,
typename RegexTraitsT,
typename FormatStringTraitsT, typename FormatStringAllocatorT >
inline void replace_all_regex(
SequenceT& Input,
const basic_regex<CharT, RegexTraitsT>& Rx,
const std::basic_string<CharT, FormatStringTraitsT, FormatStringAllocatorT>& Format,
match_flag_type Flags=match_default | format_default )
{
::boost::algorithm::find_format_all(
Input,
::boost::algorithm::regex_finder( Rx, Flags ),
::boost::algorithm::regex_formatter( Format, Flags ) );
}
// erase_regex --------------------------------------------------------------------//
//! Erase regex algorithm
/*!
Remove a substring matching given regex from the input.
The result is a modified copy of the input. It is returned as a sequence
or copied to the output iterator.
\param Output An output iterator to which the result will be copied
\param Input An input string
\param Rx A regular expression
\param Flags Regex options
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<
typename OutputIteratorT,
typename RangeT,
typename CharT,
typename RegexTraitsT >
inline OutputIteratorT erase_regex_copy(
OutputIteratorT Output,
const RangeT& Input,
const basic_regex<CharT, RegexTraitsT>& Rx,
match_flag_type Flags=match_default )
{
return ::boost::algorithm::find_format_copy(
Output,
Input,
::boost::algorithm::regex_finder( Rx, Flags ),
::boost::algorithm::empty_formatter( Input ) );
}
//! Erase regex algorithm
/*!
\overload
*/
template<
typename SequenceT,
typename CharT,
typename RegexTraitsT >
inline SequenceT erase_regex_copy(
const SequenceT& Input,
const basic_regex<CharT, RegexTraitsT>& Rx,
match_flag_type Flags=match_default )
{
return ::boost::algorithm::find_format_copy(
Input,
::boost::algorithm::regex_finder( Rx, Flags ),
::boost::algorithm::empty_formatter( Input ) );
}
//! Erase regex algorithm
/*!
Remove a substring matching given regex from the input.
The input string is modified in-place.
\param Input An input string
\param Rx A regular expression
\param Flags Regex options
*/
template<
typename SequenceT,
typename CharT,
typename RegexTraitsT >
inline void erase_regex(
SequenceT& Input,
const basic_regex<CharT, RegexTraitsT>& Rx,
match_flag_type Flags=match_default )
{
::boost::algorithm::find_format(
Input,
::boost::algorithm::regex_finder( Rx, Flags ),
::boost::algorithm::empty_formatter( Input ) );
}
// erase_all_regex --------------------------------------------------------------------//
//! Erase all regex algorithm
/*!
Erase all substrings, matching given regex, from the input.
The result is a modified copy of the input. It is returned as a sequence
or copied to the output iterator.
\param Output An output iterator to which the result will be copied
\param Input An input string
\param Rx A regular expression
\param Flags Regex options
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<
typename OutputIteratorT,
typename RangeT,
typename CharT,
typename RegexTraitsT >
inline OutputIteratorT erase_all_regex_copy(
OutputIteratorT Output,
const RangeT& Input,
const basic_regex<CharT, RegexTraitsT>& Rx,
match_flag_type Flags=match_default )
{
return ::boost::algorithm::find_format_all_copy(
Output,
Input,
::boost::algorithm::regex_finder( Rx, Flags ),
::boost::algorithm::empty_formatter( Input ) );
}
//! Erase all regex algorithm
/*!
\overload
*/
template<
typename SequenceT,
typename CharT,
typename RegexTraitsT >
inline SequenceT erase_all_regex_copy(
const SequenceT& Input,
const basic_regex<CharT, RegexTraitsT>& Rx,
match_flag_type Flags=match_default )
{
return ::boost::algorithm::find_format_all_copy(
Input,
::boost::algorithm::regex_finder( Rx, Flags ),
::boost::algorithm::empty_formatter( Input ) );
}
//! Erase all regex algorithm
/*!
Erase all substrings, matching given regex, from the input.
The input string is modified in-place.
\param Input An input string
\param Rx A regular expression
\param Flags Regex options
*/
template<
typename SequenceT,
typename CharT,
typename RegexTraitsT>
inline void erase_all_regex(
SequenceT& Input,
const basic_regex<CharT, RegexTraitsT>& Rx,
match_flag_type Flags=match_default )
{
::boost::algorithm::find_format_all(
Input,
::boost::algorithm::regex_finder( Rx, Flags ),
::boost::algorithm::empty_formatter( Input ) );
}
// find_all_regex ------------------------------------------------------------------//
//! Find all regex algorithm
/*!
This algorithm finds all substrings matching the give regex
in the input.
Each part is copied and added as a new element to the output container.
Thus the result container must be able to hold copies
of the matches (in a compatible structure like std::string) or
a reference to it (e.g. using the iterator range class).
Examples of such a container are \c std::vector<std::string>
or \c std::list<boost::iterator_range<std::string::iterator>>
\param Result A container that can hold copies of references to the substrings.
\param Input A container which will be searched.
\param Rx A regular expression
\param Flags Regex options
\return A reference to the result
\note Prior content of the result will be overwritten.
\note This function provides the strong exception-safety guarantee
*/
template<
typename SequenceSequenceT,
typename RangeT,
typename CharT,
typename RegexTraitsT >
inline SequenceSequenceT& find_all_regex(
SequenceSequenceT& Result,
const RangeT& Input,
const basic_regex<CharT, RegexTraitsT>& Rx,
match_flag_type Flags=match_default )
{
return ::boost::algorithm::iter_find(
Result,
Input,
::boost::algorithm::regex_finder(Rx,Flags) );
}
// split_regex ------------------------------------------------------------------//
//! Split regex algorithm
/*!
Tokenize expression. This function is equivalent to C strtok. Input
sequence is split into tokens, separated by separators. Separator
is an every match of the given regex.
Each part is copied and added as a new element to the output container.
Thus the result container must be able to hold copies
of the matches (in a compatible structure like std::string) or
a reference to it (e.g. using the iterator range class).
Examples of such a container are \c std::vector<std::string>
or \c std::list<boost::iterator_range<std::string::iterator>>
\param Result A container that can hold copies of references to the substrings.
\param Input A container which will be searched.
\param Rx A regular expression
\param Flags Regex options
\return A reference to the result
\note Prior content of the result will be overwritten.
\note This function provides the strong exception-safety guarantee
*/
template<
typename SequenceSequenceT,
typename RangeT,
typename CharT,
typename RegexTraitsT >
inline SequenceSequenceT& split_regex(
SequenceSequenceT& Result,
const RangeT& Input,
const basic_regex<CharT, RegexTraitsT>& Rx,
match_flag_type Flags=match_default )
{
return ::boost::algorithm::iter_split(
Result,
Input,
::boost::algorithm::regex_finder(Rx,Flags) );
}
// join_if ------------------------------------------------------------------//
#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
//! Conditional join algorithm
/*!
This algorithm joins all strings in a 'list' into one long string.
Segments are concatenated by given separator. Only segments that
match the given regular expression will be added to the result
This is a specialization of join_if algorithm.
\param Input A container that holds the input strings. It must be a container-of-containers.
\param Separator A string that will separate the joined segments.
\param Rx A regular expression
\param Flags Regex options
\return Concatenated string.
\note This function provides the strong exception-safety guarantee
*/
template<
typename SequenceSequenceT,
typename Range1T,
typename CharT,
typename RegexTraitsT >
inline typename range_value<SequenceSequenceT>::type
join_if(
const SequenceSequenceT& Input,
const Range1T& Separator,
const basic_regex<CharT, RegexTraitsT>& Rx,
match_flag_type Flags=match_default )
{
// Define working types
typedef typename range_value<SequenceSequenceT>::type ResultT;
typedef typename range_const_iterator<SequenceSequenceT>::type InputIteratorT;
// Parse input
InputIteratorT itBegin=::boost::begin(Input);
InputIteratorT itEnd=::boost::end(Input);
// Construct container to hold the result
ResultT Result;
// Roll to the first element that will be added
while(
itBegin!=itEnd &&
!::boost::regex_match(::boost::begin(*itBegin), ::boost::end(*itBegin), Rx, Flags)) ++itBegin;
// Add this element
if(itBegin!=itEnd)
{
detail::insert(Result, ::boost::end(Result), *itBegin);
++itBegin;
}
for(;itBegin!=itEnd; ++itBegin)
{
if(::boost::regex_match(::boost::begin(*itBegin), ::boost::end(*itBegin), Rx, Flags))
{
// Add separator
detail::insert(Result, ::boost::end(Result), ::boost::as_literal(Separator));
// Add element
detail::insert(Result, ::boost::end(Result), *itBegin);
}
}
return Result;
}
#else // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
//! Conditional join algorithm
/*!
This algorithm joins all strings in a 'list' into one long string.
Segments are concatenated by given separator. Only segments that
match the given regular expression will be added to the result
This is a specialization of join_if algorithm.
\param Input A container that holds the input strings. It must be a container-of-containers.
\param Separator A string that will separate the joined segments.
\param Rx A regular expression
\param Flags Regex options
\return Concatenated string.
\note This function provides the strong exception-safety guarantee
*/
template<
typename SequenceSequenceT,
typename Range1T,
typename CharT,
typename RegexTraitsT >
inline typename range_value<SequenceSequenceT>::type
join_if_regex(
const SequenceSequenceT& Input,
const Range1T& Separator,
const basic_regex<CharT, RegexTraitsT>& Rx,
match_flag_type Flags=match_default )
{
// Define working types
typedef typename range_value<SequenceSequenceT>::type ResultT;
typedef typename range_const_iterator<SequenceSequenceT>::type InputIteratorT;
// Parse input
InputIteratorT itBegin=::boost::begin(Input);
InputIteratorT itEnd=::boost::end(Input);
// Construct container to hold the result
ResultT Result;
// Roll to the first element that will be added
while(
itBegin!=itEnd &&
!::boost::regex_match(::boost::begin(*itBegin), ::boost::end(*itBegin), Rx, Flags)) ++itBegin;
// Add this element
if(itBegin!=itEnd)
{
detail::insert(Result, ::boost::end(Result), *itBegin);
++itBegin;
}
for(;itBegin!=itEnd; ++itBegin)
{
if(::boost::regex_match(::boost::begin(*itBegin), ::boost::end(*itBegin), Rx, Flags))
{
// Add separator
detail::insert(Result, ::boost::end(Result), ::boost::as_literal(Separator));
// Add element
detail::insert(Result, ::boost::end(Result), *itBegin);
}
}
return Result;
}
#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
} // namespace algorithm
// pull names into the boost namespace
using algorithm::find_regex;
using algorithm::replace_regex;
using algorithm::replace_regex_copy;
using algorithm::replace_all_regex;
using algorithm::replace_all_regex_copy;
using algorithm::erase_regex;
using algorithm::erase_regex_copy;
using algorithm::erase_all_regex;
using algorithm::erase_all_regex_copy;
using algorithm::find_all_regex;
using algorithm::split_regex;
#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
using algorithm::join_if;
#else // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
using algorithm::join_if_regex;
#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
} // namespace boost
#endif // BOOST_STRING_REGEX_HPP

View File

@@ -0,0 +1,90 @@
// Boost string_algo library regex_find_format.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_REGEX_FIND_FORMAT_HPP
#define BOOST_STRING_REGEX_FIND_FORMAT_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/regex.hpp>
#include <boost/algorithm/string/detail/finder_regex.hpp>
#include <boost/algorithm/string/detail/formatter_regex.hpp>
/*! \file
Defines the \c regex_finder and \c regex_formatter generators. These two functors
are designed to work together. \c regex_formatter uses additional information
about a match contained in the regex_finder search result.
*/
namespace boost {
namespace algorithm {
// regex_finder -----------------------------------------------//
//! "Regex" finder
/*!
Construct the \c regex_finder. Finder uses the regex engine to search
for a match.
Result is given in \c regex_search_result. This is an extension
of the iterator_range. In addition it contains match results
from the \c regex_search algorithm.
\param Rx A regular expression
\param MatchFlags Regex search options
\return An instance of the \c regex_finder object
*/
template<
typename CharT,
typename RegexTraitsT>
inline detail::find_regexF< basic_regex<CharT, RegexTraitsT> >
regex_finder(
const basic_regex<CharT, RegexTraitsT>& Rx,
match_flag_type MatchFlags=match_default )
{
return detail::
find_regexF<
basic_regex<CharT, RegexTraitsT> >( Rx, MatchFlags );
}
// regex_formater ---------------------------------------------//
//! Regex formatter
/*!
Construct the \c regex_formatter. Regex formatter uses the regex engine to
format a match found by the \c regex_finder.
This formatted it designed to closely cooperate with \c regex_finder.
\param Format Regex format definition
\param Flags Format flags
\return An instance of the \c regex_formatter functor
*/
template<
typename CharT,
typename TraitsT, typename AllocT >
inline detail::regex_formatF< std::basic_string< CharT, TraitsT, AllocT > >
regex_formatter(
const std::basic_string<CharT, TraitsT, AllocT>& Format,
match_flag_type Flags=format_default )
{
return
detail::regex_formatF< std::basic_string<CharT, TraitsT, AllocT> >(
Format,
Flags );
}
} // namespace algorithm
// pull the names to the boost namespace
using algorithm::regex_finder;
using algorithm::regex_formatter;
} // namespace boost
#endif // BOOST_STRING_REGEX_FIND_FORMAT_HPP

View File

@@ -0,0 +1,928 @@
// Boost string_algo library replace.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2006.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_REPLACE_HPP
#define BOOST_STRING_REPLACE_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/range/iterator_range_core.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/iterator.hpp>
#include <boost/range/const_iterator.hpp>
#include <boost/algorithm/string/find_format.hpp>
#include <boost/algorithm/string/finder.hpp>
#include <boost/algorithm/string/formatter.hpp>
#include <boost/algorithm/string/compare.hpp>
/*! \file
Defines various replace algorithms. Each algorithm replaces
part(s) of the input according to set of searching and replace criteria.
*/
namespace boost {
namespace algorithm {
// replace_range --------------------------------------------------------------------//
//! Replace range algorithm
/*!
Replace the given range in the input string.
The result is a modified copy of the input. It is returned as a sequence
or copied to the output iterator.
\param Output An output iterator to which the result will be copied
\param Input An input string
\param SearchRange A range in the input to be substituted
\param Format A substitute string
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<
typename OutputIteratorT,
typename Range1T,
typename Range2T>
inline OutputIteratorT replace_range_copy(
OutputIteratorT Output,
const Range1T& Input,
const iterator_range<
BOOST_STRING_TYPENAME
range_const_iterator<Range1T>::type>& SearchRange,
const Range2T& Format)
{
return ::boost::algorithm::find_format_copy(
Output,
Input,
::boost::algorithm::range_finder(SearchRange),
::boost::algorithm::const_formatter(Format));
}
//! Replace range algorithm
/*!
\overload
*/
template<typename SequenceT, typename RangeT>
inline SequenceT replace_range_copy(
const SequenceT& Input,
const iterator_range<
BOOST_STRING_TYPENAME
range_const_iterator<SequenceT>::type>& SearchRange,
const RangeT& Format)
{
return ::boost::algorithm::find_format_copy(
Input,
::boost::algorithm::range_finder(SearchRange),
::boost::algorithm::const_formatter(Format));
}
//! Replace range algorithm
/*!
Replace the given range in the input string.
The input sequence is modified in-place.
\param Input An input string
\param SearchRange A range in the input to be substituted
\param Format A substitute string
*/
template<typename SequenceT, typename RangeT>
inline void replace_range(
SequenceT& Input,
const iterator_range<
BOOST_STRING_TYPENAME
range_iterator<SequenceT>::type>& SearchRange,
const RangeT& Format)
{
::boost::algorithm::find_format(
Input,
::boost::algorithm::range_finder(SearchRange),
::boost::algorithm::const_formatter(Format));
}
// replace_first --------------------------------------------------------------------//
//! Replace first algorithm
/*!
Replace the first match of the search substring in the input
with the format string.
The result is a modified copy of the input. It is returned as a sequence
or copied to the output iterator.
\param Output An output iterator to which the result will be copied
\param Input An input string
\param Search A substring to be searched for
\param Format A substitute string
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<
typename OutputIteratorT,
typename Range1T,
typename Range2T,
typename Range3T>
inline OutputIteratorT replace_first_copy(
OutputIteratorT Output,
const Range1T& Input,
const Range2T& Search,
const Range3T& Format)
{
return ::boost::algorithm::find_format_copy(
Output,
Input,
::boost::algorithm::first_finder(Search),
::boost::algorithm::const_formatter(Format) );
}
//! Replace first algorithm
/*!
\overload
*/
template<typename SequenceT, typename Range1T, typename Range2T>
inline SequenceT replace_first_copy(
const SequenceT& Input,
const Range1T& Search,
const Range2T& Format )
{
return ::boost::algorithm::find_format_copy(
Input,
::boost::algorithm::first_finder(Search),
::boost::algorithm::const_formatter(Format) );
}
//! Replace first algorithm
/*!
replace the first match of the search substring in the input
with the format string. The input sequence is modified in-place.
\param Input An input string
\param Search A substring to be searched for
\param Format A substitute string
*/
template<typename SequenceT, typename Range1T, typename Range2T>
inline void replace_first(
SequenceT& Input,
const Range1T& Search,
const Range2T& Format )
{
::boost::algorithm::find_format(
Input,
::boost::algorithm::first_finder(Search),
::boost::algorithm::const_formatter(Format) );
}
// replace_first ( case insensitive ) ---------------------------------------------//
//! Replace first algorithm ( case insensitive )
/*!
Replace the first match of the search substring in the input
with the format string.
The result is a modified copy of the input. It is returned as a sequence
or copied to the output iterator.
Searching is case insensitive.
\param Output An output iterator to which the result will be copied
\param Input An input string
\param Search A substring to be searched for
\param Format A substitute string
\param Loc A locale used for case insensitive comparison
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<
typename OutputIteratorT,
typename Range1T,
typename Range2T,
typename Range3T>
inline OutputIteratorT ireplace_first_copy(
OutputIteratorT Output,
const Range1T& Input,
const Range2T& Search,
const Range3T& Format,
const std::locale& Loc=std::locale() )
{
return ::boost::algorithm::find_format_copy(
Output,
Input,
::boost::algorithm::first_finder(Search, is_iequal(Loc)),
::boost::algorithm::const_formatter(Format) );
}
//! Replace first algorithm ( case insensitive )
/*!
\overload
*/
template<typename SequenceT, typename Range2T, typename Range1T>
inline SequenceT ireplace_first_copy(
const SequenceT& Input,
const Range2T& Search,
const Range1T& Format,
const std::locale& Loc=std::locale() )
{
return ::boost::algorithm::find_format_copy(
Input,
::boost::algorithm::first_finder(Search, is_iequal(Loc)),
::boost::algorithm::const_formatter(Format) );
}
//! Replace first algorithm ( case insensitive )
/*!
Replace the first match of the search substring in the input
with the format string. Input sequence is modified in-place.
Searching is case insensitive.
\param Input An input string
\param Search A substring to be searched for
\param Format A substitute string
\param Loc A locale used for case insensitive comparison
*/
template<typename SequenceT, typename Range1T, typename Range2T>
inline void ireplace_first(
SequenceT& Input,
const Range1T& Search,
const Range2T& Format,
const std::locale& Loc=std::locale() )
{
::boost::algorithm::find_format(
Input,
::boost::algorithm::first_finder(Search, is_iequal(Loc)),
::boost::algorithm::const_formatter(Format) );
}
// replace_last --------------------------------------------------------------------//
//! Replace last algorithm
/*!
Replace the last match of the search string in the input
with the format string.
The result is a modified copy of the input. It is returned as a sequence
or copied to the output iterator.
\param Output An output iterator to which the result will be copied
\param Input An input string
\param Search A substring to be searched for
\param Format A substitute string
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<
typename OutputIteratorT,
typename Range1T,
typename Range2T,
typename Range3T>
inline OutputIteratorT replace_last_copy(
OutputIteratorT Output,
const Range1T& Input,
const Range2T& Search,
const Range3T& Format )
{
return ::boost::algorithm::find_format_copy(
Output,
Input,
::boost::algorithm::last_finder(Search),
::boost::algorithm::const_formatter(Format) );
}
//! Replace last algorithm
/*!
\overload
*/
template<typename SequenceT, typename Range1T, typename Range2T>
inline SequenceT replace_last_copy(
const SequenceT& Input,
const Range1T& Search,
const Range2T& Format )
{
return ::boost::algorithm::find_format_copy(
Input,
::boost::algorithm::last_finder(Search),
::boost::algorithm::const_formatter(Format) );
}
//! Replace last algorithm
/*!
Replace the last match of the search string in the input
with the format string. Input sequence is modified in-place.
\param Input An input string
\param Search A substring to be searched for
\param Format A substitute string
*/
template<typename SequenceT, typename Range1T, typename Range2T>
inline void replace_last(
SequenceT& Input,
const Range1T& Search,
const Range2T& Format )
{
::boost::algorithm::find_format(
Input,
::boost::algorithm::last_finder(Search),
::boost::algorithm::const_formatter(Format) );
}
// replace_last ( case insensitive ) -----------------------------------------------//
//! Replace last algorithm ( case insensitive )
/*!
Replace the last match of the search string in the input
with the format string.
The result is a modified copy of the input. It is returned as a sequence
or copied to the output iterator.
Searching is case insensitive.
\param Output An output iterator to which the result will be copied
\param Input An input string
\param Search A substring to be searched for
\param Format A substitute string
\param Loc A locale used for case insensitive comparison
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<
typename OutputIteratorT,
typename Range1T,
typename Range2T,
typename Range3T>
inline OutputIteratorT ireplace_last_copy(
OutputIteratorT Output,
const Range1T& Input,
const Range2T& Search,
const Range3T& Format,
const std::locale& Loc=std::locale() )
{
return ::boost::algorithm::find_format_copy(
Output,
Input,
::boost::algorithm::last_finder(Search, is_iequal(Loc)),
::boost::algorithm::const_formatter(Format) );
}
//! Replace last algorithm ( case insensitive )
/*!
\overload
*/
template<typename SequenceT, typename Range1T, typename Range2T>
inline SequenceT ireplace_last_copy(
const SequenceT& Input,
const Range1T& Search,
const Range2T& Format,
const std::locale& Loc=std::locale() )
{
return ::boost::algorithm::find_format_copy(
Input,
::boost::algorithm::last_finder(Search, is_iequal(Loc)),
::boost::algorithm::const_formatter(Format) );
}
//! Replace last algorithm ( case insensitive )
/*!
Replace the last match of the search string in the input
with the format string.The input sequence is modified in-place.
Searching is case insensitive.
\param Input An input string
\param Search A substring to be searched for
\param Format A substitute string
\param Loc A locale used for case insensitive comparison
\return A reference to the modified input
*/
template<typename SequenceT, typename Range1T, typename Range2T>
inline void ireplace_last(
SequenceT& Input,
const Range1T& Search,
const Range2T& Format,
const std::locale& Loc=std::locale() )
{
::boost::algorithm::find_format(
Input,
::boost::algorithm::last_finder(Search, is_iequal(Loc)),
::boost::algorithm::const_formatter(Format) );
}
// replace_nth --------------------------------------------------------------------//
//! Replace nth algorithm
/*!
Replace an Nth (zero-indexed) match of the search string in the input
with the format string.
The result is a modified copy of the input. It is returned as a sequence
or copied to the output iterator.
\param Output An output iterator to which the result will be copied
\param Input An input string
\param Search A substring to be searched for
\param Nth An index of the match to be replaced. The index is 0-based.
For negative N, matches are counted from the end of string.
\param Format A substitute string
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<
typename OutputIteratorT,
typename Range1T,
typename Range2T,
typename Range3T>
inline OutputIteratorT replace_nth_copy(
OutputIteratorT Output,
const Range1T& Input,
const Range2T& Search,
int Nth,
const Range3T& Format )
{
return ::boost::algorithm::find_format_copy(
Output,
Input,
::boost::algorithm::nth_finder(Search, Nth),
::boost::algorithm::const_formatter(Format) );
}
//! Replace nth algorithm
/*!
\overload
*/
template<typename SequenceT, typename Range1T, typename Range2T>
inline SequenceT replace_nth_copy(
const SequenceT& Input,
const Range1T& Search,
int Nth,
const Range2T& Format )
{
return ::boost::algorithm::find_format_copy(
Input,
::boost::algorithm::nth_finder(Search, Nth),
::boost::algorithm::const_formatter(Format) );
}
//! Replace nth algorithm
/*!
Replace an Nth (zero-indexed) match of the search string in the input
with the format string. Input sequence is modified in-place.
\param Input An input string
\param Search A substring to be searched for
\param Nth An index of the match to be replaced. The index is 0-based.
For negative N, matches are counted from the end of string.
\param Format A substitute string
*/
template<typename SequenceT, typename Range1T, typename Range2T>
inline void replace_nth(
SequenceT& Input,
const Range1T& Search,
int Nth,
const Range2T& Format )
{
::boost::algorithm::find_format(
Input,
::boost::algorithm::nth_finder(Search, Nth),
::boost::algorithm::const_formatter(Format) );
}
// replace_nth ( case insensitive ) -----------------------------------------------//
//! Replace nth algorithm ( case insensitive )
/*!
Replace an Nth (zero-indexed) match of the search string in the input
with the format string.
The result is a modified copy of the input. It is returned as a sequence
or copied to the output iterator.
Searching is case insensitive.
\param Output An output iterator to which the result will be copied
\param Input An input string
\param Search A substring to be searched for
\param Nth An index of the match to be replaced. The index is 0-based.
For negative N, matches are counted from the end of string.
\param Format A substitute string
\param Loc A locale used for case insensitive comparison
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<
typename OutputIteratorT,
typename Range1T,
typename Range2T,
typename Range3T>
inline OutputIteratorT ireplace_nth_copy(
OutputIteratorT Output,
const Range1T& Input,
const Range2T& Search,
int Nth,
const Range3T& Format,
const std::locale& Loc=std::locale() )
{
return ::boost::algorithm::find_format_copy(
Output,
Input,
::boost::algorithm::nth_finder(Search, Nth, is_iequal(Loc) ),
::boost::algorithm::const_formatter(Format) );
}
//! Replace nth algorithm ( case insensitive )
/*!
\overload
*/
template<typename SequenceT, typename Range1T, typename Range2T>
inline SequenceT ireplace_nth_copy(
const SequenceT& Input,
const Range1T& Search,
int Nth,
const Range2T& Format,
const std::locale& Loc=std::locale() )
{
return ::boost::algorithm::find_format_copy(
Input,
::boost::algorithm::nth_finder(Search, Nth, is_iequal(Loc)),
::boost::algorithm::const_formatter(Format) );
}
//! Replace nth algorithm ( case insensitive )
/*!
Replace an Nth (zero-indexed) match of the search string in the input
with the format string. Input sequence is modified in-place.
Searching is case insensitive.
\param Input An input string
\param Search A substring to be searched for
\param Nth An index of the match to be replaced. The index is 0-based.
For negative N, matches are counted from the end of string.
\param Format A substitute string
\param Loc A locale used for case insensitive comparison
*/
template<typename SequenceT, typename Range1T, typename Range2T>
inline void ireplace_nth(
SequenceT& Input,
const Range1T& Search,
int Nth,
const Range2T& Format,
const std::locale& Loc=std::locale() )
{
::boost::algorithm::find_format(
Input,
::boost::algorithm::nth_finder(Search, Nth, is_iequal(Loc)),
::boost::algorithm::const_formatter(Format) );
}
// replace_all --------------------------------------------------------------------//
//! Replace all algorithm
/*!
Replace all occurrences of the search string in the input
with the format string.
The result is a modified copy of the input. It is returned as a sequence
or copied to the output iterator.
\param Output An output iterator to which the result will be copied
\param Input An input string
\param Search A substring to be searched for
\param Format A substitute string
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<
typename OutputIteratorT,
typename Range1T,
typename Range2T,
typename Range3T>
inline OutputIteratorT replace_all_copy(
OutputIteratorT Output,
const Range1T& Input,
const Range2T& Search,
const Range3T& Format )
{
return ::boost::algorithm::find_format_all_copy(
Output,
Input,
::boost::algorithm::first_finder(Search),
::boost::algorithm::const_formatter(Format) );
}
//! Replace all algorithm
/*!
\overload
*/
template<typename SequenceT, typename Range1T, typename Range2T>
inline SequenceT replace_all_copy(
const SequenceT& Input,
const Range1T& Search,
const Range2T& Format )
{
return ::boost::algorithm::find_format_all_copy(
Input,
::boost::algorithm::first_finder(Search),
::boost::algorithm::const_formatter(Format) );
}
//! Replace all algorithm
/*!
Replace all occurrences of the search string in the input
with the format string. The input sequence is modified in-place.
\param Input An input string
\param Search A substring to be searched for
\param Format A substitute string
\return A reference to the modified input
*/
template<typename SequenceT, typename Range1T, typename Range2T>
inline void replace_all(
SequenceT& Input,
const Range1T& Search,
const Range2T& Format )
{
::boost::algorithm::find_format_all(
Input,
::boost::algorithm::first_finder(Search),
::boost::algorithm::const_formatter(Format) );
}
// replace_all ( case insensitive ) -----------------------------------------------//
//! Replace all algorithm ( case insensitive )
/*!
Replace all occurrences of the search string in the input
with the format string.
The result is a modified copy of the input. It is returned as a sequence
or copied to the output iterator.
Searching is case insensitive.
\param Output An output iterator to which the result will be copied
\param Input An input string
\param Search A substring to be searched for
\param Format A substitute string
\param Loc A locale used for case insensitive comparison
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<
typename OutputIteratorT,
typename Range1T,
typename Range2T,
typename Range3T>
inline OutputIteratorT ireplace_all_copy(
OutputIteratorT Output,
const Range1T& Input,
const Range2T& Search,
const Range3T& Format,
const std::locale& Loc=std::locale() )
{
return ::boost::algorithm::find_format_all_copy(
Output,
Input,
::boost::algorithm::first_finder(Search, is_iequal(Loc)),
::boost::algorithm::const_formatter(Format) );
}
//! Replace all algorithm ( case insensitive )
/*!
\overload
*/
template<typename SequenceT, typename Range1T, typename Range2T>
inline SequenceT ireplace_all_copy(
const SequenceT& Input,
const Range1T& Search,
const Range2T& Format,
const std::locale& Loc=std::locale() )
{
return ::boost::algorithm::find_format_all_copy(
Input,
::boost::algorithm::first_finder(Search, is_iequal(Loc)),
::boost::algorithm::const_formatter(Format) );
}
//! Replace all algorithm ( case insensitive )
/*!
Replace all occurrences of the search string in the input
with the format string.The input sequence is modified in-place.
Searching is case insensitive.
\param Input An input string
\param Search A substring to be searched for
\param Format A substitute string
\param Loc A locale used for case insensitive comparison
*/
template<typename SequenceT, typename Range1T, typename Range2T>
inline void ireplace_all(
SequenceT& Input,
const Range1T& Search,
const Range2T& Format,
const std::locale& Loc=std::locale() )
{
::boost::algorithm::find_format_all(
Input,
::boost::algorithm::first_finder(Search, is_iequal(Loc)),
::boost::algorithm::const_formatter(Format) );
}
// replace_head --------------------------------------------------------------------//
//! Replace head algorithm
/*!
Replace the head of the input with the given format string.
The head is a prefix of a string of given size.
If the sequence is shorter then required, whole string if
considered to be the head.
The result is a modified copy of the input. It is returned as a sequence
or copied to the output iterator.
\param Output An output iterator to which the result will be copied
\param Input An input string
\param N Length of the head.
For N>=0, at most N characters are extracted.
For N<0, size(Input)-|N| characters are extracted.
\param Format A substitute string
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<
typename OutputIteratorT,
typename Range1T,
typename Range2T>
inline OutputIteratorT replace_head_copy(
OutputIteratorT Output,
const Range1T& Input,
int N,
const Range2T& Format )
{
return ::boost::algorithm::find_format_copy(
Output,
Input,
::boost::algorithm::head_finder(N),
::boost::algorithm::const_formatter(Format) );
}
//! Replace head algorithm
/*!
\overload
*/
template<typename SequenceT, typename RangeT>
inline SequenceT replace_head_copy(
const SequenceT& Input,
int N,
const RangeT& Format )
{
return ::boost::algorithm::find_format_copy(
Input,
::boost::algorithm::head_finder(N),
::boost::algorithm::const_formatter(Format) );
}
//! Replace head algorithm
/*!
Replace the head of the input with the given format string.
The head is a prefix of a string of given size.
If the sequence is shorter then required, the whole string is
considered to be the head. The input sequence is modified in-place.
\param Input An input string
\param N Length of the head.
For N>=0, at most N characters are extracted.
For N<0, size(Input)-|N| characters are extracted.
\param Format A substitute string
*/
template<typename SequenceT, typename RangeT>
inline void replace_head(
SequenceT& Input,
int N,
const RangeT& Format )
{
::boost::algorithm::find_format(
Input,
::boost::algorithm::head_finder(N),
::boost::algorithm::const_formatter(Format) );
}
// replace_tail --------------------------------------------------------------------//
//! Replace tail algorithm
/*!
Replace the tail of the input with the given format string.
The tail is a suffix of a string of given size.
If the sequence is shorter then required, whole string is
considered to be the tail.
The result is a modified copy of the input. It is returned as a sequence
or copied to the output iterator.
\param Output An output iterator to which the result will be copied
\param Input An input string
\param N Length of the tail.
For N>=0, at most N characters are extracted.
For N<0, size(Input)-|N| characters are extracted.
\param Format A substitute string
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<
typename OutputIteratorT,
typename Range1T,
typename Range2T>
inline OutputIteratorT replace_tail_copy(
OutputIteratorT Output,
const Range1T& Input,
int N,
const Range2T& Format )
{
return ::boost::algorithm::find_format_copy(
Output,
Input,
::boost::algorithm::tail_finder(N),
::boost::algorithm::const_formatter(Format) );
}
//! Replace tail algorithm
/*!
\overload
*/
template<typename SequenceT, typename RangeT>
inline SequenceT replace_tail_copy(
const SequenceT& Input,
int N,
const RangeT& Format )
{
return ::boost::algorithm::find_format_copy(
Input,
::boost::algorithm::tail_finder(N),
::boost::algorithm::const_formatter(Format) );
}
//! Replace tail algorithm
/*!
Replace the tail of the input with the given format sequence.
The tail is a suffix of a string of given size.
If the sequence is shorter then required, the whole string is
considered to be the tail. The input sequence is modified in-place.
\param Input An input string
\param N Length of the tail.
For N>=0, at most N characters are extracted.
For N<0, size(Input)-|N| characters are extracted.
\param Format A substitute string
*/
template<typename SequenceT, typename RangeT>
inline void replace_tail(
SequenceT& Input,
int N,
const RangeT& Format )
{
::boost::algorithm::find_format(
Input,
::boost::algorithm::tail_finder(N),
::boost::algorithm::const_formatter(Format) );
}
} // namespace algorithm
// pull names to the boost namespace
using algorithm::replace_range_copy;
using algorithm::replace_range;
using algorithm::replace_first_copy;
using algorithm::replace_first;
using algorithm::ireplace_first_copy;
using algorithm::ireplace_first;
using algorithm::replace_last_copy;
using algorithm::replace_last;
using algorithm::ireplace_last_copy;
using algorithm::ireplace_last;
using algorithm::replace_nth_copy;
using algorithm::replace_nth;
using algorithm::ireplace_nth_copy;
using algorithm::ireplace_nth;
using algorithm::replace_all_copy;
using algorithm::replace_all;
using algorithm::ireplace_all_copy;
using algorithm::ireplace_all;
using algorithm::replace_head_copy;
using algorithm::replace_head;
using algorithm::replace_tail_copy;
using algorithm::replace_tail;
} // namespace boost
#endif // BOOST_REPLACE_HPP

View File

@@ -0,0 +1,120 @@
// Boost string_algo library sequence_traits.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_SEQUENCE_TRAITS_HPP
#define BOOST_STRING_SEQUENCE_TRAITS_HPP
#include <boost/config.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/algorithm/string/yes_no_type.hpp>
/*! \file
Traits defined in this header are used by various algorithms to achieve
better performance for specific containers.
Traits provide fail-safe defaults. If a container supports some of these
features, it is possible to specialize the specific trait for this container.
For lacking compilers, it is possible of define an override for a specific tester
function.
Due to a language restriction, it is not currently possible to define specializations for
stl containers without including the corresponding header. To decrease the overhead
needed by this inclusion, user can selectively include a specialization
header for a specific container. They are located in boost/algorithm/string/stl
directory. Alternatively she can include boost/algorithm/string/std_collection_traits.hpp
header which contains specializations for all stl containers.
*/
namespace boost {
namespace algorithm {
// sequence traits -----------------------------------------------//
//! Native replace trait
/*!
This trait specifies that the sequence has \c std::string like replace method
*/
template< typename T >
class has_native_replace
{
public:
# if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = false };
# else
BOOST_STATIC_CONSTANT(bool, value=false);
# endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
typedef mpl::bool_<has_native_replace<T>::value> type;
};
//! Stable iterators trait
/*!
This trait specifies that the sequence has stable iterators. It means
that operations like insert/erase/replace do not invalidate iterators.
*/
template< typename T >
class has_stable_iterators
{
public:
# if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = false };
# else
BOOST_STATIC_CONSTANT(bool, value=false);
# endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
typedef mpl::bool_<has_stable_iterators<T>::value> type;
};
//! Const time insert trait
/*!
This trait specifies that the sequence's insert method has
constant time complexity.
*/
template< typename T >
class has_const_time_insert
{
public:
# if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = false };
# else
BOOST_STATIC_CONSTANT(bool, value=false);
# endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
typedef mpl::bool_<has_const_time_insert<T>::value> type;
};
//! Const time erase trait
/*!
This trait specifies that the sequence's erase method has
constant time complexity.
*/
template< typename T >
class has_const_time_erase
{
public:
# if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = false };
# else
BOOST_STATIC_CONSTANT(bool, value=false);
# endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
typedef mpl::bool_<has_const_time_erase<T>::value> type;
};
} // namespace algorithm
} // namespace boost
#endif // BOOST_STRING_SEQUENCE_TRAITS_HPP

View File

@@ -0,0 +1,163 @@
// Boost string_algo library split.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2006.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_SPLIT_HPP
#define BOOST_STRING_SPLIT_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/algorithm/string/iter_find.hpp>
#include <boost/algorithm/string/finder.hpp>
#include <boost/algorithm/string/compare.hpp>
/*! \file
Defines basic split algorithms.
Split algorithms can be used to divide a string
into several parts according to given criteria.
Each part is copied and added as a new element to the
output container.
Thus the result container must be able to hold copies
of the matches (in a compatible structure like std::string) or
a reference to it (e.g. using the iterator range class).
Examples of such a container are \c std::vector<std::string>
or \c std::list<boost::iterator_range<std::string::iterator>>
*/
namespace boost {
namespace algorithm {
// find_all ------------------------------------------------------------//
//! Find all algorithm
/*!
This algorithm finds all occurrences of the search string
in the input.
Each part is copied and added as a new element to the
output container.
Thus the result container must be able to hold copies
of the matches (in a compatible structure like std::string) or
a reference to it (e.g. using the iterator range class).
Examples of such a container are \c std::vector<std::string>
or \c std::list<boost::iterator_range<std::string::iterator>>
\param Result A container that can hold copies of references to the substrings
\param Input A container which will be searched.
\param Search A substring to be searched for.
\return A reference the result
\note Prior content of the result will be overwritten.
\note This function provides the strong exception-safety guarantee
*/
template< typename SequenceSequenceT, typename Range1T, typename Range2T >
inline SequenceSequenceT& find_all(
SequenceSequenceT& Result,
Range1T& Input,
const Range2T& Search)
{
return ::boost::algorithm::iter_find(
Result,
Input,
::boost::algorithm::first_finder(Search) );
}
//! Find all algorithm ( case insensitive )
/*!
This algorithm finds all occurrences of the search string
in the input.
Each part is copied and added as a new element to the
output container. Thus the result container must be able to hold copies
of the matches (in a compatible structure like std::string) or
a reference to it (e.g. using the iterator range class).
Examples of such a container are \c std::vector<std::string>
or \c std::list<boost::iterator_range<std::string::iterator>>
Searching is case insensitive.
\param Result A container that can hold copies of references to the substrings
\param Input A container which will be searched.
\param Search A substring to be searched for.
\param Loc A locale used for case insensitive comparison
\return A reference the result
\note Prior content of the result will be overwritten.
\note This function provides the strong exception-safety guarantee
*/
template< typename SequenceSequenceT, typename Range1T, typename Range2T >
inline SequenceSequenceT& ifind_all(
SequenceSequenceT& Result,
Range1T& Input,
const Range2T& Search,
const std::locale& Loc=std::locale() )
{
return ::boost::algorithm::iter_find(
Result,
Input,
::boost::algorithm::first_finder(Search, is_iequal(Loc) ) );
}
// tokenize -------------------------------------------------------------//
//! Split algorithm
/*!
Tokenize expression. This function is equivalent to C strtok. Input
sequence is split into tokens, separated by separators. Separators
are given by means of the predicate.
Each part is copied and added as a new element to the
output container.
Thus the result container must be able to hold copies
of the matches (in a compatible structure like std::string) or
a reference to it (e.g. using the iterator range class).
Examples of such a container are \c std::vector<std::string>
or \c std::list<boost::iterator_range<std::string::iterator>>
\param Result A container that can hold copies of references to the substrings
\param Input A container which will be searched.
\param Pred A predicate to identify separators. This predicate is
supposed to return true if a given element is a separator.
\param eCompress If eCompress argument is set to token_compress_on, adjacent
separators are merged together. Otherwise, every two separators
delimit a token.
\return A reference the result
\note Prior content of the result will be overwritten.
\note This function provides the strong exception-safety guarantee
*/
template< typename SequenceSequenceT, typename RangeT, typename PredicateT >
inline SequenceSequenceT& split(
SequenceSequenceT& Result,
RangeT& Input,
PredicateT Pred,
token_compress_mode_type eCompress=token_compress_off )
{
return ::boost::algorithm::iter_split(
Result,
Input,
::boost::algorithm::token_finder( Pred, eCompress ) );
}
} // namespace algorithm
// pull names to the boost namespace
using algorithm::find_all;
using algorithm::ifind_all;
using algorithm::split;
} // namespace boost
#endif // BOOST_STRING_SPLIT_HPP

View File

@@ -0,0 +1,68 @@
// Boost string_algo library list_traits.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_STD_LIST_TRAITS_HPP
#define BOOST_STRING_STD_LIST_TRAITS_HPP
#include <boost/algorithm/string/yes_no_type.hpp>
#include <list>
#include <boost/algorithm/string/sequence_traits.hpp>
namespace boost {
namespace algorithm {
// std::list<> traits -----------------------------------------------//
// stable iterators trait
template<typename T, typename AllocT>
class has_stable_iterators< ::std::list<T,AllocT> >
{
public:
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = true };
#else
BOOST_STATIC_CONSTANT(bool, value=true);
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
typedef mpl::bool_<has_stable_iterators<T>::value> type;
};
// const time insert trait
template<typename T, typename AllocT>
class has_const_time_insert< ::std::list<T,AllocT> >
{
public:
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = true };
#else
BOOST_STATIC_CONSTANT(bool, value=true);
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
typedef mpl::bool_<has_const_time_insert<T>::value> type;
};
// const time erase trait
template<typename T, typename AllocT>
class has_const_time_erase< ::std::list<T,AllocT> >
{
public:
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = true };
#else
BOOST_STATIC_CONSTANT(bool, value=true);
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
typedef mpl::bool_<has_const_time_erase<T>::value> type;
};
} // namespace algorithm
} // namespace boost
#endif // BOOST_STRING_STD_LIST_TRAITS_HPP

View File

@@ -0,0 +1,81 @@
// Boost string_algo library string_traits.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_STD_ROPE_TRAITS_HPP
#define BOOST_STRING_STD_ROPE_TRAITS_HPP
#include <boost/algorithm/string/yes_no_type.hpp>
#include <rope>
#include <boost/algorithm/string/sequence_traits.hpp>
namespace boost {
namespace algorithm {
// SGI's std::rope<> traits -----------------------------------------------//
// native replace trait
template<typename T, typename TraitsT, typename AllocT>
class has_native_replace< std::rope<T,TraitsT,AllocT> >
{
public:
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = true };
#else
BOOST_STATIC_CONSTANT(bool, value=true);
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
typedef mpl::bool_<value> type;
};
// stable iterators trait
template<typename T, typename TraitsT, typename AllocT>
class has_stable_iterators< std::rope<T,TraitsT,AllocT> >
{
public:
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = true };
#else
BOOST_STATIC_CONSTANT(bool, value=true);
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
typedef mpl::bool_<value> type;
};
// const time insert trait
template<typename T, typename TraitsT, typename AllocT>
class has_const_time_insert< std::rope<T,TraitsT,AllocT> >
{
public:
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = true };
#else
BOOST_STATIC_CONSTANT(bool, value=true);
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
typedef mpl::bool_<value> type;
};
// const time erase trait
template<typename T, typename TraitsT, typename AllocT>
class has_const_time_erase< std::rope<T,TraitsT,AllocT> >
{
public:
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = true };
#else
BOOST_STATIC_CONSTANT(bool, value=true);
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
typedef mpl::bool_<value> type;
};
} // namespace algorithm
} // namespace boost
#endif // BOOST_STRING_ROPE_TRAITS_HPP

View File

@@ -0,0 +1,69 @@
// Boost string_algo library slist_traits.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_STD_SLIST_TRAITS_HPP
#define BOOST_STRING_STD_SLIST_TRAITS_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/algorithm/string/yes_no_type.hpp>
#include BOOST_SLIST_HEADER
#include <boost/algorithm/string/sequence_traits.hpp>
namespace boost {
namespace algorithm {
// SGI's std::slist<> traits -----------------------------------------------//
// stable iterators trait
template<typename T, typename AllocT>
class has_stable_iterators< BOOST_STD_EXTENSION_NAMESPACE::slist<T,AllocT> >
{
public:
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = true };
#else
BOOST_STATIC_CONSTANT(bool, value=true);
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
typedef mpl::bool_<has_stable_iterators<T>::value> type;
};
// const time insert trait
template<typename T, typename AllocT>
class has_const_time_insert< BOOST_STD_EXTENSION_NAMESPACE::slist<T,AllocT> >
{
public:
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = true };
#else
BOOST_STATIC_CONSTANT(bool, value=true);
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
typedef mpl::bool_<has_const_time_insert<T>::value> type;
};
// const time erase trait
template<typename T, typename AllocT>
class has_const_time_erase< BOOST_STD_EXTENSION_NAMESPACE::slist<T,AllocT> >
{
public:
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = true };
#else
BOOST_STATIC_CONSTANT(bool, value=true);
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
typedef mpl::bool_<has_const_time_erase<T>::value> type;
};
} // namespace algorithm
} // namespace boost
#endif // BOOST_STRING_STD_LIST_TRAITS_HPP

View File

@@ -0,0 +1,44 @@
// Boost string_algo library string_traits.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_STD_STRING_TRAITS_HPP
#define BOOST_STRING_STD_STRING_TRAITS_HPP
#include <boost/algorithm/string/yes_no_type.hpp>
#include <string>
#include <boost/algorithm/string/sequence_traits.hpp>
namespace boost {
namespace algorithm {
// std::basic_string<> traits -----------------------------------------------//
// native replace trait
template<typename T, typename TraitsT, typename AllocT>
class has_native_replace< std::basic_string<T, TraitsT, AllocT> >
{
public:
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = true } ;
#else
BOOST_STATIC_CONSTANT(bool, value=true);
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
typedef mpl::bool_<has_native_replace<T>::value> type;
};
} // namespace algorithm
} // namespace boost
#endif // BOOST_STRING_LIST_TRAITS_HPP

View File

@@ -0,0 +1,26 @@
// Boost string_algo library std_containers_traits.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_STD_CONTAINERS_TRAITS_HPP
#define BOOST_STRING_STD_CONTAINERS_TRAITS_HPP
/*!\file
This file includes sequence traits for stl containers.
*/
#include <boost/config.hpp>
#include <boost/algorithm/string/std/string_traits.hpp>
#include <boost/algorithm/string/std/list_traits.hpp>
#ifdef BOOST_HAS_SLIST
# include <boost/algorithm/string/std/slist_traits.hpp>
#endif
#endif // BOOST_STRING_STD_CONTAINERS_TRAITS_HPP

View File

@@ -0,0 +1,398 @@
// Boost string_algo library trim.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_TRIM_HPP
#define BOOST_STRING_TRIM_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/const_iterator.hpp>
#include <boost/range/as_literal.hpp>
#include <boost/range/iterator_range_core.hpp>
#include <boost/algorithm/string/detail/trim.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <locale>
/*! \file
Defines trim algorithms.
Trim algorithms are used to remove trailing and leading spaces from a
sequence (string). Space is recognized using given locales.
Parametric (\c _if) variants use a predicate (functor) to select which characters
are to be trimmed..
Functions take a selection predicate as a parameter, which is used to determine
whether a character is a space. Common predicates are provided in classification.hpp header.
*/
namespace boost {
namespace algorithm {
// left trim -----------------------------------------------//
//! Left trim - parametric
/*!
Remove all leading spaces from the input.
The supplied predicate is used to determine which characters are considered spaces.
The result is a trimmed copy of the input. It is returned as a sequence
or copied to the output iterator
\param Output An output iterator to which the result will be copied
\param Input An input range
\param IsSpace A unary predicate identifying spaces
\return
An output iterator pointing just after the last inserted character or
a copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<typename OutputIteratorT, typename RangeT, typename PredicateT>
inline OutputIteratorT trim_left_copy_if(
OutputIteratorT Output,
const RangeT& Input,
PredicateT IsSpace)
{
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> lit_range(::boost::as_literal(Input));
std::copy(
::boost::algorithm::detail::trim_begin(
::boost::begin(lit_range),
::boost::end(lit_range),
IsSpace ),
::boost::end(lit_range),
Output);
return Output;
}
//! Left trim - parametric
/*!
\overload
*/
template<typename SequenceT, typename PredicateT>
inline SequenceT trim_left_copy_if(const SequenceT& Input, PredicateT IsSpace)
{
return SequenceT(
::boost::algorithm::detail::trim_begin(
::boost::begin(Input),
::boost::end(Input),
IsSpace ),
::boost::end(Input));
}
//! Left trim - parametric
/*!
Remove all leading spaces from the input.
The result is a trimmed copy of the input.
\param Input An input sequence
\param Loc a locale used for 'space' classification
\return A trimmed copy of the input
\note This function provides the strong exception-safety guarantee
*/
template<typename SequenceT>
inline SequenceT trim_left_copy(const SequenceT& Input, const std::locale& Loc=std::locale())
{
return
::boost::algorithm::trim_left_copy_if(
Input,
is_space(Loc));
}
//! Left trim
/*!
Remove all leading spaces from the input. The supplied predicate is
used to determine which characters are considered spaces.
The input sequence is modified in-place.
\param Input An input sequence
\param IsSpace A unary predicate identifying spaces
*/
template<typename SequenceT, typename PredicateT>
inline void trim_left_if(SequenceT& Input, PredicateT IsSpace)
{
Input.erase(
::boost::begin(Input),
::boost::algorithm::detail::trim_begin(
::boost::begin(Input),
::boost::end(Input),
IsSpace));
}
//! Left trim
/*!
Remove all leading spaces from the input.
The Input sequence is modified in-place.
\param Input An input sequence
\param Loc A locale used for 'space' classification
*/
template<typename SequenceT>
inline void trim_left(SequenceT& Input, const std::locale& Loc=std::locale())
{
::boost::algorithm::trim_left_if(
Input,
is_space(Loc));
}
// right trim -----------------------------------------------//
//! Right trim - parametric
/*!
Remove all trailing spaces from the input.
The supplied predicate is used to determine which characters are considered spaces.
The result is a trimmed copy of the input. It is returned as a sequence
or copied to the output iterator
\param Output An output iterator to which the result will be copied
\param Input An input range
\param IsSpace A unary predicate identifying spaces
\return
An output iterator pointing just after the last inserted character or
a copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<typename OutputIteratorT, typename RangeT, typename PredicateT>
inline OutputIteratorT trim_right_copy_if(
OutputIteratorT Output,
const RangeT& Input,
PredicateT IsSpace )
{
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> lit_range(::boost::as_literal(Input));
std::copy(
::boost::begin(lit_range),
::boost::algorithm::detail::trim_end(
::boost::begin(lit_range),
::boost::end(lit_range),
IsSpace ),
Output );
return Output;
}
//! Right trim - parametric
/*!
\overload
*/
template<typename SequenceT, typename PredicateT>
inline SequenceT trim_right_copy_if(const SequenceT& Input, PredicateT IsSpace)
{
return SequenceT(
::boost::begin(Input),
::boost::algorithm::detail::trim_end(
::boost::begin(Input),
::boost::end(Input),
IsSpace)
);
}
//! Right trim
/*!
Remove all trailing spaces from the input.
The result is a trimmed copy of the input
\param Input An input sequence
\param Loc A locale used for 'space' classification
\return A trimmed copy of the input
\note This function provides the strong exception-safety guarantee
*/
template<typename SequenceT>
inline SequenceT trim_right_copy(const SequenceT& Input, const std::locale& Loc=std::locale())
{
return
::boost::algorithm::trim_right_copy_if(
Input,
is_space(Loc));
}
//! Right trim - parametric
/*!
Remove all trailing spaces from the input.
The supplied predicate is used to determine which characters are considered spaces.
The input sequence is modified in-place.
\param Input An input sequence
\param IsSpace A unary predicate identifying spaces
*/
template<typename SequenceT, typename PredicateT>
inline void trim_right_if(SequenceT& Input, PredicateT IsSpace)
{
Input.erase(
::boost::algorithm::detail::trim_end(
::boost::begin(Input),
::boost::end(Input),
IsSpace ),
::boost::end(Input)
);
}
//! Right trim
/*!
Remove all trailing spaces from the input.
The input sequence is modified in-place.
\param Input An input sequence
\param Loc A locale used for 'space' classification
*/
template<typename SequenceT>
inline void trim_right(SequenceT& Input, const std::locale& Loc=std::locale())
{
::boost::algorithm::trim_right_if(
Input,
is_space(Loc) );
}
// both side trim -----------------------------------------------//
//! Trim - parametric
/*!
Remove all trailing and leading spaces from the input.
The supplied predicate is used to determine which characters are considered spaces.
The result is a trimmed copy of the input. It is returned as a sequence
or copied to the output iterator
\param Output An output iterator to which the result will be copied
\param Input An input range
\param IsSpace A unary predicate identifying spaces
\return
An output iterator pointing just after the last inserted character or
a copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<typename OutputIteratorT, typename RangeT, typename PredicateT>
inline OutputIteratorT trim_copy_if(
OutputIteratorT Output,
const RangeT& Input,
PredicateT IsSpace)
{
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> lit_range(::boost::as_literal(Input));
BOOST_STRING_TYPENAME
range_const_iterator<RangeT>::type TrimEnd=
::boost::algorithm::detail::trim_end(
::boost::begin(lit_range),
::boost::end(lit_range),
IsSpace);
std::copy(
detail::trim_begin(
::boost::begin(lit_range), TrimEnd, IsSpace),
TrimEnd,
Output
);
return Output;
}
//! Trim - parametric
/*!
\overload
*/
template<typename SequenceT, typename PredicateT>
inline SequenceT trim_copy_if(const SequenceT& Input, PredicateT IsSpace)
{
BOOST_STRING_TYPENAME
range_const_iterator<SequenceT>::type TrimEnd=
::boost::algorithm::detail::trim_end(
::boost::begin(Input),
::boost::end(Input),
IsSpace);
return SequenceT(
detail::trim_begin(
::boost::begin(Input),
TrimEnd,
IsSpace),
TrimEnd
);
}
//! Trim
/*!
Remove all leading and trailing spaces from the input.
The result is a trimmed copy of the input
\param Input An input sequence
\param Loc A locale used for 'space' classification
\return A trimmed copy of the input
\note This function provides the strong exception-safety guarantee
*/
template<typename SequenceT>
inline SequenceT trim_copy( const SequenceT& Input, const std::locale& Loc=std::locale() )
{
return
::boost::algorithm::trim_copy_if(
Input,
is_space(Loc) );
}
//! Trim
/*!
Remove all leading and trailing spaces from the input.
The supplied predicate is used to determine which characters are considered spaces.
The input sequence is modified in-place.
\param Input An input sequence
\param IsSpace A unary predicate identifying spaces
*/
template<typename SequenceT, typename PredicateT>
inline void trim_if(SequenceT& Input, PredicateT IsSpace)
{
::boost::algorithm::trim_right_if( Input, IsSpace );
::boost::algorithm::trim_left_if( Input, IsSpace );
}
//! Trim
/*!
Remove all leading and trailing spaces from the input.
The input sequence is modified in-place.
\param Input An input sequence
\param Loc A locale used for 'space' classification
*/
template<typename SequenceT>
inline void trim(SequenceT& Input, const std::locale& Loc=std::locale())
{
::boost::algorithm::trim_if(
Input,
is_space( Loc ) );
}
} // namespace algorithm
// pull names to the boost namespace
using algorithm::trim_left;
using algorithm::trim_left_if;
using algorithm::trim_left_copy;
using algorithm::trim_left_copy_if;
using algorithm::trim_right;
using algorithm::trim_right_if;
using algorithm::trim_right_copy;
using algorithm::trim_right_copy_if;
using algorithm::trim;
using algorithm::trim_if;
using algorithm::trim_copy;
using algorithm::trim_copy_if;
} // namespace boost
#endif // BOOST_STRING_TRIM_HPP

View File

@@ -0,0 +1,217 @@
// Boost string_algo library trim.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_TRIM_ALL_HPP
#define BOOST_STRING_TRIM_ALL_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/find_format.hpp>
#include <boost/algorithm/string/formatter.hpp>
#include <boost/algorithm/string/finder.hpp>
#include <locale>
/*! \file
Defines trim_all algorithms.
Just like \c trim, \c trim_all removes all trailing and leading spaces from a
sequence (string). In addition, spaces in the middle of the sequence are truncated
to just one character. Space is recognized using given locales.
\c trim_fill acts as trim_all, but the spaces in the middle are replaces with
a user-define sequence of character.
Parametric (\c _if) variants use a predicate (functor) to select which characters
are to be trimmed..
Functions take a selection predicate as a parameter, which is used to determine
whether a character is a space. Common predicates are provided in classification.hpp header.
*/
namespace boost {
namespace algorithm {
// multi line trim ----------------------------------------------- //
//! Trim All - parametric
/*!
Remove all leading and trailing spaces from the input and
compress all other spaces to a single character.
The result is a trimmed copy of the input
\param Input An input sequence
\param IsSpace A unary predicate identifying spaces
\return A trimmed copy of the input
*/
template<typename SequenceT, typename PredicateT>
inline SequenceT trim_all_copy_if(const SequenceT& Input, PredicateT IsSpace)
{
return
::boost::find_format_all_copy(
::boost::trim_copy_if(Input, IsSpace),
::boost::token_finder(IsSpace, ::boost::token_compress_on),
::boost::dissect_formatter(::boost::head_finder(1)));
}
//! Trim All
/*!
Remove all leading and trailing spaces from the input and
compress all other spaces to a single character.
The input sequence is modified in-place.
\param Input An input sequence
\param IsSpace A unary predicate identifying spaces
*/
template<typename SequenceT, typename PredicateT>
inline void trim_all_if(SequenceT& Input, PredicateT IsSpace)
{
::boost::trim_if(Input, IsSpace);
::boost::find_format_all(
Input,
::boost::token_finder(IsSpace, ::boost::token_compress_on),
::boost::dissect_formatter(::boost::head_finder(1)));
}
//! Trim All
/*!
Remove all leading and trailing spaces from the input and
compress all other spaces to a single character.
The result is a trimmed copy of the input
\param Input An input sequence
\param Loc A locale used for 'space' classification
\return A trimmed copy of the input
*/
template<typename SequenceT>
inline SequenceT trim_all_copy(const SequenceT& Input, const std::locale& Loc =std::locale())
{
return trim_all_copy_if(Input, ::boost::is_space(Loc));
}
//! Trim All
/*!
Remove all leading and trailing spaces from the input and
compress all other spaces to a single character.
The input sequence is modified in-place.
\param Input An input sequence
\param Loc A locale used for 'space' classification
\return A trimmed copy of the input
*/
template<typename SequenceT>
inline void trim_all(SequenceT& Input, const std::locale& Loc =std::locale())
{
trim_all_if(Input, ::boost::is_space(Loc));
}
//! Trim Fill - parametric
/*!
Remove all leading and trailing spaces from the input and
replace all every block of consecutive spaces with a fill string
defined by user.
The result is a trimmed copy of the input
\param Input An input sequence
\param Fill A string used to fill the inner spaces
\param IsSpace A unary predicate identifying spaces
\return A trimmed copy of the input
*/
template<typename SequenceT, typename RangeT, typename PredicateT>
inline SequenceT trim_fill_copy_if(const SequenceT& Input, const RangeT& Fill, PredicateT IsSpace)
{
return
::boost::find_format_all_copy(
::boost::trim_copy_if(Input, IsSpace),
::boost::token_finder(IsSpace, ::boost::token_compress_on),
::boost::const_formatter(::boost::as_literal(Fill)));
}
//! Trim Fill
/*!
Remove all leading and trailing spaces from the input and
replace all every block of consecutive spaces with a fill string
defined by user.
The input sequence is modified in-place.
\param Input An input sequence
\param Fill A string used to fill the inner spaces
\param IsSpace A unary predicate identifying spaces
*/
template<typename SequenceT, typename RangeT, typename PredicateT>
inline void trim_fill_if(SequenceT& Input, const RangeT& Fill, PredicateT IsSpace)
{
::boost::trim_if(Input, IsSpace);
::boost::find_format_all(
Input,
::boost::token_finder(IsSpace, ::boost::token_compress_on),
::boost::const_formatter(::boost::as_literal(Fill)));
}
//! Trim Fill
/*!
Remove all leading and trailing spaces from the input and
replace all every block of consecutive spaces with a fill string
defined by user.
The result is a trimmed copy of the input
\param Input An input sequence
\param Fill A string used to fill the inner spaces
\param Loc A locale used for 'space' classification
\return A trimmed copy of the input
*/
template<typename SequenceT, typename RangeT>
inline SequenceT trim_fill_copy(const SequenceT& Input, const RangeT& Fill, const std::locale& Loc =std::locale())
{
return trim_fill_copy_if(Input, Fill, ::boost::is_space(Loc));
}
//! Trim Fill
/*!
Remove all leading and trailing spaces from the input and
replace all every block of consecutive spaces with a fill string
defined by user.
The input sequence is modified in-place.
\param Input An input sequence
\param Fill A string used to fill the inner spaces
\param Loc A locale used for 'space' classification
\return A trimmed copy of the input
*/
template<typename SequenceT, typename RangeT>
inline void trim_fill(SequenceT& Input, const RangeT& Fill, const std::locale& Loc =std::locale())
{
trim_fill_if(Input, Fill, ::boost::is_space(Loc));
}
} // namespace algorithm
// pull names to the boost namespace
using algorithm::trim_all;
using algorithm::trim_all_if;
using algorithm::trim_all_copy;
using algorithm::trim_all_copy_if;
using algorithm::trim_fill;
using algorithm::trim_fill_if;
using algorithm::trim_fill_copy;
using algorithm::trim_fill_copy_if;
} // namespace boost
#endif // BOOST_STRING_TRIM_ALL_HPP

View File

@@ -0,0 +1,33 @@
// Boost string_algo library yes_no_type.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_YES_NO_TYPE_DETAIL_HPP
#define BOOST_STRING_YES_NO_TYPE_DETAIL_HPP
namespace boost {
namespace algorithm {
// taken from boost mailing-list
// when yes_no_type will become officially
// a part of boost distribution, this header
// will be deprecated
template<int I> struct size_descriptor
{
typedef char (& type)[I];
};
typedef size_descriptor<1>::type yes_type;
typedef size_descriptor<2>::type no_type;
} // namespace algorithm
} // namespace boost
#endif // BOOST_STRING_YES_NO_TYPE_DETAIL_HPP

View File

@@ -0,0 +1,20 @@
/*
(c) 2014-2015 Glen Joseph Fernandes
<glenjofe -at- gmail.com>
Distributed under the Boost Software
License, Version 1.0.
http://boost.org/LICENSE_1_0.txt
*/
#ifndef BOOST_ALIGN_ALIGN_HPP
#define BOOST_ALIGN_ALIGN_HPP
#include <boost/config.hpp>
#if !defined(BOOST_NO_CXX11_STD_ALIGN)
#include <boost/align/detail/align_cxx11.hpp>
#else
#include <boost/align/detail/align.hpp>
#endif
#endif

View File

@@ -0,0 +1,38 @@
/*
(c) 2014 Glen Joseph Fernandes
<glenjofe -at- gmail.com>
Distributed under the Boost Software
License, Version 1.0.
http://boost.org/LICENSE_1_0.txt
*/
#ifndef BOOST_ALIGN_DETAIL_ALIGN_HPP
#define BOOST_ALIGN_DETAIL_ALIGN_HPP
#include <boost/align/detail/is_alignment.hpp>
#include <boost/assert.hpp>
namespace boost {
namespace alignment {
inline void* align(std::size_t alignment, std::size_t size,
void*& ptr, std::size_t& space)
{
BOOST_ASSERT(detail::is_alignment(alignment));
if (size <= space) {
char* p = reinterpret_cast<char*>((reinterpret_cast<std::
size_t>(ptr) + alignment - 1) & ~(alignment - 1));
std::ptrdiff_t n = p - static_cast<char*>(ptr);
if (size <= space - n) {
ptr = p;
space -= n;
return p;
}
}
return 0;
}
} /* .alignment */
} /* .boost */
#endif

View File

@@ -0,0 +1,22 @@
/*
(c) 2014 Glen Joseph Fernandes
<glenjofe -at- gmail.com>
Distributed under the Boost Software
License, Version 1.0.
http://boost.org/LICENSE_1_0.txt
*/
#ifndef BOOST_ALIGN_DETAIL_ALIGN_CXX11_HPP
#define BOOST_ALIGN_DETAIL_ALIGN_CXX11_HPP
#include <memory>
namespace boost {
namespace alignment {
using std::align;
} /* .alignment */
} /* .boost */
#endif

View File

@@ -0,0 +1,29 @@
/*
(c) 2014 Glen Joseph Fernandes
<glenjofe -at- gmail.com>
Distributed under the Boost Software
License, Version 1.0.
http://boost.org/LICENSE_1_0.txt
*/
#ifndef BOOST_ALIGN_DETAIL_IS_ALIGNMENT_HPP
#define BOOST_ALIGN_DETAIL_IS_ALIGNMENT_HPP
#include <boost/config.hpp>
#include <cstddef>
namespace boost {
namespace alignment {
namespace detail {
BOOST_CONSTEXPR inline bool is_alignment(std::size_t value)
BOOST_NOEXCEPT
{
return (value > 0) && ((value & (value - 1)) == 0);
}
} /* .detail */
} /* .alignment */
} /* .boost */
#endif

View File

@@ -0,0 +1,18 @@
//-----------------------------------------------------------------------------
// boost aligned_storage.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2002-2003
// Eric Friedman, Itay Maman
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_ALIGNED_STORAGE_HPP
#define BOOST_ALIGNED_STORAGE_HPP
#include <boost/type_traits/aligned_storage.hpp>
#endif // BOOST_ALIGNED_STORAGE_HPP

View File

@@ -0,0 +1,446 @@
/* The following code declares class array,
* an STL container (as wrapper) for arrays of constant size.
*
* See
* http://www.boost.org/libs/array/
* for documentation.
*
* The original author site is at: http://www.josuttis.com/
*
* (C) Copyright Nicolai M. Josuttis 2001.
*
* Distributed under the Boost Software License, Version 1.0. (See
* accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* 14 Apr 2012 - (mtc) Added support for boost::hash
* 28 Dec 2010 - (mtc) Added cbegin and cend (and crbegin and crend) for C++Ox compatibility.
* 10 Mar 2010 - (mtc) fill method added, matching resolution of the standard library working group.
* See <http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#776> or Trac issue #3168
* Eventually, we should remove "assign" which is now a synonym for "fill" (Marshall Clow)
* 10 Mar 2010 - added workaround for SUNCC and !STLPort [trac #3893] (Marshall Clow)
* 29 Jan 2004 - c_array() added, BOOST_NO_PRIVATE_IN_AGGREGATE removed (Nico Josuttis)
* 23 Aug 2002 - fix for Non-MSVC compilers combined with MSVC libraries.
* 05 Aug 2001 - minor update (Nico Josuttis)
* 20 Jan 2001 - STLport fix (Beman Dawes)
* 29 Sep 2000 - Initial Revision (Nico Josuttis)
*
* Jan 29, 2004
*/
#ifndef BOOST_ARRAY_HPP
#define BOOST_ARRAY_HPP
#include <boost/detail/workaround.hpp>
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
# pragma warning(push)
# pragma warning(disable:4996) // 'std::equal': Function call with parameters that may be unsafe
# pragma warning(disable:4510) // boost::array<T,N>' : default constructor could not be generated
# pragma warning(disable:4610) // warning C4610: class 'boost::array<T,N>' can never be instantiated - user defined constructor required
#endif
#include <cstddef>
#include <stdexcept>
#include <boost/assert.hpp>
#include <boost/swap.hpp>
// Handles broken standard libraries better than <iterator>
#include <boost/detail/iterator.hpp>
#include <boost/throw_exception.hpp>
#include <boost/functional/hash_fwd.hpp>
#include <algorithm>
// FIXES for broken compilers
#include <boost/config.hpp>
namespace boost {
template<class T, std::size_t N>
class array {
public:
T elems[N]; // fixed-size array of elements of type T
public:
// type definitions
typedef T value_type;
typedef T* iterator;
typedef const T* const_iterator;
typedef T& reference;
typedef const T& const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
// iterator support
iterator begin() { return elems; }
const_iterator begin() const { return elems; }
const_iterator cbegin() const { return elems; }
iterator end() { return elems+N; }
const_iterator end() const { return elems+N; }
const_iterator cend() const { return elems+N; }
// reverse iterator support
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
#elif defined(_MSC_VER) && (_MSC_VER == 1300) && defined(BOOST_DINKUMWARE_STDLIB) && (BOOST_DINKUMWARE_STDLIB == 310)
// workaround for broken reverse_iterator in VC7
typedef std::reverse_iterator<std::_Ptrit<value_type, difference_type, iterator,
reference, iterator, reference> > reverse_iterator;
typedef std::reverse_iterator<std::_Ptrit<value_type, difference_type, const_iterator,
const_reference, iterator, reference> > const_reverse_iterator;
#elif defined(_RWSTD_NO_CLASS_PARTIAL_SPEC)
typedef std::reverse_iterator<iterator, std::random_access_iterator_tag,
value_type, reference, iterator, difference_type> reverse_iterator;
typedef std::reverse_iterator<const_iterator, std::random_access_iterator_tag,
value_type, const_reference, const_iterator, difference_type> const_reverse_iterator;
#else
// workaround for broken reverse_iterator implementations
typedef std::reverse_iterator<iterator,T> reverse_iterator;
typedef std::reverse_iterator<const_iterator,T> const_reverse_iterator;
#endif
reverse_iterator rbegin() { return reverse_iterator(end()); }
const_reverse_iterator rbegin() const {
return const_reverse_iterator(end());
}
const_reverse_iterator crbegin() const {
return const_reverse_iterator(end());
}
reverse_iterator rend() { return reverse_iterator(begin()); }
const_reverse_iterator rend() const {
return const_reverse_iterator(begin());
}
const_reverse_iterator crend() const {
return const_reverse_iterator(begin());
}
// operator[]
reference operator[](size_type i)
{
BOOST_ASSERT_MSG( i < N, "out of range" );
return elems[i];
}
const_reference operator[](size_type i) const
{
BOOST_ASSERT_MSG( i < N, "out of range" );
return elems[i];
}
// at() with range check
reference at(size_type i) { rangecheck(i); return elems[i]; }
const_reference at(size_type i) const { rangecheck(i); return elems[i]; }
// front() and back()
reference front()
{
return elems[0];
}
const_reference front() const
{
return elems[0];
}
reference back()
{
return elems[N-1];
}
const_reference back() const
{
return elems[N-1];
}
// size is constant
static size_type size() { return N; }
static bool empty() { return false; }
static size_type max_size() { return N; }
enum { static_size = N };
// swap (note: linear complexity)
void swap (array<T,N>& y) {
for (size_type i = 0; i < N; ++i)
boost::swap(elems[i],y.elems[i]);
}
// direct access to data (read-only)
const T* data() const { return elems; }
T* data() { return elems; }
// use array as C array (direct read/write access to data)
T* c_array() { return elems; }
// assignment with type conversion
template <typename T2>
array<T,N>& operator= (const array<T2,N>& rhs) {
std::copy(rhs.begin(),rhs.end(), begin());
return *this;
}
// assign one value to all elements
void assign (const T& value) { fill ( value ); } // A synonym for fill
void fill (const T& value)
{
std::fill_n(begin(),size(),value);
}
// check range (may be private because it is static)
static void rangecheck (size_type i) {
if (i >= size()) {
std::out_of_range e("array<>: index out of range");
boost::throw_exception(e);
}
}
};
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
template< class T >
class array< T, 0 > {
public:
// type definitions
typedef T value_type;
typedef T* iterator;
typedef const T* const_iterator;
typedef T& reference;
typedef const T& const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
// iterator support
iterator begin() { return iterator( reinterpret_cast< T * >( this ) ); }
const_iterator begin() const { return const_iterator( reinterpret_cast< const T * >( this ) ); }
const_iterator cbegin() const { return const_iterator( reinterpret_cast< const T * >( this ) ); }
iterator end() { return begin(); }
const_iterator end() const { return begin(); }
const_iterator cend() const { return cbegin(); }
// reverse iterator support
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
#elif defined(_MSC_VER) && (_MSC_VER == 1300) && defined(BOOST_DINKUMWARE_STDLIB) && (BOOST_DINKUMWARE_STDLIB == 310)
// workaround for broken reverse_iterator in VC7
typedef std::reverse_iterator<std::_Ptrit<value_type, difference_type, iterator,
reference, iterator, reference> > reverse_iterator;
typedef std::reverse_iterator<std::_Ptrit<value_type, difference_type, const_iterator,
const_reference, iterator, reference> > const_reverse_iterator;
#elif defined(_RWSTD_NO_CLASS_PARTIAL_SPEC)
typedef std::reverse_iterator<iterator, std::random_access_iterator_tag,
value_type, reference, iterator, difference_type> reverse_iterator;
typedef std::reverse_iterator<const_iterator, std::random_access_iterator_tag,
value_type, const_reference, const_iterator, difference_type> const_reverse_iterator;
#else
// workaround for broken reverse_iterator implementations
typedef std::reverse_iterator<iterator,T> reverse_iterator;
typedef std::reverse_iterator<const_iterator,T> const_reverse_iterator;
#endif
reverse_iterator rbegin() { return reverse_iterator(end()); }
const_reverse_iterator rbegin() const {
return const_reverse_iterator(end());
}
const_reverse_iterator crbegin() const {
return const_reverse_iterator(end());
}
reverse_iterator rend() { return reverse_iterator(begin()); }
const_reverse_iterator rend() const {
return const_reverse_iterator(begin());
}
const_reverse_iterator crend() const {
return const_reverse_iterator(begin());
}
// operator[]
reference operator[](size_type /*i*/)
{
return failed_rangecheck();
}
const_reference operator[](size_type /*i*/) const
{
return failed_rangecheck();
}
// at() with range check
reference at(size_type /*i*/) { return failed_rangecheck(); }
const_reference at(size_type /*i*/) const { return failed_rangecheck(); }
// front() and back()
reference front()
{
return failed_rangecheck();
}
const_reference front() const
{
return failed_rangecheck();
}
reference back()
{
return failed_rangecheck();
}
const_reference back() const
{
return failed_rangecheck();
}
// size is constant
static size_type size() { return 0; }
static bool empty() { return true; }
static size_type max_size() { return 0; }
enum { static_size = 0 };
void swap (array<T,0>& /*y*/) {
}
// direct access to data (read-only)
const T* data() const { return 0; }
T* data() { return 0; }
// use array as C array (direct read/write access to data)
T* c_array() { return 0; }
// assignment with type conversion
template <typename T2>
array<T,0>& operator= (const array<T2,0>& ) {
return *this;
}
// assign one value to all elements
void assign (const T& value) { fill ( value ); }
void fill (const T& ) {}
// check range (may be private because it is static)
static reference failed_rangecheck () {
std::out_of_range e("attempt to access element of an empty array");
boost::throw_exception(e);
#if defined(BOOST_NO_EXCEPTIONS) || (!defined(BOOST_MSVC) && !defined(__PATHSCALE__))
//
// We need to return something here to keep
// some compilers happy: however we will never
// actually get here....
//
static T placeholder;
return placeholder;
#endif
}
};
#endif
// comparisons
template<class T, std::size_t N>
bool operator== (const array<T,N>& x, const array<T,N>& y) {
return std::equal(x.begin(), x.end(), y.begin());
}
template<class T, std::size_t N>
bool operator< (const array<T,N>& x, const array<T,N>& y) {
return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end());
}
template<class T, std::size_t N>
bool operator!= (const array<T,N>& x, const array<T,N>& y) {
return !(x==y);
}
template<class T, std::size_t N>
bool operator> (const array<T,N>& x, const array<T,N>& y) {
return y<x;
}
template<class T, std::size_t N>
bool operator<= (const array<T,N>& x, const array<T,N>& y) {
return !(y<x);
}
template<class T, std::size_t N>
bool operator>= (const array<T,N>& x, const array<T,N>& y) {
return !(x<y);
}
// global swap()
template<class T, std::size_t N>
inline void swap (array<T,N>& x, array<T,N>& y) {
x.swap(y);
}
#if defined(__SUNPRO_CC)
// Trac ticket #4757; the Sun Solaris compiler can't handle
// syntax like 'T(&get_c_array(boost::array<T,N>& arg))[N]'
//
// We can't just use this for all compilers, because the
// borland compilers can't handle this form.
namespace detail {
template <typename T, std::size_t N> struct c_array
{
typedef T type[N];
};
}
// Specific for boost::array: simply returns its elems data member.
template <typename T, std::size_t N>
typename detail::c_array<T,N>::type& get_c_array(boost::array<T,N>& arg)
{
return arg.elems;
}
// Specific for boost::array: simply returns its elems data member.
template <typename T, std::size_t N>
typename const detail::c_array<T,N>::type& get_c_array(const boost::array<T,N>& arg)
{
return arg.elems;
}
#else
// Specific for boost::array: simply returns its elems data member.
template <typename T, std::size_t N>
T(&get_c_array(boost::array<T,N>& arg))[N]
{
return arg.elems;
}
// Const version.
template <typename T, std::size_t N>
const T(&get_c_array(const boost::array<T,N>& arg))[N]
{
return arg.elems;
}
#endif
#if 0
// Overload for std::array, assuming that std::array will have
// explicit conversion functions as discussed at the WG21 meeting
// in Summit, March 2009.
template <typename T, std::size_t N>
T(&get_c_array(std::array<T,N>& arg))[N]
{
return static_cast<T(&)[N]>(arg);
}
// Const version.
template <typename T, std::size_t N>
const T(&get_c_array(const std::array<T,N>& arg))[N]
{
return static_cast<T(&)[N]>(arg);
}
#endif
template<class T, std::size_t N>
std::size_t hash_value(const array<T,N>& arr)
{
return boost::hash_range(arr.begin(), arr.end());
}
} /* namespace boost */
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
# pragma warning(pop)
#endif
#endif /*BOOST_ARRAY_HPP*/

View File

@@ -0,0 +1,85 @@
//
// boost/assert.hpp - BOOST_ASSERT(expr)
// BOOST_ASSERT_MSG(expr, msg)
// BOOST_VERIFY(expr)
// BOOST_VERIFY_MSG(expr, msg)
// BOOST_ASSERT_IS_VOID
//
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
// Copyright (c) 2007, 2014 Peter Dimov
// Copyright (c) Beman Dawes 2011
// Copyright (c) 2015 Ion Gaztanaga
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
// Note: There are no include guards. This is intentional.
//
// See http://www.boost.org/libs/assert/assert.html for documentation.
//
//
// Stop inspect complaining about use of 'assert':
//
// boostinspect:naassert_macro
//
//
// BOOST_ASSERT, BOOST_ASSERT_MSG, BOOST_ASSERT_IS_VOID
//
#undef BOOST_ASSERT
#undef BOOST_ASSERT_MSG
#undef BOOST_ASSERT_IS_VOID
#if defined(BOOST_DISABLE_ASSERTS) || ( defined(BOOST_ENABLE_ASSERT_DEBUG_HANDLER) && defined(NDEBUG) )
# define BOOST_ASSERT(expr) ((void)0)
# define BOOST_ASSERT_MSG(expr, msg) ((void)0)
# define BOOST_ASSERT_IS_VOID
#elif defined(BOOST_ENABLE_ASSERT_HANDLER) || ( defined(BOOST_ENABLE_ASSERT_DEBUG_HANDLER) && !defined(NDEBUG) )
#include <boost/config.hpp> // for BOOST_LIKELY
#include <boost/current_function.hpp>
namespace boost
{
void assertion_failed(char const * expr, char const * function, char const * file, long line); // user defined
void assertion_failed_msg(char const * expr, char const * msg, char const * function, char const * file, long line); // user defined
} // namespace boost
#define BOOST_ASSERT(expr) (BOOST_LIKELY(!!(expr))? ((void)0): ::boost::assertion_failed(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
#define BOOST_ASSERT_MSG(expr, msg) (BOOST_LIKELY(!!(expr))? ((void)0): ::boost::assertion_failed_msg(#expr, msg, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
#else
# include <assert.h> // .h to support old libraries w/o <cassert> - effect is the same
# define BOOST_ASSERT(expr) assert(expr)
# define BOOST_ASSERT_MSG(expr, msg) assert((expr)&&(msg))
#if defined(NDEBUG)
# define BOOST_ASSERT_IS_VOID
#endif
#endif
//
// BOOST_VERIFY, BOOST_VERIFY_MSG
//
#undef BOOST_VERIFY
#undef BOOST_VERIFY_MSG
#if defined(BOOST_DISABLE_ASSERTS) || ( !defined(BOOST_ENABLE_ASSERT_HANDLER) && defined(NDEBUG) )
# define BOOST_VERIFY(expr) ((void)(expr))
# define BOOST_VERIFY_MSG(expr, msg) ((void)(expr))
#else
# define BOOST_VERIFY(expr) BOOST_ASSERT(expr)
# define BOOST_VERIFY_MSG(expr, msg) BOOST_ASSERT_MSG(expr,msg)
#endif

View File

@@ -0,0 +1,18 @@
#ifndef BOOST_ATOMIC_HPP
#define BOOST_ATOMIC_HPP
// Copyright (c) 2011 Helge Bahmann
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// This header includes all Boost.Atomic public headers
#include <boost/atomic/atomic.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#endif

View File

@@ -0,0 +1,93 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2011 Helge Bahmann
* Copyright (c) 2013 Tim Blechmann
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/atomic.hpp
*
* This header contains definition of \c atomic template and \c atomic_flag.
*/
#ifndef BOOST_ATOMIC_ATOMIC_HPP_INCLUDED_
#define BOOST_ATOMIC_ATOMIC_HPP_INCLUDED_
#include <boost/atomic/capabilities.hpp>
#include <boost/atomic/fences.hpp>
#include <boost/atomic/atomic_flag.hpp>
#include <boost/atomic/detail/atomic_template.hpp>
#include <boost/atomic/detail/operations.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
using atomics::atomic;
using atomics::atomic_char;
using atomics::atomic_uchar;
using atomics::atomic_schar;
using atomics::atomic_uint8_t;
using atomics::atomic_int8_t;
using atomics::atomic_ushort;
using atomics::atomic_short;
using atomics::atomic_uint16_t;
using atomics::atomic_int16_t;
using atomics::atomic_uint;
using atomics::atomic_int;
using atomics::atomic_uint32_t;
using atomics::atomic_int32_t;
using atomics::atomic_ulong;
using atomics::atomic_long;
using atomics::atomic_uint64_t;
using atomics::atomic_int64_t;
#ifdef BOOST_HAS_LONG_LONG
using atomics::atomic_ullong;
using atomics::atomic_llong;
#endif
using atomics::atomic_address;
using atomics::atomic_bool;
using atomics::atomic_wchar_t;
#if !defined(BOOST_NO_CXX11_CHAR16_T)
using atomics::atomic_char16_t;
#endif
#if !defined(BOOST_NO_CXX11_CHAR32_T)
using atomics::atomic_char32_t;
#endif
using atomics::atomic_int_least8_t;
using atomics::atomic_uint_least8_t;
using atomics::atomic_int_least16_t;
using atomics::atomic_uint_least16_t;
using atomics::atomic_int_least32_t;
using atomics::atomic_uint_least32_t;
using atomics::atomic_int_least64_t;
using atomics::atomic_uint_least64_t;
using atomics::atomic_int_fast8_t;
using atomics::atomic_uint_fast8_t;
using atomics::atomic_int_fast16_t;
using atomics::atomic_uint_fast16_t;
using atomics::atomic_int_fast32_t;
using atomics::atomic_uint_fast32_t;
using atomics::atomic_int_fast64_t;
using atomics::atomic_uint_fast64_t;
using atomics::atomic_intmax_t;
using atomics::atomic_uintmax_t;
using atomics::atomic_size_t;
using atomics::atomic_ptrdiff_t;
#if defined(BOOST_HAS_INTPTR_T)
using atomics::atomic_intptr_t;
using atomics::atomic_uintptr_t;
#endif
} // namespace boost
#endif // BOOST_ATOMIC_ATOMIC_HPP_INCLUDED_

View File

@@ -0,0 +1,33 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2011 Helge Bahmann
* Copyright (c) 2013 Tim Blechmann
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/atomic_flag.hpp
*
* This header contains definition of \c atomic_flag.
*/
#ifndef BOOST_ATOMIC_ATOMIC_FLAG_HPP_INCLUDED_
#define BOOST_ATOMIC_ATOMIC_FLAG_HPP_INCLUDED_
#include <boost/atomic/capabilities.hpp>
#include <boost/atomic/detail/operations.hpp>
#include <boost/atomic/detail/atomic_flag.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
using atomics::atomic_flag;
} // namespace boost
#endif // BOOST_ATOMIC_ATOMIC_FLAG_HPP_INCLUDED_

View File

@@ -0,0 +1,161 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/capabilities.hpp
*
* This header defines feature capabilities macros.
*/
#ifndef BOOST_ATOMIC_CAPABILITIES_HPP_INCLUDED_
#define BOOST_ATOMIC_CAPABILITIES_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/platform.hpp>
#include <boost/atomic/detail/int_sizes.hpp>
#if !defined(BOOST_ATOMIC_EMULATED)
#include BOOST_ATOMIC_DETAIL_HEADER(boost/atomic/detail/caps_)
#endif
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#ifndef BOOST_ATOMIC_INT8_LOCK_FREE
#define BOOST_ATOMIC_INT8_LOCK_FREE 0
#endif
#ifndef BOOST_ATOMIC_INT16_LOCK_FREE
#define BOOST_ATOMIC_INT16_LOCK_FREE 0
#endif
#ifndef BOOST_ATOMIC_INT32_LOCK_FREE
#define BOOST_ATOMIC_INT32_LOCK_FREE 0
#endif
#ifndef BOOST_ATOMIC_INT64_LOCK_FREE
#define BOOST_ATOMIC_INT64_LOCK_FREE 0
#endif
#ifndef BOOST_ATOMIC_INT128_LOCK_FREE
#define BOOST_ATOMIC_INT128_LOCK_FREE 0
#endif
#ifndef BOOST_ATOMIC_CHAR_LOCK_FREE
#define BOOST_ATOMIC_CHAR_LOCK_FREE BOOST_ATOMIC_INT8_LOCK_FREE
#endif
#ifndef BOOST_ATOMIC_CHAR16_T_LOCK_FREE
#define BOOST_ATOMIC_CHAR16_T_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE
#endif
#ifndef BOOST_ATOMIC_CHAR32_T_LOCK_FREE
#define BOOST_ATOMIC_CHAR32_T_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
#endif
#ifndef BOOST_ATOMIC_WCHAR_T_LOCK_FREE
#if BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 1
#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE BOOST_ATOMIC_INT8_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 2
#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 4
#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 8
#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE
#else
#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE 0
#endif
#endif
#ifndef BOOST_ATOMIC_SHORT_LOCK_FREE
#if BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 1
#define BOOST_ATOMIC_SHORT_LOCK_FREE BOOST_ATOMIC_INT8_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 2
#define BOOST_ATOMIC_SHORT_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 4
#define BOOST_ATOMIC_SHORT_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 8
#define BOOST_ATOMIC_SHORT_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE
#else
#define BOOST_ATOMIC_SHORT_LOCK_FREE 0
#endif
#endif
#ifndef BOOST_ATOMIC_INT_LOCK_FREE
#if BOOST_ATOMIC_DETAIL_SIZEOF_INT == 1
#define BOOST_ATOMIC_INT_LOCK_FREE BOOST_ATOMIC_INT8_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_INT == 2
#define BOOST_ATOMIC_INT_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_INT == 4
#define BOOST_ATOMIC_INT_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_INT == 8
#define BOOST_ATOMIC_INT_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE
#else
#define BOOST_ATOMIC_INT_LOCK_FREE 0
#endif
#endif
#ifndef BOOST_ATOMIC_LONG_LOCK_FREE
#if BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 1
#define BOOST_ATOMIC_LONG_LOCK_FREE BOOST_ATOMIC_INT8_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 2
#define BOOST_ATOMIC_LONG_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 4
#define BOOST_ATOMIC_LONG_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 8
#define BOOST_ATOMIC_LONG_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE
#else
#define BOOST_ATOMIC_LONG_LOCK_FREE 0
#endif
#endif
#ifndef BOOST_ATOMIC_LLONG_LOCK_FREE
#if BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 1
#define BOOST_ATOMIC_LLONG_LOCK_FREE BOOST_ATOMIC_INT8_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 2
#define BOOST_ATOMIC_LLONG_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 4
#define BOOST_ATOMIC_LLONG_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 8
#define BOOST_ATOMIC_LLONG_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE
#else
#define BOOST_ATOMIC_LLONG_LOCK_FREE 0
#endif
#endif
#ifndef BOOST_ATOMIC_POINTER_LOCK_FREE
#if (BOOST_ATOMIC_DETAIL_SIZEOF_POINTER + 0) == 8
#define BOOST_ATOMIC_POINTER_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE
#elif (BOOST_ATOMIC_DETAIL_SIZEOF_POINTER + 0) == 4
#define BOOST_ATOMIC_POINTER_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
#else
#define BOOST_ATOMIC_POINTER_LOCK_FREE 0
#endif
#endif
#define BOOST_ATOMIC_ADDRESS_LOCK_FREE BOOST_ATOMIC_POINTER_LOCK_FREE
#ifndef BOOST_ATOMIC_BOOL_LOCK_FREE
// We store bools in 1-byte storage in all backends
#define BOOST_ATOMIC_BOOL_LOCK_FREE BOOST_ATOMIC_INT8_LOCK_FREE
#endif
#ifndef BOOST_ATOMIC_FLAG_LOCK_FREE
#define BOOST_ATOMIC_FLAG_LOCK_FREE BOOST_ATOMIC_BOOL_LOCK_FREE
#endif
#ifndef BOOST_ATOMIC_THREAD_FENCE
#define BOOST_ATOMIC_THREAD_FENCE 0
#endif
#ifndef BOOST_ATOMIC_SIGNAL_FENCE
#define BOOST_ATOMIC_SIGNAL_FENCE 0
#endif
#endif // BOOST_ATOMIC_CAPABILITIES_HPP_INCLUDED_

View File

@@ -0,0 +1,70 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/atomic_flag.hpp
*
* This header contains interface definition of \c atomic_flag.
*/
#ifndef BOOST_ATOMIC_DETAIL_ATOMIC_FLAG_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_ATOMIC_FLAG_HPP_INCLUDED_
#include <boost/assert.hpp>
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/operations_lockfree.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
/*
* IMPLEMENTATION NOTE: All interface functions MUST be declared with BOOST_FORCEINLINE,
* see comment for convert_memory_order_to_gcc in ops_gcc_atomic.hpp.
*/
namespace boost {
namespace atomics {
#if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX)
#define BOOST_ATOMIC_NO_ATOMIC_FLAG_INIT
#else
#define BOOST_ATOMIC_FLAG_INIT {}
#endif
struct atomic_flag
{
typedef atomics::detail::operations< 1u, false > operations;
typedef operations::storage_type storage_type;
operations::aligned_storage_type m_storage;
BOOST_FORCEINLINE BOOST_CONSTEXPR atomic_flag() BOOST_NOEXCEPT : m_storage(0)
{
}
BOOST_FORCEINLINE bool test_and_set(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
return operations::test_and_set(m_storage.value, order);
}
BOOST_FORCEINLINE void clear(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
BOOST_ASSERT(order != memory_order_acquire);
BOOST_ASSERT(order != memory_order_acq_rel);
operations::clear(m_storage.value, order);
}
BOOST_DELETED_FUNCTION(atomic_flag(atomic_flag const&))
BOOST_DELETED_FUNCTION(atomic_flag& operator= (atomic_flag const&))
};
} // namespace atomics
} // namespace boost
#endif // BOOST_ATOMIC_DETAIL_ATOMIC_FLAG_HPP_INCLUDED_

View File

@@ -0,0 +1,774 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2011 Helge Bahmann
* Copyright (c) 2013 Tim Blechmann
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/atomic_template.hpp
*
* This header contains interface definition of \c atomic template.
*/
#ifndef BOOST_ATOMIC_DETAIL_ATOMIC_TEMPLATE_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_ATOMIC_TEMPLATE_HPP_INCLUDED_
#include <cstddef>
#include <boost/cstdint.hpp>
#include <boost/assert.hpp>
#include <boost/type_traits/is_signed.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/bitwise_cast.hpp>
#include <boost/atomic/detail/operations_fwd.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if defined(BOOST_MSVC)
#pragma warning(push)
// 'boost::atomics::atomic<T>' : multiple assignment operators specified
#pragma warning(disable: 4522)
#endif
/*
* IMPLEMENTATION NOTE: All interface functions MUST be declared with BOOST_FORCEINLINE,
* see comment for convert_memory_order_to_gcc in ops_gcc_atomic.hpp.
*/
namespace boost {
namespace atomics {
namespace detail {
BOOST_FORCEINLINE BOOST_CONSTEXPR memory_order deduce_failure_order(memory_order order) BOOST_NOEXCEPT
{
return order == memory_order_acq_rel ? memory_order_acquire : (order == memory_order_release ? memory_order_relaxed : order);
}
BOOST_FORCEINLINE BOOST_CONSTEXPR bool cas_failure_order_must_not_be_stronger_than_success_order(memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
// 15 == (memory_order_seq_cst | memory_order_consume), see memory_order.hpp
// Given the enum values we can test the strength of memory order requirements with this single condition.
return (failure_order & 15u) <= (success_order & 15u);
}
template< typename T, bool IsInt = boost::is_integral< T >::value >
struct classify
{
typedef void type;
};
template< typename T >
struct classify< T, true > { typedef int type; };
template< typename T >
struct classify< T*, false > { typedef void* type; };
template< typename T, typename Kind >
class base_atomic;
//! Implementation for integers
template< typename T >
class base_atomic< T, int >
{
private:
typedef T value_type;
typedef T difference_type;
typedef atomics::detail::operations< storage_size_of< value_type >::value, boost::is_signed< T >::value > operations;
protected:
typedef value_type value_arg_type;
public:
typedef typename operations::storage_type storage_type;
protected:
typename operations::aligned_storage_type m_storage;
public:
BOOST_DEFAULTED_FUNCTION(base_atomic(), {})
BOOST_CONSTEXPR explicit base_atomic(value_type v) BOOST_NOEXCEPT : m_storage(v) {}
BOOST_FORCEINLINE void store(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
BOOST_ASSERT(order != memory_order_consume);
BOOST_ASSERT(order != memory_order_acquire);
BOOST_ASSERT(order != memory_order_acq_rel);
operations::store(m_storage.value, static_cast< storage_type >(v), order);
}
BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT
{
BOOST_ASSERT(order != memory_order_release);
BOOST_ASSERT(order != memory_order_acq_rel);
return static_cast< value_type >(operations::load(m_storage.value, order));
}
BOOST_FORCEINLINE value_type fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
return static_cast< value_type >(operations::fetch_add(m_storage.value, static_cast< storage_type >(v), order));
}
BOOST_FORCEINLINE value_type fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
return static_cast< value_type >(operations::fetch_sub(m_storage.value, static_cast< storage_type >(v), order));
}
BOOST_FORCEINLINE value_type exchange(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
return static_cast< value_type >(operations::exchange(m_storage.value, static_cast< storage_type >(v), order));
}
BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT
{
BOOST_ASSERT(failure_order != memory_order_release);
BOOST_ASSERT(failure_order != memory_order_acq_rel);
BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
storage_type old_value = static_cast< storage_type >(expected);
const bool res = operations::compare_exchange_strong(m_storage.value, old_value, static_cast< storage_type >(desired), success_order, failure_order);
expected = static_cast< value_type >(old_value);
return res;
}
BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order));
}
BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT
{
BOOST_ASSERT(failure_order != memory_order_release);
BOOST_ASSERT(failure_order != memory_order_acq_rel);
BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
storage_type old_value = static_cast< storage_type >(expected);
const bool res = operations::compare_exchange_weak(m_storage.value, old_value, static_cast< storage_type >(desired), success_order, failure_order);
expected = static_cast< value_type >(old_value);
return res;
}
BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order));
}
BOOST_FORCEINLINE value_type fetch_and(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
return static_cast< value_type >(operations::fetch_and(m_storage.value, static_cast< storage_type >(v), order));
}
BOOST_FORCEINLINE value_type fetch_or(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
return static_cast< value_type >(operations::fetch_or(m_storage.value, static_cast< storage_type >(v), order));
}
BOOST_FORCEINLINE value_type fetch_xor(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
return static_cast< value_type >(operations::fetch_xor(m_storage.value, static_cast< storage_type >(v), order));
}
BOOST_FORCEINLINE bool is_lock_free() const volatile BOOST_NOEXCEPT
{
return operations::is_lock_free(m_storage.value);
}
BOOST_FORCEINLINE value_type operator++(int) volatile BOOST_NOEXCEPT
{
return fetch_add(1);
}
BOOST_FORCEINLINE value_type operator++() volatile BOOST_NOEXCEPT
{
return fetch_add(1) + 1;
}
BOOST_FORCEINLINE value_type operator--(int) volatile BOOST_NOEXCEPT
{
return fetch_sub(1);
}
BOOST_FORCEINLINE value_type operator--() volatile BOOST_NOEXCEPT
{
return fetch_sub(1) - 1;
}
BOOST_FORCEINLINE value_type operator+=(difference_type v) volatile BOOST_NOEXCEPT
{
return fetch_add(v) + v;
}
BOOST_FORCEINLINE value_type operator-=(difference_type v) volatile BOOST_NOEXCEPT
{
return fetch_sub(v) - v;
}
BOOST_FORCEINLINE value_type operator&=(value_type v) volatile BOOST_NOEXCEPT
{
return fetch_and(v) & v;
}
BOOST_FORCEINLINE value_type operator|=(value_type v) volatile BOOST_NOEXCEPT
{
return fetch_or(v) | v;
}
BOOST_FORCEINLINE value_type operator^=(value_type v) volatile BOOST_NOEXCEPT
{
return fetch_xor(v) ^ v;
}
BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&))
BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&))
};
//! Implementation for bool
template< >
class base_atomic< bool, int >
{
private:
typedef bool value_type;
typedef atomics::detail::operations< 1u, false > operations;
protected:
typedef value_type value_arg_type;
public:
typedef operations::storage_type storage_type;
protected:
operations::aligned_storage_type m_storage;
public:
BOOST_DEFAULTED_FUNCTION(base_atomic(), {})
BOOST_CONSTEXPR explicit base_atomic(value_type v) BOOST_NOEXCEPT : m_storage(v) {}
BOOST_FORCEINLINE void store(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
BOOST_ASSERT(order != memory_order_consume);
BOOST_ASSERT(order != memory_order_acquire);
BOOST_ASSERT(order != memory_order_acq_rel);
operations::store(m_storage.value, static_cast< storage_type >(v), order);
}
BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT
{
BOOST_ASSERT(order != memory_order_release);
BOOST_ASSERT(order != memory_order_acq_rel);
return !!operations::load(m_storage.value, order);
}
BOOST_FORCEINLINE value_type exchange(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
return !!operations::exchange(m_storage.value, static_cast< storage_type >(v), order);
}
BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT
{
BOOST_ASSERT(failure_order != memory_order_release);
BOOST_ASSERT(failure_order != memory_order_acq_rel);
BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
storage_type old_value = static_cast< storage_type >(expected);
const bool res = operations::compare_exchange_strong(m_storage.value, old_value, static_cast< storage_type >(desired), success_order, failure_order);
expected = !!old_value;
return res;
}
BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order));
}
BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT
{
BOOST_ASSERT(failure_order != memory_order_release);
BOOST_ASSERT(failure_order != memory_order_acq_rel);
BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
storage_type old_value = static_cast< storage_type >(expected);
const bool res = operations::compare_exchange_weak(m_storage.value, old_value, static_cast< storage_type >(desired), success_order, failure_order);
expected = !!old_value;
return res;
}
BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order));
}
BOOST_FORCEINLINE bool is_lock_free() const volatile BOOST_NOEXCEPT
{
return operations::is_lock_free(m_storage.value);
}
BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&))
BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&))
};
//! Implementation for user-defined types, such as structs and enums
template< typename T >
class base_atomic< T, void >
{
private:
typedef T value_type;
typedef atomics::detail::operations< storage_size_of< value_type >::value, false > operations;
protected:
typedef value_type const& value_arg_type;
public:
typedef typename operations::storage_type storage_type;
protected:
typename operations::aligned_storage_type m_storage;
public:
BOOST_FORCEINLINE explicit base_atomic(value_type const& v = value_type()) BOOST_NOEXCEPT : m_storage(atomics::detail::bitwise_cast< storage_type >(v))
{
}
BOOST_FORCEINLINE void store(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
BOOST_ASSERT(order != memory_order_consume);
BOOST_ASSERT(order != memory_order_acquire);
BOOST_ASSERT(order != memory_order_acq_rel);
operations::store(m_storage.value, atomics::detail::bitwise_cast< storage_type >(v), order);
}
BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT
{
BOOST_ASSERT(order != memory_order_release);
BOOST_ASSERT(order != memory_order_acq_rel);
return atomics::detail::bitwise_cast< value_type >(operations::load(m_storage.value, order));
}
BOOST_FORCEINLINE value_type exchange(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
return atomics::detail::bitwise_cast< value_type >(operations::exchange(m_storage.value, atomics::detail::bitwise_cast< storage_type >(v), order));
}
BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT
{
BOOST_ASSERT(failure_order != memory_order_release);
BOOST_ASSERT(failure_order != memory_order_acq_rel);
BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected);
const bool res = operations::compare_exchange_strong(m_storage.value, old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order);
expected = atomics::detail::bitwise_cast< value_type >(old_value);
return res;
}
BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order));
}
BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT
{
BOOST_ASSERT(failure_order != memory_order_release);
BOOST_ASSERT(failure_order != memory_order_acq_rel);
BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected);
const bool res = operations::compare_exchange_weak(m_storage.value, old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order);
expected = atomics::detail::bitwise_cast< value_type >(old_value);
return res;
}
BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order));
}
BOOST_FORCEINLINE bool is_lock_free() const volatile BOOST_NOEXCEPT
{
return operations::is_lock_free(m_storage.value);
}
BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&))
BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&))
};
//! Implementation for pointers
template< typename T >
class base_atomic< T*, void* >
{
private:
typedef T* value_type;
typedef std::ptrdiff_t difference_type;
typedef atomics::detail::operations< storage_size_of< value_type >::value, false > operations;
protected:
typedef value_type value_arg_type;
public:
typedef typename operations::storage_type storage_type;
protected:
typename operations::aligned_storage_type m_storage;
public:
BOOST_DEFAULTED_FUNCTION(base_atomic(), {})
BOOST_FORCEINLINE explicit base_atomic(value_type const& v) BOOST_NOEXCEPT : m_storage(atomics::detail::bitwise_cast< storage_type >(v))
{
}
BOOST_FORCEINLINE void store(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
BOOST_ASSERT(order != memory_order_consume);
BOOST_ASSERT(order != memory_order_acquire);
BOOST_ASSERT(order != memory_order_acq_rel);
operations::store(m_storage.value, atomics::detail::bitwise_cast< storage_type >(v), order);
}
BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT
{
BOOST_ASSERT(order != memory_order_release);
BOOST_ASSERT(order != memory_order_acq_rel);
return atomics::detail::bitwise_cast< value_type >(operations::load(m_storage.value, order));
}
BOOST_FORCEINLINE value_type fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
return atomics::detail::bitwise_cast< value_type >(operations::fetch_add(m_storage.value, static_cast< storage_type >(v * sizeof(T)), order));
}
BOOST_FORCEINLINE value_type fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
return atomics::detail::bitwise_cast< value_type >(operations::fetch_sub(m_storage.value, static_cast< storage_type >(v * sizeof(T)), order));
}
BOOST_FORCEINLINE value_type exchange(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
return atomics::detail::bitwise_cast< value_type >(operations::exchange(m_storage.value, atomics::detail::bitwise_cast< storage_type >(v), order));
}
BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT
{
BOOST_ASSERT(failure_order != memory_order_release);
BOOST_ASSERT(failure_order != memory_order_acq_rel);
BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected);
const bool res = operations::compare_exchange_strong(m_storage.value, old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order);
expected = atomics::detail::bitwise_cast< value_type >(old_value);
return res;
}
BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order));
}
BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT
{
BOOST_ASSERT(failure_order != memory_order_release);
BOOST_ASSERT(failure_order != memory_order_acq_rel);
BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected);
const bool res = operations::compare_exchange_weak(m_storage.value, old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order);
expected = atomics::detail::bitwise_cast< value_type >(old_value);
return res;
}
BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order));
}
BOOST_FORCEINLINE bool is_lock_free() const volatile BOOST_NOEXCEPT
{
return operations::is_lock_free(m_storage.value);
}
BOOST_FORCEINLINE value_type operator++(int) volatile BOOST_NOEXCEPT
{
return fetch_add(1);
}
BOOST_FORCEINLINE value_type operator++() volatile BOOST_NOEXCEPT
{
return fetch_add(1) + 1;
}
BOOST_FORCEINLINE value_type operator--(int) volatile BOOST_NOEXCEPT
{
return fetch_sub(1);
}
BOOST_FORCEINLINE value_type operator--() volatile BOOST_NOEXCEPT
{
return fetch_sub(1) - 1;
}
BOOST_FORCEINLINE value_type operator+=(difference_type v) volatile BOOST_NOEXCEPT
{
return fetch_add(v) + v;
}
BOOST_FORCEINLINE value_type operator-=(difference_type v) volatile BOOST_NOEXCEPT
{
return fetch_sub(v) - v;
}
BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&))
BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&))
};
//! Implementation for void pointers
template< >
class base_atomic< void*, void* >
{
private:
typedef void* value_type;
typedef std::ptrdiff_t difference_type;
typedef atomics::detail::operations< storage_size_of< value_type >::value, false > operations;
protected:
typedef value_type value_arg_type;
public:
typedef operations::storage_type storage_type;
protected:
operations::aligned_storage_type m_storage;
public:
BOOST_DEFAULTED_FUNCTION(base_atomic(), {})
BOOST_FORCEINLINE explicit base_atomic(value_type const& v) BOOST_NOEXCEPT : m_storage(atomics::detail::bitwise_cast< storage_type >(v))
{
}
BOOST_FORCEINLINE void store(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
BOOST_ASSERT(order != memory_order_consume);
BOOST_ASSERT(order != memory_order_acquire);
BOOST_ASSERT(order != memory_order_acq_rel);
operations::store(m_storage.value, atomics::detail::bitwise_cast< storage_type >(v), order);
}
BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT
{
BOOST_ASSERT(order != memory_order_release);
BOOST_ASSERT(order != memory_order_acq_rel);
return atomics::detail::bitwise_cast< value_type >(operations::load(m_storage.value, order));
}
BOOST_FORCEINLINE value_type fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
return atomics::detail::bitwise_cast< value_type >(operations::fetch_add(m_storage.value, static_cast< storage_type >(v), order));
}
BOOST_FORCEINLINE value_type fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
return atomics::detail::bitwise_cast< value_type >(operations::fetch_sub(m_storage.value, static_cast< storage_type >(v), order));
}
BOOST_FORCEINLINE value_type exchange(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
return atomics::detail::bitwise_cast< value_type >(operations::exchange(m_storage.value, atomics::detail::bitwise_cast< storage_type >(v), order));
}
BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT
{
BOOST_ASSERT(failure_order != memory_order_release);
BOOST_ASSERT(failure_order != memory_order_acq_rel);
BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected);
const bool res = operations::compare_exchange_strong(m_storage.value, old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order);
expected = atomics::detail::bitwise_cast< value_type >(old_value);
return res;
}
BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order));
}
BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT
{
BOOST_ASSERT(failure_order != memory_order_release);
BOOST_ASSERT(failure_order != memory_order_acq_rel);
BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected);
const bool res = operations::compare_exchange_weak(m_storage.value, old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order);
expected = atomics::detail::bitwise_cast< value_type >(old_value);
return res;
}
BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order));
}
BOOST_FORCEINLINE bool is_lock_free() const volatile BOOST_NOEXCEPT
{
return operations::is_lock_free(m_storage.value);
}
BOOST_FORCEINLINE value_type operator++(int) volatile BOOST_NOEXCEPT
{
return fetch_add(1);
}
BOOST_FORCEINLINE value_type operator++() volatile BOOST_NOEXCEPT
{
return (char*)fetch_add(1) + 1;
}
BOOST_FORCEINLINE value_type operator--(int) volatile BOOST_NOEXCEPT
{
return fetch_sub(1);
}
BOOST_FORCEINLINE value_type operator--() volatile BOOST_NOEXCEPT
{
return (char*)fetch_sub(1) - 1;
}
BOOST_FORCEINLINE value_type operator+=(difference_type v) volatile BOOST_NOEXCEPT
{
return (char*)fetch_add(v) + v;
}
BOOST_FORCEINLINE value_type operator-=(difference_type v) volatile BOOST_NOEXCEPT
{
return (char*)fetch_sub(v) - v;
}
BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&))
BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&))
};
} // namespace detail
template< typename T >
class atomic :
public atomics::detail::base_atomic< T, typename atomics::detail::classify< T >::type >
{
private:
typedef T value_type;
typedef atomics::detail::base_atomic< T, typename atomics::detail::classify< T >::type > base_type;
typedef typename base_type::value_arg_type value_arg_type;
public:
typedef typename base_type::storage_type storage_type;
public:
BOOST_DEFAULTED_FUNCTION(atomic(), BOOST_NOEXCEPT {})
// NOTE: The constructor is made explicit because gcc 4.7 complains that
// operator=(value_arg_type) is considered ambiguous with operator=(atomic const&)
// in assignment expressions, even though conversion to atomic<> is less preferred
// than conversion to value_arg_type.
BOOST_FORCEINLINE explicit BOOST_CONSTEXPR atomic(value_arg_type v) BOOST_NOEXCEPT : base_type(v) {}
BOOST_FORCEINLINE value_type operator= (value_arg_type v) volatile BOOST_NOEXCEPT
{
this->store(v);
return v;
}
BOOST_FORCEINLINE operator value_type() volatile const BOOST_NOEXCEPT
{
return this->load();
}
BOOST_FORCEINLINE storage_type& storage() BOOST_NOEXCEPT { return this->m_storage.value; }
BOOST_FORCEINLINE storage_type volatile& storage() volatile BOOST_NOEXCEPT { return this->m_storage.value; }
BOOST_FORCEINLINE storage_type const& storage() const BOOST_NOEXCEPT { return this->m_storage.value; }
BOOST_FORCEINLINE storage_type const volatile& storage() const volatile BOOST_NOEXCEPT { return this->m_storage.value; }
BOOST_DELETED_FUNCTION(atomic(atomic const&))
BOOST_DELETED_FUNCTION(atomic& operator= (atomic const&))
BOOST_DELETED_FUNCTION(atomic& operator= (atomic const&) volatile)
};
typedef atomic< char > atomic_char;
typedef atomic< unsigned char > atomic_uchar;
typedef atomic< signed char > atomic_schar;
typedef atomic< uint8_t > atomic_uint8_t;
typedef atomic< int8_t > atomic_int8_t;
typedef atomic< unsigned short > atomic_ushort;
typedef atomic< short > atomic_short;
typedef atomic< uint16_t > atomic_uint16_t;
typedef atomic< int16_t > atomic_int16_t;
typedef atomic< unsigned int > atomic_uint;
typedef atomic< int > atomic_int;
typedef atomic< uint32_t > atomic_uint32_t;
typedef atomic< int32_t > atomic_int32_t;
typedef atomic< unsigned long > atomic_ulong;
typedef atomic< long > atomic_long;
typedef atomic< uint64_t > atomic_uint64_t;
typedef atomic< int64_t > atomic_int64_t;
#ifdef BOOST_HAS_LONG_LONG
typedef atomic< boost::ulong_long_type > atomic_ullong;
typedef atomic< boost::long_long_type > atomic_llong;
#endif
typedef atomic< void* > atomic_address;
typedef atomic< bool > atomic_bool;
typedef atomic< wchar_t > atomic_wchar_t;
#if !defined(BOOST_NO_CXX11_CHAR16_T)
typedef atomic< char16_t > atomic_char16_t;
#endif
#if !defined(BOOST_NO_CXX11_CHAR32_T)
typedef atomic< char32_t > atomic_char32_t;
#endif
typedef atomic< int_least8_t > atomic_int_least8_t;
typedef atomic< uint_least8_t > atomic_uint_least8_t;
typedef atomic< int_least16_t > atomic_int_least16_t;
typedef atomic< uint_least16_t > atomic_uint_least16_t;
typedef atomic< int_least32_t > atomic_int_least32_t;
typedef atomic< uint_least32_t > atomic_uint_least32_t;
typedef atomic< int_least64_t > atomic_int_least64_t;
typedef atomic< uint_least64_t > atomic_uint_least64_t;
typedef atomic< int_fast8_t > atomic_int_fast8_t;
typedef atomic< uint_fast8_t > atomic_uint_fast8_t;
typedef atomic< int_fast16_t > atomic_int_fast16_t;
typedef atomic< uint_fast16_t > atomic_uint_fast16_t;
typedef atomic< int_fast32_t > atomic_int_fast32_t;
typedef atomic< uint_fast32_t > atomic_uint_fast32_t;
typedef atomic< int_fast64_t > atomic_int_fast64_t;
typedef atomic< uint_fast64_t > atomic_uint_fast64_t;
typedef atomic< intmax_t > atomic_intmax_t;
typedef atomic< uintmax_t > atomic_uintmax_t;
typedef atomic< std::size_t > atomic_size_t;
typedef atomic< std::ptrdiff_t > atomic_ptrdiff_t;
#if defined(BOOST_HAS_INTPTR_T)
typedef atomic< intptr_t > atomic_intptr_t;
typedef atomic< uintptr_t > atomic_uintptr_t;
#endif
} // namespace atomics
} // namespace boost
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
#endif // BOOST_ATOMIC_DETAIL_ATOMIC_TEMPLATE_HPP_INCLUDED_

View File

@@ -0,0 +1,53 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2009 Helge Bahmann
* Copyright (c) 2012 Tim Blechmann
* Copyright (c) 2013 - 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/bitwise_cast.hpp
*
* This header defines \c bitwise_cast used to convert between storage and value types
*/
#ifndef BOOST_ATOMIC_DETAIL_BITWISE_CAST_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_BITWISE_CAST_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#if !defined(BOOST_ATOMIC_DETAIL_HAS_BUILTIN_MEMCPY)
#include <cstring>
#endif
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
template< typename To, typename From >
BOOST_FORCEINLINE To bitwise_cast(From const& from) BOOST_NOEXCEPT
{
struct
{
To to;
}
value = {};
BOOST_ATOMIC_DETAIL_MEMCPY
(
&reinterpret_cast< char& >(value.to),
&reinterpret_cast< const char& >(from),
(sizeof(From) < sizeof(To) ? sizeof(From) : sizeof(To))
);
return value.to;
}
} // namespace detail
} // namespace atomics
} // namespace boost
#endif // BOOST_ATOMIC_DETAIL_BITWISE_CAST_HPP_INCLUDED_

View File

@@ -0,0 +1,34 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2009 Helge Bahmann
* Copyright (c) 2013 Tim Blechmann
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/caps_gcc_alpha.hpp
*
* This header defines feature capabilities macros
*/
#ifndef BOOST_ATOMIC_DETAIL_CAPS_GCC_ALPHA_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CAPS_GCC_ALPHA_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#define BOOST_ATOMIC_INT8_LOCK_FREE 2
#define BOOST_ATOMIC_INT16_LOCK_FREE 2
#define BOOST_ATOMIC_INT32_LOCK_FREE 2
#define BOOST_ATOMIC_INT64_LOCK_FREE 2
#define BOOST_ATOMIC_POINTER_LOCK_FREE 2
#define BOOST_ATOMIC_THREAD_FENCE 2
#define BOOST_ATOMIC_SIGNAL_FENCE 2
#endif // BOOST_ATOMIC_DETAIL_CAPS_GCC_ALPHA_HPP_INCLUDED_

View File

@@ -0,0 +1,56 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2009 Helge Bahmann
* Copyright (c) 2009 Phil Endecott
* Copyright (c) 2013 Tim Blechmann
* ARM Code by Phil Endecott, based on other architectures.
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/caps_gcc_arm.hpp
*
* This header defines feature capabilities macros
*/
#ifndef BOOST_ATOMIC_DETAIL_CAPS_GCC_ARM_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CAPS_GCC_ARM_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if !(defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6ZK__))
// ARMv7 and later have dmb instruction
#define BOOST_ATOMIC_DETAIL_ARM_HAS_DMB 1
#endif
#if !(defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6Z__))
// ARMv6k and ARMv7 have 8 and 16 ldrex/strex variants
#define BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXB_STREXB 1
#define BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXH_STREXH 1
#if !(((defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6ZK__)) && defined(__thumb__)) || defined(__ARM_ARCH_7M__))
// ARMv6k and ARMv7 except ARMv7-M have 64-bit ldrex/strex variants.
// Unfortunately, GCC (at least 4.7.3 on Ubuntu) does not allocate register pairs properly when targeting ARMv6k Thumb,
// which is required for ldrexd/strexd instructions, so we disable 64-bit support. When targeting ARMv6k ARM
// or ARMv7 (both ARM and Thumb 2) it works as expected.
#define BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXD_STREXD 1
#endif
#endif
#define BOOST_ATOMIC_INT8_LOCK_FREE 2
#define BOOST_ATOMIC_INT16_LOCK_FREE 2
#define BOOST_ATOMIC_INT32_LOCK_FREE 2
#if defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXD_STREXD)
#define BOOST_ATOMIC_INT64_LOCK_FREE 2
#endif
#define BOOST_ATOMIC_POINTER_LOCK_FREE 2
#define BOOST_ATOMIC_THREAD_FENCE 2
#define BOOST_ATOMIC_SIGNAL_FENCE 2
#endif // BOOST_ATOMIC_DETAIL_CAPS_GCC_ARM_HPP_INCLUDED_

View File

@@ -0,0 +1,134 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/caps_gcc_atomic.hpp
*
* This header defines feature capabilities macros
*/
#ifndef BOOST_ATOMIC_DETAIL_CAPS_GCC_ATOMIC_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CAPS_GCC_ATOMIC_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/int_sizes.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if defined(__i386__) && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
#define BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B 1
#endif
#if defined(__x86_64__) && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16)
#define BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B 1
#endif
#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B) && (defined(BOOST_HAS_INT128) || !defined(BOOST_NO_ALIGNMENT))
#define BOOST_ATOMIC_INT128_LOCK_FREE 2
#else
#define BOOST_ATOMIC_INT128_LOCK_FREE 0
#endif
#if __GCC_ATOMIC_LLONG_LOCK_FREE == 2
#define BOOST_ATOMIC_LLONG_LOCK_FREE 2
#else
#define BOOST_ATOMIC_LLONG_LOCK_FREE BOOST_ATOMIC_INT128_LOCK_FREE
#endif
#if __GCC_ATOMIC_LONG_LOCK_FREE == 2
#define BOOST_ATOMIC_LONG_LOCK_FREE 2
#else
#define BOOST_ATOMIC_LONG_LOCK_FREE BOOST_ATOMIC_LLONG_LOCK_FREE
#endif
#if __GCC_ATOMIC_INT_LOCK_FREE == 2
#define BOOST_ATOMIC_INT_LOCK_FREE 2
#else
#define BOOST_ATOMIC_INT_LOCK_FREE BOOST_ATOMIC_LONG_LOCK_FREE
#endif
#if __GCC_ATOMIC_SHORT_LOCK_FREE == 2
#define BOOST_ATOMIC_SHORT_LOCK_FREE 2
#else
#define BOOST_ATOMIC_SHORT_LOCK_FREE BOOST_ATOMIC_INT_LOCK_FREE
#endif
#if __GCC_ATOMIC_CHAR_LOCK_FREE == 2
#define BOOST_ATOMIC_CHAR_LOCK_FREE 2
#else
#define BOOST_ATOMIC_CHAR_LOCK_FREE BOOST_ATOMIC_SHORT_LOCK_FREE
#endif
#if __GCC_ATOMIC_POINTER_LOCK_FREE == 2
#define BOOST_ATOMIC_POINTER_LOCK_FREE 2
#else
#define BOOST_ATOMIC_POINTER_LOCK_FREE 0
#endif
#define BOOST_ATOMIC_INT8_LOCK_FREE BOOST_ATOMIC_CHAR_LOCK_FREE
#if BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 2
#define BOOST_ATOMIC_INT16_LOCK_FREE BOOST_ATOMIC_SHORT_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_INT == 2
#define BOOST_ATOMIC_INT16_LOCK_FREE BOOST_ATOMIC_INT_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 2
#define BOOST_ATOMIC_INT16_LOCK_FREE BOOST_ATOMIC_LONG_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 2
#define BOOST_ATOMIC_INT16_LOCK_FREE BOOST_ATOMIC_LLONG_LOCK_FREE
#else
#define BOOST_ATOMIC_INT16_LOCK_FREE 0
#endif
#if BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 4
#define BOOST_ATOMIC_INT32_LOCK_FREE BOOST_ATOMIC_SHORT_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_INT == 4
#define BOOST_ATOMIC_INT32_LOCK_FREE BOOST_ATOMIC_INT_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 4
#define BOOST_ATOMIC_INT32_LOCK_FREE BOOST_ATOMIC_LONG_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 4
#define BOOST_ATOMIC_INT32_LOCK_FREE BOOST_ATOMIC_LLONG_LOCK_FREE
#else
#define BOOST_ATOMIC_INT32_LOCK_FREE 0
#endif
#if BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 8
#define BOOST_ATOMIC_INT64_LOCK_FREE BOOST_ATOMIC_SHORT_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_INT == 8
#define BOOST_ATOMIC_INT64_LOCK_FREE BOOST_ATOMIC_INT_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 8
#define BOOST_ATOMIC_INT64_LOCK_FREE BOOST_ATOMIC_LONG_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 8
#define BOOST_ATOMIC_INT64_LOCK_FREE BOOST_ATOMIC_LLONG_LOCK_FREE
#else
#define BOOST_ATOMIC_INT64_LOCK_FREE 0
#endif
#if __GCC_ATOMIC_WCHAR_T_LOCK_FREE == 2
#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE 2
#elif BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 8
#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 4
#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 2
#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 1
#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE BOOST_ATOMIC_INT8_LOCK_FREE
#else
#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE 0
#endif
#define BOOST_ATOMIC_CHAR32_T_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
#define BOOST_ATOMIC_CHAR16_T_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE
#define BOOST_ATOMIC_THREAD_FENCE 2
#define BOOST_ATOMIC_SIGNAL_FENCE 2
#endif // BOOST_ATOMIC_DETAIL_CAPS_GCC_ATOMIC_HPP_INCLUDED_

View File

@@ -0,0 +1,36 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2009 Helge Bahmann
* Copyright (c) 2013 Tim Blechmann
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/caps_gcc_ppc.hpp
*
* This header defines feature capabilities macros
*/
#ifndef BOOST_ATOMIC_DETAIL_CAPS_GCC_PPC_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CAPS_GCC_PPC_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#define BOOST_ATOMIC_INT8_LOCK_FREE 2
#define BOOST_ATOMIC_INT16_LOCK_FREE 2
#define BOOST_ATOMIC_INT32_LOCK_FREE 2
#if defined(__powerpc64__) || defined(__PPC64__)
#define BOOST_ATOMIC_INT64_LOCK_FREE 2
#endif
#define BOOST_ATOMIC_POINTER_LOCK_FREE 2
#define BOOST_ATOMIC_THREAD_FENCE 2
#define BOOST_ATOMIC_SIGNAL_FENCE 2
#endif // BOOST_ATOMIC_DETAIL_CAPS_GCC_PPC_HPP_INCLUDED_

View File

@@ -0,0 +1,34 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2010 Helge Bahmann
* Copyright (c) 2013 Tim Blechmann
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/caps_gcc_sparc.hpp
*
* This header defines feature capabilities macros
*/
#ifndef BOOST_ATOMIC_DETAIL_CAPS_GCC_SPARC_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CAPS_GCC_SPARC_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#define BOOST_ATOMIC_INT8_LOCK_FREE 2
#define BOOST_ATOMIC_INT16_LOCK_FREE 2
#define BOOST_ATOMIC_INT32_LOCK_FREE 2
#define BOOST_ATOMIC_INT64_LOCK_FREE 2
#define BOOST_ATOMIC_POINTER_LOCK_FREE 2
#define BOOST_ATOMIC_THREAD_FENCE 2
#define BOOST_ATOMIC_SIGNAL_FENCE 2
#endif // BOOST_ATOMIC_DETAIL_CAPS_GCC_SPARC_HPP_INCLUDED_

View File

@@ -0,0 +1,62 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2011 Helge Bahmann
* Copyright (c) 2013 Tim Blechmann
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/caps_gcc_sync.hpp
*
* This header defines feature capabilities macros
*/
#ifndef BOOST_ATOMIC_DETAIL_CAPS_GCC_SYNC_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CAPS_GCC_SYNC_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if defined(__i386__) && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
#define BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B 1
#endif
#if defined(__x86_64__) && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16)
#define BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B 1
#endif
#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1)\
|| defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2)\
|| defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)\
|| defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)\
|| defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16)
#define BOOST_ATOMIC_INT8_LOCK_FREE 2
#endif
#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2)\
|| defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)\
|| defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)\
|| defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16)
#define BOOST_ATOMIC_INT16_LOCK_FREE 2
#endif
#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)\
|| defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)\
|| defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16)
#define BOOST_ATOMIC_INT32_LOCK_FREE 2
#endif
#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)\
|| defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16)
#define BOOST_ATOMIC_INT64_LOCK_FREE 2
#endif
#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16)
#define BOOST_ATOMIC_INT128_LOCK_FREE 2
#endif
#define BOOST_ATOMIC_THREAD_FENCE 2
#define BOOST_ATOMIC_SIGNAL_FENCE 2
#endif // BOOST_ATOMIC_DETAIL_CAPS_GCC_SYNC_HPP_INCLUDED_

View File

@@ -0,0 +1,52 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2009 Helge Bahmann
* Copyright (c) 2012 Tim Blechmann
* Copyright (c) 2013 - 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/caps_gcc_x86.hpp
*
* This header defines feature capabilities macros
*/
#ifndef BOOST_ATOMIC_DETAIL_CAPS_GCC_X86_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CAPS_GCC_X86_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if defined(__i386__) &&\
(\
defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) ||\
defined(__i586__) || defined(__i686__) || defined(__pentium4__) || defined(__nocona__) || defined(__core2__) || defined(__corei7__) ||\
defined(__k6__) || defined(__athlon__) || defined(__k8__) || defined(__amdfam10__) || defined(__bdver1__) || defined(__bdver2__) || defined(__bdver3__) || defined(__btver1__) || defined(__btver2__)\
)
#define BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B 1
#endif
#if defined(__x86_64__) && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16)
#define BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B 1
#endif
#define BOOST_ATOMIC_INT8_LOCK_FREE 2
#define BOOST_ATOMIC_INT16_LOCK_FREE 2
#define BOOST_ATOMIC_INT32_LOCK_FREE 2
#if defined(__x86_64__) || defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B)
#define BOOST_ATOMIC_INT64_LOCK_FREE 2
#endif
#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B) && (defined(BOOST_HAS_INT128) || !defined(BOOST_NO_ALIGNMENT))
#define BOOST_ATOMIC_INT128_LOCK_FREE 2
#endif
#define BOOST_ATOMIC_POINTER_LOCK_FREE 2
#define BOOST_ATOMIC_THREAD_FENCE 2
#define BOOST_ATOMIC_SIGNAL_FENCE 2
#endif // BOOST_ATOMIC_DETAIL_CAPS_GCC_X86_HPP_INCLUDED_

View File

@@ -0,0 +1,35 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2009, 2011 Helge Bahmann
* Copyright (c) 2009 Phil Endecott
* Copyright (c) 2013 Tim Blechmann
* Linux-specific code by Phil Endecott
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/caps_linux_arm.hpp
*
* This header defines feature capabilities macros
*/
#ifndef BOOST_ATOMIC_DETAIL_CAPS_LINUX_ARM_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CAPS_LINUX_ARM_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#define BOOST_ATOMIC_INT8_LOCK_FREE 2
#define BOOST_ATOMIC_INT16_LOCK_FREE 2
#define BOOST_ATOMIC_INT32_LOCK_FREE 2
#define BOOST_ATOMIC_POINTER_LOCK_FREE 2
#define BOOST_ATOMIC_THREAD_FENCE 2
#define BOOST_ATOMIC_SIGNAL_FENCE 2
#endif // BOOST_ATOMIC_DETAIL_CAPS_LINUX_ARM_HPP_INCLUDED_

View File

@@ -0,0 +1,34 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2009 Helge Bahmann
* Copyright (c) 2013 Tim Blechmann
* Copyright (c) 2012 - 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/caps_msvc_arm.hpp
*
* This header defines feature capabilities macros
*/
#ifndef BOOST_ATOMIC_DETAIL_CAPS_MSVC_ARM_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CAPS_MSVC_ARM_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#define BOOST_ATOMIC_INT8_LOCK_FREE 2
#define BOOST_ATOMIC_INT16_LOCK_FREE 2
#define BOOST_ATOMIC_INT32_LOCK_FREE 2
#define BOOST_ATOMIC_INT64_LOCK_FREE 2
#define BOOST_ATOMIC_POINTER_LOCK_FREE 2
#define BOOST_ATOMIC_THREAD_FENCE 2
#define BOOST_ATOMIC_SIGNAL_FENCE 2
#endif // BOOST_ATOMIC_DETAIL_CAPS_MSVC_ARM_HPP_INCLUDED_

View File

@@ -0,0 +1,50 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2009 Helge Bahmann
* Copyright (c) 2013 Tim Blechmann
* Copyright (c) 2012 - 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/caps_msvc_x86.hpp
*
* This header defines feature capabilities macros
*/
#ifndef BOOST_ATOMIC_DETAIL_CAPS_MSVC_X86_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CAPS_MSVC_X86_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if defined(_M_IX86) && _M_IX86 >= 500
#define BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B 1
#endif
#if _MSC_VER >= 1500 && defined(_M_AMD64) && !defined(BOOST_ATOMIC_NO_CMPXCHG16B)
#define BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B 1
#endif
#define BOOST_ATOMIC_INT8_LOCK_FREE 2
#define BOOST_ATOMIC_INT16_LOCK_FREE 2
#define BOOST_ATOMIC_INT32_LOCK_FREE 2
#if defined(_M_AMD64) || defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B)
#define BOOST_ATOMIC_INT64_LOCK_FREE 2
#endif
#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B) && (defined(BOOST_HAS_INT128) || !defined(BOOST_NO_ALIGNMENT))
#define BOOST_ATOMIC_INT128_LOCK_FREE 2
#endif
#define BOOST_ATOMIC_POINTER_LOCK_FREE 2
#define BOOST_ATOMIC_THREAD_FENCE 2
#define BOOST_ATOMIC_SIGNAL_FENCE 2
#endif // BOOST_ATOMIC_DETAIL_CAPS_MSVC_X86_HPP_INCLUDED_

View File

@@ -0,0 +1,33 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2009 Helge Bahmann
* Copyright (c) 2013 Tim Blechmann
* Copyright (c) 2012 - 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/caps_windows.hpp
*
* This header defines feature capabilities macros
*/
#ifndef BOOST_ATOMIC_DETAIL_CAPS_WINDOWS_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CAPS_WINDOWS_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#define BOOST_ATOMIC_INT8_LOCK_FREE 2
#define BOOST_ATOMIC_INT16_LOCK_FREE 2
#define BOOST_ATOMIC_INT32_LOCK_FREE 2
#define BOOST_ATOMIC_POINTER_LOCK_FREE 2
#define BOOST_ATOMIC_THREAD_FENCE 2
#define BOOST_ATOMIC_SIGNAL_FENCE 2
#endif // BOOST_ATOMIC_DETAIL_CAPS_WINDOWS_HPP_INCLUDED_

View File

@@ -0,0 +1,75 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2012 Hartmut Kaiser
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/config.hpp
*
* This header defines configuraion macros for Boost.Atomic
*/
#ifndef BOOST_ATOMIC_DETAIL_CONFIG_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CONFIG_HPP_INCLUDED_
#include <boost/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if defined(__has_builtin)
#if __has_builtin(__builtin_memcpy)
#define BOOST_ATOMIC_DETAIL_HAS_BUILTIN_MEMCPY
#endif
#if __has_builtin(__builtin_memcmp)
#define BOOST_ATOMIC_DETAIL_HAS_BUILTIN_MEMCMP
#endif
#elif defined(BOOST_GCC)
#define BOOST_ATOMIC_DETAIL_HAS_BUILTIN_MEMCPY
#define BOOST_ATOMIC_DETAIL_HAS_BUILTIN_MEMCMP
#endif
#if defined(BOOST_ATOMIC_DETAIL_HAS_BUILTIN_MEMCPY)
#define BOOST_ATOMIC_DETAIL_MEMCPY __builtin_memcpy
#else
#define BOOST_ATOMIC_DETAIL_MEMCPY std::memcpy
#endif
#if defined(BOOST_ATOMIC_DETAIL_HAS_BUILTIN_MEMCMP)
#define BOOST_ATOMIC_DETAIL_MEMCMP __builtin_memcmp
#else
#define BOOST_ATOMIC_DETAIL_MEMCMP std::memcmp
#endif
#if defined(__CUDACC__)
// nvcc does not support alternatives in asm statement constraints
#define BOOST_ATOMIC_DETAIL_NO_ASM_CONSTRAINT_ALTERNATIVES
// nvcc does not support condition code register ("cc") clobber in asm statements
#define BOOST_ATOMIC_DETAIL_NO_ASM_CLOBBER_CC
#endif
#if !defined(BOOST_ATOMIC_DETAIL_NO_ASM_CLOBBER_CC)
#define BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC "cc"
#define BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "cc",
#else
#define BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
#define BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA
#endif
#if (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) && (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) < 403)
// This macro indicates we're using older binutils that don't support implied zero displacements for memory opereands,
// making code like this invalid:
// movl 4+(%%edx), %%eax
#define BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS
#endif
#if defined(__clang__) || (defined(BOOST_GCC) && (BOOST_GCC+0) < 40500)
// This macro indicates that the compiler does not support allocating rax:rdx register pairs ("A") in asm blocks
#define BOOST_ATOMIC_DETAIL_NO_ASM_RAX_RDX_PAIRS
#endif
#endif // BOOST_ATOMIC_DETAIL_CONFIG_HPP_INCLUDED_

View File

@@ -0,0 +1,140 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/int_sizes.hpp
*
* This header defines macros for testing buitin integer type sizes
*/
#ifndef BOOST_ATOMIC_DETAIL_INT_SIZES_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_INT_SIZES_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
// GCC and compatible compilers define internal macros with builtin type traits
#if defined(__SIZEOF_SHORT__)
#define BOOST_ATOMIC_DETAIL_SIZEOF_SHORT __SIZEOF_SHORT__
#endif
#if defined(__SIZEOF_INT__)
#define BOOST_ATOMIC_DETAIL_SIZEOF_INT __SIZEOF_INT__
#endif
#if defined(__SIZEOF_LONG__)
#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG __SIZEOF_LONG__
#endif
#if defined(__SIZEOF_LONG_LONG__)
#define BOOST_ATOMIC_DETAIL_SIZEOF_LLONG __SIZEOF_LONG_LONG__
#endif
#if defined(__SIZEOF_WCHAR_T__)
#define BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T __SIZEOF_WCHAR_T__
#endif
#if defined(__SIZEOF_POINTER__)
#define BOOST_ATOMIC_DETAIL_SIZEOF_POINTER __SIZEOF_POINTER__
#elif defined(_MSC_VER)
#if defined(_M_AMD64) || defined(_M_IA64)
#define BOOST_ATOMIC_DETAIL_SIZEOF_POINTER 8
#else
#define BOOST_ATOMIC_DETAIL_SIZEOF_POINTER 4
#endif
#endif
#if !defined(BOOST_ATOMIC_DETAIL_SIZEOF_SHORT) || !defined(BOOST_ATOMIC_DETAIL_SIZEOF_INT) ||\
!defined(BOOST_ATOMIC_DETAIL_SIZEOF_LONG) || !defined(BOOST_ATOMIC_DETAIL_SIZEOF_LLONG)
// Try to deduce sizes from limits
#include <limits.h>
#include <boost/cstdint.hpp>
#if (USHRT_MAX + 0) == 0xff
#define BOOST_ATOMIC_DETAIL_SIZEOF_SHORT 1
#elif (USHRT_MAX + 0) == 0xffff
#define BOOST_ATOMIC_DETAIL_SIZEOF_SHORT 2
#elif (USHRT_MAX + 0) == 0xffffffff
#define BOOST_ATOMIC_DETAIL_SIZEOF_SHORT 4
#elif (USHRT_MAX + 0) == UINT64_C(0xffffffffffffffff)
#define BOOST_ATOMIC_DETAIL_SIZEOF_SHORT 8
#endif
#if (UINT_MAX + 0) == 0xff
#define BOOST_ATOMIC_DETAIL_SIZEOF_INT 1
#elif (UINT_MAX + 0) == 0xffff
#define BOOST_ATOMIC_DETAIL_SIZEOF_INT 2
#elif (UINT_MAX + 0) == 0xffffffff
#define BOOST_ATOMIC_DETAIL_SIZEOF_INT 4
#elif (UINT_MAX + 0) == UINT64_C(0xffffffffffffffff)
#define BOOST_ATOMIC_DETAIL_SIZEOF_INT 8
#endif
#if (ULONG_MAX + 0) == 0xff
#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG 1
#elif (ULONG_MAX + 0) == 0xffff
#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG 2
#elif (ULONG_MAX + 0) == 0xffffffff
#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG 4
#elif (ULONG_MAX + 0) == UINT64_C(0xffffffffffffffff)
#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG 8
#endif
#if defined(__hpux) // HP-UX's value of ULONG_LONG_MAX is unusable in preprocessor expressions
#define BOOST_ATOMIC_DETAIL_SIZEOF_LLONG 8
#else
// The list of the non-standard macros (the ones except ULLONG_MAX) is taken from cstdint.hpp
#if defined(ULLONG_MAX)
#define BOOST_ATOMIC_DETAIL_ULLONG_MAX ULLONG_MAX
#elif defined(ULONG_LONG_MAX)
#define BOOST_ATOMIC_DETAIL_ULLONG_MAX ULONG_LONG_MAX
#elif defined(ULONGLONG_MAX)
#define BOOST_ATOMIC_DETAIL_ULLONG_MAX ULONGLONG_MAX
#elif defined(_LLONG_MAX) // strangely enough, this one seems to be holding the limit for the unsigned integer
#define BOOST_ATOMIC_DETAIL_ULLONG_MAX _LLONG_MAX
#endif
#if (BOOST_ATOMIC_DETAIL_ULLONG_MAX + 0) == 0xff
#define BOOST_ATOMIC_DETAIL_SIZEOF_LLONG 1
#elif (BOOST_ATOMIC_DETAIL_ULLONG_MAX + 0) == 0xffff
#define BOOST_ATOMIC_DETAIL_SIZEOF_LLONG 2
#elif (BOOST_ATOMIC_DETAIL_ULLONG_MAX + 0) == 0xffffffff
#define BOOST_ATOMIC_DETAIL_SIZEOF_LLONG 4
#elif (BOOST_ATOMIC_DETAIL_ULLONG_MAX + 0) == UINT64_C(0xffffffffffffffff)
#define BOOST_ATOMIC_DETAIL_SIZEOF_LLONG 8
#endif
#endif // defined(__hpux)
#endif
#if !defined(BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T)
#include <wchar.h>
#include <boost/cstdint.hpp>
#if defined(_MSC_VER) && ( _MSC_VER <= 1310 || defined(UNDER_CE) && _MSC_VER <= 1500 )
// MSVC 7.1 and MSVC 8 (arm) define WCHAR_MAX to a value not suitable for constant expressions
#define BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T 2
#elif (WCHAR_MAX + 0) == 0xff || (WCHAR_MAX + 0) == 0x7f
#define BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T 1
#elif (WCHAR_MAX + 0) == 0xffff || (WCHAR_MAX + 0) == 0x7fff
#define BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T 2
#elif (WCHAR_MAX + 0) == 0xffffffff || (WCHAR_MAX + 0) == 0x7fffffff
#define BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T 4
#elif (WCHAR_MAX + 0) == UINT64_C(0xffffffffffffffff) || (WCHAR_MAX + 0) == INT64_C(0x7fffffffffffffff)
#define BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T 8
#endif
#endif
#if !defined(BOOST_ATOMIC_DETAIL_SIZEOF_SHORT) || !defined(BOOST_ATOMIC_DETAIL_SIZEOF_INT) ||\
!defined(BOOST_ATOMIC_DETAIL_SIZEOF_LONG) || !defined(BOOST_ATOMIC_DETAIL_SIZEOF_LLONG) ||\
!defined(BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T)
#error Boost.Atomic: Failed to determine builtin integer sizes, the target platform is not supported. Please, report to the developers.
#endif
#endif // BOOST_ATOMIC_DETAIL_INT_SIZES_HPP_INCLUDED_

View File

@@ -0,0 +1,481 @@
#ifndef BOOST_ATOMIC_DETAIL_INTERLOCKED_HPP
#define BOOST_ATOMIC_DETAIL_INTERLOCKED_HPP
// Copyright (c) 2009 Helge Bahmann
// Copyright (c) 2012 - 2014 Andrey Semashev
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/atomic/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if defined(_WIN32_WCE)
#if _WIN32_WCE >= 0x600
extern "C" long __cdecl _InterlockedCompareExchange( long volatile *, long, long );
extern "C" long __cdecl _InterlockedExchangeAdd( long volatile *, long );
extern "C" long __cdecl _InterlockedExchange( long volatile *, long );
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare) _InterlockedCompareExchange((long*)(dest), exchange, compare)
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(dest, addend) _InterlockedExchangeAdd((long*)(dest), (long)(addend))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE(dest, newval) _InterlockedExchange((long*)(dest), (long)(newval))
#else // _WIN32_WCE >= 0x600
extern "C" long __cdecl InterlockedCompareExchange( long*, long, long );
extern "C" long __cdecl InterlockedExchangeAdd( long*, long );
extern "C" long __cdecl InterlockedExchange( long*, long );
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare) InterlockedCompareExchange((long*)(dest), exchange, compare)
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(dest, addend) InterlockedExchangeAdd((long*)(dest), (long)(addend))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE(dest, newval) InterlockedExchange((long*)(dest), (long)(newval))
#endif // _WIN32_WCE >= 0x600
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) ((void*)BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE((long*)(dest), (long)(exchange), (long)(compare)))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER(dest, exchange) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE((long*)(dest), (long)(exchange)))
#elif defined(_MSC_VER) && _MSC_VER >= 1310
#if _MSC_VER < 1400
extern "C" long __cdecl _InterlockedCompareExchange( long volatile *, long, long );
extern "C" long __cdecl _InterlockedExchangeAdd( long volatile *, long );
extern "C" long __cdecl _InterlockedExchange( long volatile *, long );
#if defined(BOOST_MSVC)
#pragma intrinsic(_InterlockedCompareExchange)
#pragma intrinsic(_InterlockedExchangeAdd)
#pragma intrinsic(_InterlockedExchange)
#endif
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare) _InterlockedCompareExchange((long*)(dest), exchange, compare)
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(dest, addend) _InterlockedExchangeAdd((long*)(dest), (long)(addend))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE(dest, newval) _InterlockedExchange((long*)(dest), (long)(newval))
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) ((void*)BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE((long*)(dest), (long)(exchange), (long)(compare)))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER(dest, exchange) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE((long*)(dest), (long)(exchange)))
#else // _MSC_VER < 1400
#include <intrin.h>
#if defined(BOOST_MSVC)
#pragma intrinsic(_InterlockedCompareExchange)
#pragma intrinsic(_InterlockedExchangeAdd)
#pragma intrinsic(_InterlockedExchange)
#pragma intrinsic(_InterlockedAnd)
#pragma intrinsic(_InterlockedOr)
#pragma intrinsic(_InterlockedXor)
#endif
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare) _InterlockedCompareExchange((long*)(dest), (long)(exchange), (long)(compare))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(dest, addend) _InterlockedExchangeAdd((long*)(dest), (long)(addend))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE(dest, newval) _InterlockedExchange((long*)(dest), (long)(newval))
#define BOOST_ATOMIC_INTERLOCKED_AND(dest, arg) _InterlockedAnd((long*)(dest), (long)(arg))
#define BOOST_ATOMIC_INTERLOCKED_OR(dest, arg) _InterlockedOr((long*)(dest), (long)(arg))
#define BOOST_ATOMIC_INTERLOCKED_XOR(dest, arg) _InterlockedXor((long*)(dest), (long)(arg))
#if (defined(_M_IX86) && _M_IX86 >= 500) || defined(_M_AMD64) || defined(_M_IA64)
#if defined(BOOST_MSVC)
#pragma intrinsic(_InterlockedCompareExchange64)
#endif
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64(dest, exchange, compare) _InterlockedCompareExchange64((__int64*)(dest), (__int64)(exchange), (__int64)(compare))
#endif
#if _MSC_VER >= 1500 && defined(_M_AMD64)
#if defined(BOOST_MSVC)
#pragma intrinsic(_InterlockedCompareExchange128)
#endif
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE128(dest, exchange, compare) _InterlockedCompareExchange128((__int64*)(dest), ((const __int64*)(&exchange))[1], ((const __int64*)(&exchange))[0], (__int64*)(compare))
#endif
#if _MSC_VER >= 1600
// MSVC 2010 and later provide intrinsics for 8 and 16 bit integers.
// Note that for each bit count these macros must be either all defined or all not defined.
// Otherwise atomic<> operations will be implemented inconsistently.
#if defined(BOOST_MSVC)
#pragma intrinsic(_InterlockedCompareExchange8)
#pragma intrinsic(_InterlockedExchangeAdd8)
#pragma intrinsic(_InterlockedExchange8)
#pragma intrinsic(_InterlockedAnd8)
#pragma intrinsic(_InterlockedOr8)
#pragma intrinsic(_InterlockedXor8)
#endif
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE8(dest, exchange, compare) _InterlockedCompareExchange8((char*)(dest), (char)(exchange), (char)(compare))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD8(dest, addend) _InterlockedExchangeAdd8((char*)(dest), (char)(addend))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE8(dest, newval) _InterlockedExchange8((char*)(dest), (char)(newval))
#define BOOST_ATOMIC_INTERLOCKED_AND8(dest, arg) _InterlockedAnd8((char*)(dest), (char)(arg))
#define BOOST_ATOMIC_INTERLOCKED_OR8(dest, arg) _InterlockedOr8((char*)(dest), (char)(arg))
#define BOOST_ATOMIC_INTERLOCKED_XOR8(dest, arg) _InterlockedXor8((char*)(dest), (char)(arg))
#if defined(BOOST_MSVC)
#pragma intrinsic(_InterlockedCompareExchange16)
#pragma intrinsic(_InterlockedExchangeAdd16)
#pragma intrinsic(_InterlockedExchange16)
#pragma intrinsic(_InterlockedAnd16)
#pragma intrinsic(_InterlockedOr16)
#pragma intrinsic(_InterlockedXor16)
#endif
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE16(dest, exchange, compare) _InterlockedCompareExchange16((short*)(dest), (short)(exchange), (short)(compare))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD16(dest, addend) _InterlockedExchangeAdd16((short*)(dest), (short)(addend))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE16(dest, newval) _InterlockedExchange16((short*)(dest), (short)(newval))
#define BOOST_ATOMIC_INTERLOCKED_AND16(dest, arg) _InterlockedAnd16((short*)(dest), (short)(arg))
#define BOOST_ATOMIC_INTERLOCKED_OR16(dest, arg) _InterlockedOr16((short*)(dest), (short)(arg))
#define BOOST_ATOMIC_INTERLOCKED_XOR16(dest, arg) _InterlockedXor16((short*)(dest), (short)(arg))
#endif // _MSC_VER >= 1600
#if defined(_M_AMD64) || defined(_M_IA64)
#if defined(BOOST_MSVC)
#pragma intrinsic(_InterlockedExchangeAdd64)
#pragma intrinsic(_InterlockedExchange64)
#pragma intrinsic(_InterlockedAnd64)
#pragma intrinsic(_InterlockedOr64)
#pragma intrinsic(_InterlockedXor64)
#endif
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64(dest, addend) _InterlockedExchangeAdd64((__int64*)(dest), (__int64)(addend))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE64(dest, newval) _InterlockedExchange64((__int64*)(dest), (__int64)(newval))
#define BOOST_ATOMIC_INTERLOCKED_AND64(dest, arg) _InterlockedAnd64((__int64*)(dest), (__int64)(arg))
#define BOOST_ATOMIC_INTERLOCKED_OR64(dest, arg) _InterlockedOr64((__int64*)(dest), (__int64)(arg))
#define BOOST_ATOMIC_INTERLOCKED_XOR64(dest, arg) _InterlockedXor64((__int64*)(dest), (__int64)(arg))
#if defined(BOOST_MSVC)
#pragma intrinsic(_InterlockedCompareExchangePointer)
#pragma intrinsic(_InterlockedExchangePointer)
#endif
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) _InterlockedCompareExchangePointer((void**)(dest), (void*)(exchange), (void*)(compare))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER(dest, newval) _InterlockedExchangePointer((void**)(dest), (void*)(newval))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64((long*)(dest), byte_offset))
#elif defined(_M_IX86)
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) ((void*)_InterlockedCompareExchange((long*)(dest), (long)(exchange), (long)(compare)))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER(dest, newval) ((void*)_InterlockedExchange((long*)(dest), (long)(newval)))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD((long*)(dest), byte_offset))
#endif
#if _MSC_VER >= 1700 && defined(_M_ARM)
#if defined(BOOST_MSVC)
#pragma intrinsic(_InterlockedExchangeAdd64)
#pragma intrinsic(_InterlockedExchange64)
#pragma intrinsic(_InterlockedAnd64)
#pragma intrinsic(_InterlockedOr64)
#pragma intrinsic(_InterlockedXor64)
#endif
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64(dest, addend) _InterlockedExchangeAdd64((__int64*)(dest), (__int64)(addend))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE64(dest, newval) _InterlockedExchange64((__int64*)(dest), (__int64)(newval))
#define BOOST_ATOMIC_INTERLOCKED_AND64(dest, arg) _InterlockedAnd64((__int64*)(dest), (__int64)(arg))
#define BOOST_ATOMIC_INTERLOCKED_OR64(dest, arg) _InterlockedOr64((__int64*)(dest), (__int64)(arg))
#define BOOST_ATOMIC_INTERLOCKED_XOR64(dest, arg) _InterlockedXor64((__int64*)(dest), (__int64)(arg))
#if defined(BOOST_MSVC)
#pragma intrinsic(_InterlockedCompareExchange8_nf)
#pragma intrinsic(_InterlockedCompareExchange8_acq)
#pragma intrinsic(_InterlockedCompareExchange8_rel)
#pragma intrinsic(_InterlockedCompareExchange16_nf)
#pragma intrinsic(_InterlockedCompareExchange16_acq)
#pragma intrinsic(_InterlockedCompareExchange16_rel)
#pragma intrinsic(_InterlockedCompareExchange_nf)
#pragma intrinsic(_InterlockedCompareExchange_acq)
#pragma intrinsic(_InterlockedCompareExchange_rel)
#pragma intrinsic(_InterlockedCompareExchange64)
#pragma intrinsic(_InterlockedCompareExchange64_nf)
#pragma intrinsic(_InterlockedCompareExchange64_acq)
#pragma intrinsic(_InterlockedCompareExchange64_rel)
#pragma intrinsic(_InterlockedCompareExchangePointer)
#pragma intrinsic(_InterlockedCompareExchangePointer_nf)
#pragma intrinsic(_InterlockedCompareExchangePointer_acq)
#pragma intrinsic(_InterlockedCompareExchangePointer_rel)
#endif
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE8_RELAXED(dest, exchange, compare) _InterlockedCompareExchange8_nf((char*)(dest), (char)(exchange), (char)(compare))
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE8_ACQUIRE(dest, exchange, compare) _InterlockedCompareExchange8_acq((char*)(dest), (char)(exchange), (char)(compare))
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE8_RELEASE(dest, exchange, compare) _InterlockedCompareExchange8_rel((char*)(dest), (char)(exchange), (char)(compare))
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE16_RELAXED(dest, exchange, compare) _InterlockedCompareExchange16_nf((short*)(dest), (short)(exchange), (short)(compare))
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE16_ACQUIRE(dest, exchange, compare) _InterlockedCompareExchange16_acq((short*)(dest), (short)(exchange), (short)(compare))
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE16_RELEASE(dest, exchange, compare) _InterlockedCompareExchange16_rel((short*)(dest), (short)(exchange), (short)(compare))
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_RELAXED(dest, exchange, compare) _InterlockedCompareExchange_nf((long*)(dest), (long)(exchange), (long)(compare))
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_ACQUIRE(dest, exchange, compare) _InterlockedCompareExchange_acq((long*)(dest), (long)(exchange), (long)(compare))
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_RELEASE(dest, exchange, compare) _InterlockedCompareExchange_rel((long*)(dest), (long)(exchange), (long)(compare))
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64(dest, exchange, compare) _InterlockedCompareExchange64((__int64*)(dest), (__int64)(exchange), (__int64)(compare))
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64_RELAXED(dest, exchange, compare) _InterlockedCompareExchange64_nf((__int64*)(dest), (__int64)(exchange), (__int64)(compare))
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64_ACQUIRE(dest, exchange, compare) _InterlockedCompareExchange64_acq((__int64*)(dest), (__int64)(exchange), (__int64)(compare))
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64_RELEASE(dest, exchange, compare) _InterlockedCompareExchange64_rel((__int64*)(dest), (__int64)(exchange), (__int64)(compare))
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) _InterlockedCompareExchangePointer((void**)(dest), (void*)(exchange), (void*)(compare))
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_POINTER_RELAXED(dest, exchange, compare) _InterlockedCompareExchangePointer_nf((void**)(dest), (void*)(exchange), (void*)(compare))
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_POINTER_ACQUIRE(dest, exchange, compare) _InterlockedCompareExchangePointer_acq((void**)(dest), (void*)(exchange), (void*)(compare))
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_POINTER_RELEASE(dest, exchange, compare) _InterlockedCompareExchangePointer_rel((void**)(dest), (void*)(exchange), (void*)(compare))
#if defined(BOOST_MSVC)
#pragma intrinsic(_InterlockedExchangeAdd8_nf)
#pragma intrinsic(_InterlockedExchangeAdd8_acq)
#pragma intrinsic(_InterlockedExchangeAdd8_rel)
#pragma intrinsic(_InterlockedExchangeAdd16_nf)
#pragma intrinsic(_InterlockedExchangeAdd16_acq)
#pragma intrinsic(_InterlockedExchangeAdd16_rel)
#pragma intrinsic(_InterlockedExchangeAdd_nf)
#pragma intrinsic(_InterlockedExchangeAdd_acq)
#pragma intrinsic(_InterlockedExchangeAdd_rel)
#pragma intrinsic(_InterlockedExchangeAdd64_nf)
#pragma intrinsic(_InterlockedExchangeAdd64_acq)
#pragma intrinsic(_InterlockedExchangeAdd64_rel)
#endif
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD8_RELAXED(dest, addend) _InterlockedExchangeAdd8_nf((char*)(dest), (char)(addend))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD8_ACQUIRE(dest, addend) _InterlockedExchangeAdd8_acq((char*)(dest), (char)(addend))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD8_RELEASE(dest, addend) _InterlockedExchangeAdd8_rel((char*)(dest), (char)(addend))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD16_RELAXED(dest, addend) _InterlockedExchangeAdd16_nf((short*)(dest), (short)(addend))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD16_ACQUIRE(dest, addend) _InterlockedExchangeAdd16_acq((short*)(dest), (short)(addend))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD16_RELEASE(dest, addend) _InterlockedExchangeAdd16_rel((short*)(dest), (short)(addend))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_RELAXED(dest, addend) _InterlockedExchangeAdd_nf((long*)(dest), (long)(addend))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_ACQUIRE(dest, addend) _InterlockedExchangeAdd_acq((long*)(dest), (long)(addend))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_RELEASE(dest, addend) _InterlockedExchangeAdd_rel((long*)(dest), (long)(addend))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64_RELAXED(dest, addend) _InterlockedExchangeAdd64_nf((__int64*)(dest), (__int64)(addend))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64_ACQUIRE(dest, addend) _InterlockedExchangeAdd64_acq((__int64*)(dest), (__int64)(addend))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64_RELEASE(dest, addend) _InterlockedExchangeAdd64_rel((__int64*)(dest), (__int64)(addend))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD((long*)(dest), byte_offset))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER_RELAXED(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_RELAXED((long*)(dest), byte_offset))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER_ACQUIRE(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_ACQUIRE((long*)(dest), byte_offset))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER_RELEASE(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_RELEASE((long*)(dest), byte_offset))
#if defined(BOOST_MSVC)
#pragma intrinsic(_InterlockedExchange8_nf)
#pragma intrinsic(_InterlockedExchange8_acq)
#pragma intrinsic(_InterlockedExchange16_nf)
#pragma intrinsic(_InterlockedExchange16_acq)
#pragma intrinsic(_InterlockedExchange_nf)
#pragma intrinsic(_InterlockedExchange_acq)
#pragma intrinsic(_InterlockedExchange64_nf)
#pragma intrinsic(_InterlockedExchange64_acq)
#pragma intrinsic(_InterlockedExchangePointer)
#pragma intrinsic(_InterlockedExchangePointer_nf)
#pragma intrinsic(_InterlockedExchangePointer_acq)
#if _MSC_VER >= 1800
#pragma intrinsic(_InterlockedExchange8_rel)
#pragma intrinsic(_InterlockedExchange16_rel)
#pragma intrinsic(_InterlockedExchange_rel)
#pragma intrinsic(_InterlockedExchange64_rel)
#pragma intrinsic(_InterlockedExchangePointer_rel)
#endif
#endif
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE8_RELAXED(dest, newval) _InterlockedExchange8_nf((char*)(dest), (char)(newval))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE8_ACQUIRE(dest, newval) _InterlockedExchange8_acq((char*)(dest), (char)(newval))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE16_RELAXED(dest, newval) _InterlockedExchange16_nf((short*)(dest), (short)(newval))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE16_ACQUIRE(dest, newval) _InterlockedExchange16_acq((short*)(dest), (short)(newval))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_RELAXED(dest, newval) _InterlockedExchange_nf((long*)(dest), (long)(newval))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ACQUIRE(dest, newval) _InterlockedExchange_acq((long*)(dest), (long)(newval))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE64_RELAXED(dest, newval) _InterlockedExchange64_nf((__int64*)(dest), (__int64)(newval))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE64_ACQUIRE(dest, newval) _InterlockedExchange64_acq((__int64*)(dest), (__int64)(newval))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER(dest, newval) _InterlockedExchangePointer((void**)(dest), (void*)(newval))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER_RELAXED(dest, newval) _InterlockedExchangePointer_nf((void**)(dest), (void*)(newval))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER_ACQUIRE(dest, newval) _InterlockedExchangePointer_acq((void**)(dest), (void*)(newval))
#if _MSC_VER >= 1800
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE8_RELEASE(dest, newval) _InterlockedExchange8_rel((char*)(dest), (char)(newval))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE16_RELEASE(dest, newval) _InterlockedExchange16_rel((short*)(dest), (short)(newval))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_RELEASE(dest, newval) _InterlockedExchange_rel((long*)(dest), (long)(newval))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE64_RELEASE(dest, newval) _InterlockedExchange64_rel((__int64*)(dest), (__int64)(newval))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER_RELEASE(dest, newval) _InterlockedExchangePointer_rel((void**)(dest), (void*)(newval))
#else
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE8_RELEASE(dest, newval) BOOST_ATOMIC_INTERLOCKED_EXCHANGE8(dest, newval)
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE16_RELEASE(dest, newval) BOOST_ATOMIC_INTERLOCKED_EXCHANGE16(dest, newval)
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_RELEASE(dest, newval) BOOST_ATOMIC_INTERLOCKED_EXCHANGE(dest, newval)
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE64_RELEASE(dest, newval) BOOST_ATOMIC_INTERLOCKED_EXCHANGE64(dest, newval)
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER_RELEASE(dest, newval) BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER(dest, newval)
#endif
#if defined(BOOST_MSVC)
#pragma intrinsic(_InterlockedAnd8_nf)
#pragma intrinsic(_InterlockedAnd8_acq)
#pragma intrinsic(_InterlockedAnd8_rel)
#pragma intrinsic(_InterlockedAnd16_nf)
#pragma intrinsic(_InterlockedAnd16_acq)
#pragma intrinsic(_InterlockedAnd16_rel)
#pragma intrinsic(_InterlockedAnd_nf)
#pragma intrinsic(_InterlockedAnd_acq)
#pragma intrinsic(_InterlockedAnd_rel)
#pragma intrinsic(_InterlockedAnd64_nf)
#pragma intrinsic(_InterlockedAnd64_acq)
#pragma intrinsic(_InterlockedAnd64_rel)
#endif
#define BOOST_ATOMIC_INTERLOCKED_AND8_RELAXED(dest, arg) _InterlockedAnd8_nf((char*)(dest), (char)(arg))
#define BOOST_ATOMIC_INTERLOCKED_AND8_ACQUIRE(dest, arg) _InterlockedAnd8_acq((char*)(dest), (char)(arg))
#define BOOST_ATOMIC_INTERLOCKED_AND8_RELEASE(dest, arg) _InterlockedAnd8_rel((char*)(dest), (char)(arg))
#define BOOST_ATOMIC_INTERLOCKED_AND16_RELAXED(dest, arg) _InterlockedAnd16_nf((short*)(dest), (short)(arg))
#define BOOST_ATOMIC_INTERLOCKED_AND16_ACQUIRE(dest, arg) _InterlockedAnd16_acq((short*)(dest), (short)(arg))
#define BOOST_ATOMIC_INTERLOCKED_AND16_RELEASE(dest, arg) _InterlockedAnd16_rel((short*)(dest), (short)(arg))
#define BOOST_ATOMIC_INTERLOCKED_AND_RELAXED(dest, arg) _InterlockedAnd_nf((long*)(dest), (long)(arg))
#define BOOST_ATOMIC_INTERLOCKED_AND_ACQUIRE(dest, arg) _InterlockedAnd_acq((long*)(dest), (long)(arg))
#define BOOST_ATOMIC_INTERLOCKED_AND_RELEASE(dest, arg) _InterlockedAnd_rel((long*)(dest), (long)(arg))
#define BOOST_ATOMIC_INTERLOCKED_AND64_RELAXED(dest, arg) _InterlockedAnd64_nf((__int64*)(dest), (__int64)(arg))
#define BOOST_ATOMIC_INTERLOCKED_AND64_ACQUIRE(dest, arg) _InterlockedAnd64_acq((__int64*)(dest), (__int64)(arg))
#define BOOST_ATOMIC_INTERLOCKED_AND64_RELEASE(dest, arg) _InterlockedAnd64_rel((__int64*)(dest), (__int64)(arg))
#if defined(BOOST_MSVC)
#pragma intrinsic(_InterlockedOr8_nf)
#pragma intrinsic(_InterlockedOr8_acq)
#pragma intrinsic(_InterlockedOr8_rel)
#pragma intrinsic(_InterlockedOr16_nf)
#pragma intrinsic(_InterlockedOr16_acq)
#pragma intrinsic(_InterlockedOr16_rel)
#pragma intrinsic(_InterlockedOr_nf)
#pragma intrinsic(_InterlockedOr_acq)
#pragma intrinsic(_InterlockedOr_rel)
#pragma intrinsic(_InterlockedOr64_nf)
#pragma intrinsic(_InterlockedOr64_acq)
#pragma intrinsic(_InterlockedOr64_rel)
#endif
#define BOOST_ATOMIC_INTERLOCKED_OR8_RELAXED(dest, arg) _InterlockedOr8_nf((char*)(dest), (char)(arg))
#define BOOST_ATOMIC_INTERLOCKED_OR8_ACQUIRE(dest, arg) _InterlockedOr8_acq((char*)(dest), (char)(arg))
#define BOOST_ATOMIC_INTERLOCKED_OR8_RELEASE(dest, arg) _InterlockedOr8_rel((char*)(dest), (char)(arg))
#define BOOST_ATOMIC_INTERLOCKED_OR16_RELAXED(dest, arg) _InterlockedOr16_nf((short*)(dest), (short)(arg))
#define BOOST_ATOMIC_INTERLOCKED_OR16_ACQUIRE(dest, arg) _InterlockedOr16_acq((short*)(dest), (short)(arg))
#define BOOST_ATOMIC_INTERLOCKED_OR16_RELEASE(dest, arg) _InterlockedOr16_rel((short*)(dest), (short)(arg))
#define BOOST_ATOMIC_INTERLOCKED_OR_RELAXED(dest, arg) _InterlockedOr_nf((long*)(dest), (long)(arg))
#define BOOST_ATOMIC_INTERLOCKED_OR_ACQUIRE(dest, arg) _InterlockedOr_acq((long*)(dest), (long)(arg))
#define BOOST_ATOMIC_INTERLOCKED_OR_RELEASE(dest, arg) _InterlockedOr_rel((long*)(dest), (long)(arg))
#define BOOST_ATOMIC_INTERLOCKED_OR64_RELAXED(dest, arg) _InterlockedOr64_nf((__int64*)(dest), (__int64)(arg))
#define BOOST_ATOMIC_INTERLOCKED_OR64_ACQUIRE(dest, arg) _InterlockedOr64_acq((__int64*)(dest), (__int64)(arg))
#define BOOST_ATOMIC_INTERLOCKED_OR64_RELEASE(dest, arg) _InterlockedOr64_rel((__int64*)(dest), (__int64)(arg))
#if defined(BOOST_MSVC)
#pragma intrinsic(_InterlockedXor8_nf)
#pragma intrinsic(_InterlockedXor8_acq)
#pragma intrinsic(_InterlockedXor8_rel)
#pragma intrinsic(_InterlockedXor16_nf)
#pragma intrinsic(_InterlockedXor16_acq)
#pragma intrinsic(_InterlockedXor16_rel)
#pragma intrinsic(_InterlockedXor_nf)
#pragma intrinsic(_InterlockedXor_acq)
#pragma intrinsic(_InterlockedXor_rel)
#pragma intrinsic(_InterlockedXor64_nf)
#pragma intrinsic(_InterlockedXor64_acq)
#pragma intrinsic(_InterlockedXor64_rel)
#endif
#define BOOST_ATOMIC_INTERLOCKED_XOR8_RELAXED(dest, arg) _InterlockedXor8_nf((char*)(dest), (char)(arg))
#define BOOST_ATOMIC_INTERLOCKED_XOR8_ACQUIRE(dest, arg) _InterlockedXor8_acq((char*)(dest), (char)(arg))
#define BOOST_ATOMIC_INTERLOCKED_XOR8_RELEASE(dest, arg) _InterlockedXor8_rel((char*)(dest), (char)(arg))
#define BOOST_ATOMIC_INTERLOCKED_XOR16_RELAXED(dest, arg) _InterlockedXor16_nf((short*)(dest), (short)(arg))
#define BOOST_ATOMIC_INTERLOCKED_XOR16_ACQUIRE(dest, arg) _InterlockedXor16_acq((short*)(dest), (short)(arg))
#define BOOST_ATOMIC_INTERLOCKED_XOR16_RELEASE(dest, arg) _InterlockedXor16_rel((short*)(dest), (short)(arg))
#define BOOST_ATOMIC_INTERLOCKED_XOR_RELAXED(dest, arg) _InterlockedXor_nf((long*)(dest), (long)(arg))
#define BOOST_ATOMIC_INTERLOCKED_XOR_ACQUIRE(dest, arg) _InterlockedXor_acq((long*)(dest), (long)(arg))
#define BOOST_ATOMIC_INTERLOCKED_XOR_RELEASE(dest, arg) _InterlockedXor_rel((long*)(dest), (long)(arg))
#define BOOST_ATOMIC_INTERLOCKED_XOR64_RELAXED(dest, arg) _InterlockedXor64_nf((__int64*)(dest), (__int64)(arg))
#define BOOST_ATOMIC_INTERLOCKED_XOR64_ACQUIRE(dest, arg) _InterlockedXor64_acq((__int64*)(dest), (__int64)(arg))
#define BOOST_ATOMIC_INTERLOCKED_XOR64_RELEASE(dest, arg) _InterlockedXor64_rel((__int64*)(dest), (__int64)(arg))
#endif // _MSC_VER >= 1700 && defined(_M_ARM)
#endif // _MSC_VER < 1400
#else // defined(_MSC_VER) && _MSC_VER >= 1310
#if defined(BOOST_USE_WINDOWS_H)
#include <windows.h>
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare) InterlockedCompareExchange((long*)(dest), (long)(exchange), (long)(compare))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE(dest, newval) InterlockedExchange((long*)(dest), (long)(newval))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(dest, addend) InterlockedExchangeAdd((long*)(dest), (long)(addend))
#if defined(_WIN64)
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64(dest, exchange, compare) InterlockedCompareExchange64((__int64*)(dest), (__int64)(exchange), (__int64)(compare))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE64(dest, newval) InterlockedExchange64((__int64*)(dest), (__int64)(newval))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64(dest, addend) InterlockedExchangeAdd64((__int64*)(dest), (__int64)(addend))
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) InterlockedCompareExchangePointer((void**)(dest), (void*)(exchange), (void*)(compare))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER(dest, newval) InterlockedExchangePointer((void**)(dest), (void*)(newval))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64(dest, byte_offset))
#else // defined(_WIN64)
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) ((void*)BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER(dest, newval) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE(dest, newval))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(dest, byte_offset))
#endif // defined(_WIN64)
#else // defined(BOOST_USE_WINDOWS_H)
#if defined(__MINGW64__)
#define BOOST_ATOMIC_INTERLOCKED_IMPORT
#else
#define BOOST_ATOMIC_INTERLOCKED_IMPORT __declspec(dllimport)
#endif
namespace boost {
namespace atomics {
namespace detail {
extern "C" {
BOOST_ATOMIC_INTERLOCKED_IMPORT long __stdcall InterlockedCompareExchange(long volatile*, long, long);
BOOST_ATOMIC_INTERLOCKED_IMPORT long __stdcall InterlockedExchange(long volatile*, long);
BOOST_ATOMIC_INTERLOCKED_IMPORT long __stdcall InterlockedExchangeAdd(long volatile*, long);
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare) boost::atomics::detail::InterlockedCompareExchange((long*)(dest), (long)(exchange), (long)(compare))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE(dest, newval) boost::atomics::detail::InterlockedExchange((long*)(dest), (long)(newval))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(dest, addend) boost::atomics::detail::InterlockedExchangeAdd((long*)(dest), (long)(addend))
#if defined(_WIN64)
BOOST_ATOMIC_INTERLOCKED_IMPORT __int64 __stdcall InterlockedCompareExchange64(__int64 volatile*, __int64, __int64);
BOOST_ATOMIC_INTERLOCKED_IMPORT __int64 __stdcall InterlockedExchange64(__int64 volatile*, __int64);
BOOST_ATOMIC_INTERLOCKED_IMPORT __int64 __stdcall InterlockedExchangeAdd64(__int64 volatile*, __int64);
BOOST_ATOMIC_INTERLOCKED_IMPORT void* __stdcall InterlockedCompareExchangePointer(void* volatile *, void*, void*);
BOOST_ATOMIC_INTERLOCKED_IMPORT void* __stdcall InterlockedExchangePointer(void* volatile *, void*);
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64(dest, exchange, compare) boost::atomics::detail::InterlockedCompareExchange64((__int64*)(dest), (__int64)(exchange), (__int64)(compare))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE64(dest, newval) boost::atomics::detail::InterlockedExchange64((__int64*)(dest), (__int64)(newval))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64(dest, addend) boost::atomics::detail::InterlockedExchangeAdd64((__int64*)(dest), (__int64)(addend))
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) boost::atomics::detail::InterlockedCompareExchangePointer((void**)(dest), (void*)(exchange), (void*)(compare))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER(dest, newval) boost::atomics::detail::InterlockedExchangePointer((void**)(dest), (void*)(newval))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64(dest, byte_offset))
#else // defined(_WIN64)
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) ((void*)BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER(dest, newval) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE(dest, newval))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(dest, byte_offset))
#endif // defined(_WIN64)
} // extern "C"
} // namespace detail
} // namespace atomics
} // namespace boost
#undef BOOST_ATOMIC_INTERLOCKED_IMPORT
#endif // defined(BOOST_USE_WINDOWS_H)
#endif // defined(_MSC_VER)
#endif

View File

@@ -0,0 +1,58 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2012 Hartmut Kaiser
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/config.hpp
*
* This header defines macros for linking with compiled library of Boost.Atomic
*/
#ifndef BOOST_ATOMIC_DETAIL_LINK_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_LINK_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
///////////////////////////////////////////////////////////////////////////////
// Set up dll import/export options
#if (defined(BOOST_ATOMIC_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)) && \
!defined(BOOST_ATOMIC_STATIC_LINK)
#if defined(BOOST_ATOMIC_SOURCE)
#define BOOST_ATOMIC_DECL BOOST_SYMBOL_EXPORT
#define BOOST_ATOMIC_BUILD_DLL
#else
#define BOOST_ATOMIC_DECL BOOST_SYMBOL_IMPORT
#endif
#endif // building a shared library
#ifndef BOOST_ATOMIC_DECL
#define BOOST_ATOMIC_DECL
#endif
///////////////////////////////////////////////////////////////////////////////
// Auto library naming
#if !defined(BOOST_ATOMIC_SOURCE) && !defined(BOOST_ALL_NO_LIB) && \
!defined(BOOST_ATOMIC_NO_LIB)
#define BOOST_LIB_NAME boost_atomic
// tell the auto-link code to select a dll when required:
#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_ATOMIC_DYN_LINK)
#define BOOST_DYN_LINK
#endif
#include <boost/config/auto_link.hpp>
#endif // auto-linking disabled
#endif

View File

@@ -0,0 +1,51 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2011 Helge Bahmann
* Copyright (c) 2013-2014 Andrey Semashev
*/
/*!
* \file atomic/detail/lockpool.hpp
*
* This header contains declaration of the lockpool used to emulate atomic ops.
*/
#ifndef BOOST_ATOMIC_DETAIL_LOCKPOOL_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_LOCKPOOL_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/link.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
struct lockpool
{
class scoped_lock
{
void* m_lock;
public:
explicit BOOST_ATOMIC_DECL scoped_lock(const volatile void* addr) BOOST_NOEXCEPT;
BOOST_ATOMIC_DECL ~scoped_lock() BOOST_NOEXCEPT;
BOOST_DELETED_FUNCTION(scoped_lock(scoped_lock const&))
BOOST_DELETED_FUNCTION(scoped_lock& operator=(scoped_lock const&))
};
static BOOST_ATOMIC_DECL void thread_fence() BOOST_NOEXCEPT;
static BOOST_ATOMIC_DECL void signal_fence() BOOST_NOEXCEPT;
};
} // namespace detail
} // namespace atomics
} // namespace boost
#endif // BOOST_ATOMIC_DETAIL_LOCKPOOL_HPP_INCLUDED_

View File

@@ -0,0 +1,24 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/operations.hpp
*
* This header defines atomic operations, including the emulated version.
*/
#ifndef BOOST_ATOMIC_DETAIL_OPERATIONS_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_OPERATIONS_HPP_INCLUDED_
#include <boost/atomic/detail/operations_lockfree.hpp>
#include <boost/atomic/detail/ops_emulated.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#endif // BOOST_ATOMIC_DETAIL_OPERATIONS_HPP_INCLUDED_

View File

@@ -0,0 +1,35 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/operations_fwd.hpp
*
* This header contains forward declaration of the \c operations template.
*/
#ifndef BOOST_ATOMIC_DETAIL_OPERATIONS_FWD_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_OPERATIONS_FWD_HPP_INCLUDED_
#include <cstddef>
#include <boost/atomic/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
template< std::size_t Size, bool Signed >
struct operations;
} // namespace detail
} // namespace atomics
} // namespace boost
#endif // BOOST_ATOMIC_DETAIL_OPERATIONS_FWD_HPP_INCLUDED_

View File

@@ -0,0 +1,30 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/operations_lockfree.hpp
*
* This header defines lockfree atomic operations.
*/
#ifndef BOOST_ATOMIC_DETAIL_OPERATIONS_LOCKFREE_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_OPERATIONS_LOCKFREE_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/platform.hpp>
#if !defined(BOOST_ATOMIC_EMULATED)
#include BOOST_ATOMIC_DETAIL_HEADER(boost/atomic/detail/ops_)
#else
#include <boost/atomic/detail/operations_fwd.hpp>
#endif
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#endif // BOOST_ATOMIC_DETAIL_OPERATIONS_LOCKFREE_HPP_INCLUDED_

View File

@@ -0,0 +1,105 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/ops_cas_based.hpp
*
* This header contains CAS-based implementation of the \c operations template.
*/
#ifndef BOOST_ATOMIC_DETAIL_OPS_CAS_BASED_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_OPS_CAS_BASED_HPP_INCLUDED_
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
template< typename Base >
struct cas_based_exchange :
public Base
{
typedef typename Base::storage_type storage_type;
static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type old_val;
atomics::detail::non_atomic_load(storage, old_val);
while (!Base::compare_exchange_weak(storage, old_val, v, order, memory_order_relaxed)) {}
return old_val;
}
};
template< typename Base >
struct cas_based_operations :
public Base
{
typedef typename Base::storage_type storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type old_val;
atomics::detail::non_atomic_load(storage, old_val);
while (!Base::compare_exchange_weak(storage, old_val, old_val + v, order, memory_order_relaxed)) {}
return old_val;
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type old_val;
atomics::detail::non_atomic_load(storage, old_val);
while (!Base::compare_exchange_weak(storage, old_val, old_val - v, order, memory_order_relaxed)) {}
return old_val;
}
static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type old_val;
atomics::detail::non_atomic_load(storage, old_val);
while (!Base::compare_exchange_weak(storage, old_val, old_val & v, order, memory_order_relaxed)) {}
return old_val;
}
static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type old_val;
atomics::detail::non_atomic_load(storage, old_val);
while (!Base::compare_exchange_weak(storage, old_val, old_val | v, order, memory_order_relaxed)) {}
return old_val;
}
static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type old_val;
atomics::detail::non_atomic_load(storage, old_val);
while (!Base::compare_exchange_weak(storage, old_val, old_val ^ v, order, memory_order_relaxed)) {}
return old_val;
}
static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
return !!Base::exchange(storage, (storage_type)1, order);
}
static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
Base::store(storage, (storage_type)0, order);
}
};
} // namespace detail
} // namespace atomics
} // namespace boost
#endif // BOOST_ATOMIC_DETAIL_OPS_CAS_BASED_HPP_INCLUDED_

View File

@@ -0,0 +1,161 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/ops_emulated.hpp
*
* This header contains lockpool-based implementation of the \c operations template.
*/
#ifndef BOOST_ATOMIC_DETAIL_OPS_EMULATED_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_OPS_EMULATED_HPP_INCLUDED_
#include <cstddef>
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/detail/operations_fwd.hpp>
#include <boost/atomic/detail/lockpool.hpp>
#include <boost/atomic/capabilities.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
template< typename T >
struct emulated_operations
{
typedef T storage_type;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
lockpool::scoped_lock lock(&storage);
const_cast< storage_type& >(storage) = v;
}
static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order) BOOST_NOEXCEPT
{
lockpool::scoped_lock lock(&storage);
return const_cast< storage_type const& >(storage);
}
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
storage_type& s = const_cast< storage_type& >(storage);
lockpool::scoped_lock lock(&storage);
storage_type old_val = s;
s += v;
return old_val;
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
storage_type& s = const_cast< storage_type& >(storage);
lockpool::scoped_lock lock(&storage);
storage_type old_val = s;
s -= v;
return old_val;
}
static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
storage_type& s = const_cast< storage_type& >(storage);
lockpool::scoped_lock lock(&storage);
storage_type old_val = s;
s = v;
return old_val;
}
static BOOST_FORCEINLINE bool compare_exchange_strong(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
{
storage_type& s = const_cast< storage_type& >(storage);
lockpool::scoped_lock lock(&storage);
storage_type old_val = s;
const bool res = old_val == expected;
if (res)
s = desired;
expected = old_val;
return res;
}
static BOOST_FORCEINLINE bool compare_exchange_weak(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
{
// Note: This function is the exact copy of compare_exchange_strong. The reason we're not just forwarding the call
// is that MSVC-12 ICEs in this case.
storage_type& s = const_cast< storage_type& >(storage);
lockpool::scoped_lock lock(&storage);
storage_type old_val = s;
const bool res = old_val == expected;
if (res)
s = desired;
expected = old_val;
return res;
}
static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
storage_type& s = const_cast< storage_type& >(storage);
lockpool::scoped_lock lock(&storage);
storage_type old_val = s;
s &= v;
return old_val;
}
static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
storage_type& s = const_cast< storage_type& >(storage);
lockpool::scoped_lock lock(&storage);
storage_type old_val = s;
s |= v;
return old_val;
}
static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
storage_type& s = const_cast< storage_type& >(storage);
lockpool::scoped_lock lock(&storage);
storage_type old_val = s;
s ^= v;
return old_val;
}
static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
return !!exchange(storage, (storage_type)1, order);
}
static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
store(storage, (storage_type)0, order);
}
static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
{
return false;
}
};
template< std::size_t Size, bool Signed >
struct operations :
public emulated_operations< typename make_storage_type< Size, Signed >::type >
{
typedef typename make_storage_type< Size, Signed >::aligned aligned_storage_type;
};
} // namespace detail
} // namespace atomics
} // namespace boost
#endif // BOOST_ATOMIC_DETAIL_OPS_EMULATED_HPP_INCLUDED_

View File

@@ -0,0 +1,68 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/ops_extending_cas_based.hpp
*
* This header contains a boilerplate of the \c operations template implementation that requires sign/zero extension in arithmetic operations.
*/
#ifndef BOOST_ATOMIC_DETAIL_OPS_EXTENDING_CAS_BASED_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_OPS_EXTENDING_CAS_BASED_HPP_INCLUDED_
#include <cstddef>
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
template< typename Base, std::size_t Size, bool Signed >
struct extending_cas_based_operations :
public Base
{
typedef typename Base::storage_type storage_type;
typedef typename make_storage_type< Size, Signed >::type emulated_storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type old_val;
atomics::detail::non_atomic_load(storage, old_val);
emulated_storage_type new_val;
do
{
new_val = static_cast< emulated_storage_type >(old_val) + static_cast< emulated_storage_type >(v);
}
while (!Base::compare_exchange_weak(storage, old_val, static_cast< storage_type >(new_val), order, memory_order_relaxed));
return old_val;
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type old_val;
atomics::detail::non_atomic_load(storage, old_val);
emulated_storage_type new_val;
do
{
new_val = static_cast< emulated_storage_type >(old_val) - static_cast< emulated_storage_type >(v);
}
while (!Base::compare_exchange_weak(storage, old_val, static_cast< storage_type >(new_val), order, memory_order_relaxed));
return old_val;
}
};
} // namespace detail
} // namespace atomics
} // namespace boost
#endif // BOOST_ATOMIC_DETAIL_OPS_EXTENDING_CAS_BASED_HPP_INCLUDED_

View File

@@ -0,0 +1,876 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2009 Helge Bahmann
* Copyright (c) 2013 Tim Blechmann
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/ops_gcc_alpha.hpp
*
* This header contains implementation of the \c operations template.
*/
#ifndef BOOST_ATOMIC_DETAIL_OPS_GCC_ALPHA_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_OPS_GCC_ALPHA_HPP_INCLUDED_
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/detail/operations_fwd.hpp>
#include <boost/atomic/capabilities.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
/*
Refer to http://h71000.www7.hp.com/doc/82final/5601/5601pro_004.html
(HP OpenVMS systems documentation) and the Alpha Architecture Reference Manual.
*/
/*
NB: The most natural thing would be to write the increment/decrement
operators along the following lines:
__asm__ __volatile__
(
"1: ldl_l %0,%1 \n"
"addl %0,1,%0 \n"
"stl_c %0,%1 \n"
"beq %0,1b\n"
: "=&b" (tmp)
: "m" (value)
: "cc"
);
However according to the comments on the HP website and matching
comments in the Linux kernel sources this defies branch prediction,
as the cpu assumes that backward branches are always taken; so
instead copy the trick from the Linux kernel, introduce a forward
branch and back again.
I have, however, had a hard time measuring the difference between
the two versions in microbenchmarks -- I am leaving it in nevertheless
as it apparently does not hurt either.
*/
struct gcc_alpha_operations_base
{
static BOOST_FORCEINLINE void fence_before(memory_order order) BOOST_NOEXCEPT
{
if ((order & memory_order_release) != 0)
__asm__ __volatile__ ("mb" ::: "memory");
}
static BOOST_FORCEINLINE void fence_after(memory_order order) BOOST_NOEXCEPT
{
if ((order & (memory_order_consume | memory_order_acquire)) != 0)
__asm__ __volatile__ ("mb" ::: "memory");
}
static BOOST_FORCEINLINE void fence_after_store(memory_order order) BOOST_NOEXCEPT
{
if (order == memory_order_seq_cst)
__asm__ __volatile__ ("mb" ::: "memory");
}
};
template< bool Signed >
struct operations< 4u, Signed > :
public gcc_alpha_operations_base
{
typedef typename make_storage_type< 4u, Signed >::type storage_type;
typedef typename make_storage_type< 4u, Signed >::aligned aligned_storage_type;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
fence_before(order);
storage = v;
fence_after_store(order);
}
static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
{
storage_type v = storage;
fence_after(order);
return v;
}
static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, tmp;
fence_before(order);
__asm__ __volatile__
(
"1:\n"
"mov %3, %1\n"
"ldl_l %0, %2\n"
"stl_c %1, %2\n"
"beq %1, 2f\n"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
: "=&r" (original), // %0
"=&r" (tmp) // %1
: "m" (storage), // %2
"r" (v) // %3
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE bool compare_exchange_weak(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
fence_before(success_order);
int success;
storage_type current;
__asm__ __volatile__
(
"1:\n"
"ldl_l %2, %4\n" // current = *(&storage)
"cmpeq %2, %0, %3\n" // success = current == expected
"mov %2, %0\n" // expected = current
"beq %3, 2f\n" // if (success == 0) goto end
"stl_c %1, %4\n" // storage = desired; desired = store succeeded
"mov %1, %3\n" // success = desired
"2:\n"
: "+&r" (expected), // %0
"+&r" (desired), // %1
"=&r" (current), // %2
"=&r" (success) // %3
: "m" (storage) // %4
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
if (success)
fence_after(success_order);
else
fence_after(failure_order);
return !!success;
}
static BOOST_FORCEINLINE bool compare_exchange_strong(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
int success;
storage_type current, tmp;
fence_before(success_order);
__asm__ __volatile__
(
"1:\n"
"mov %5, %1\n" // tmp = desired
"ldl_l %2, %4\n" // current = *(&storage)
"cmpeq %2, %0, %3\n" // success = current == expected
"mov %2, %0\n" // expected = current
"beq %3, 2f\n" // if (success == 0) goto end
"stl_c %1, %4\n" // storage = tmp; tmp = store succeeded
"beq %1, 3f\n" // if (tmp == 0) goto retry
"mov %1, %3\n" // success = tmp
"2:\n"
".subsection 2\n"
"3: br 1b\n"
".previous\n"
: "+&r" (expected), // %0
"=&r" (tmp), // %1
"=&r" (current), // %2
"=&r" (success) // %3
: "m" (storage), // %4
"r" (desired) // %5
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
if (success)
fence_after(success_order);
else
fence_after(failure_order);
return !!success;
}
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, modified;
fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldl_l %0, %2\n"
"addl %0, %3, %1\n"
"stl_c %1, %2\n"
"beq %1, 2f\n"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
: "=&r" (original), // %0
"=&r" (modified) // %1
: "m" (storage), // %2
"r" (v) // %3
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, modified;
fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldl_l %0, %2\n"
"subl %0, %3, %1\n"
"stl_c %1, %2\n"
"beq %1, 2f\n"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
: "=&r" (original), // %0
"=&r" (modified) // %1
: "m" (storage), // %2
"r" (v) // %3
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, modified;
fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldl_l %0, %2\n"
"and %0, %3, %1\n"
"stl_c %1, %2\n"
"beq %1, 2f\n"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
: "=&r" (original), // %0
"=&r" (modified) // %1
: "m" (storage), // %2
"r" (v) // %3
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, modified;
fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldl_l %0, %2\n"
"bis %0, %3, %1\n"
"stl_c %1, %2\n"
"beq %1, 2f\n"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
: "=&r" (original), // %0
"=&r" (modified) // %1
: "m" (storage), // %2
"r" (v) // %3
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, modified;
fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldl_l %0, %2\n"
"xor %0, %3, %1\n"
"stl_c %1, %2\n"
"beq %1, 2f\n"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
: "=&r" (original), // %0
"=&r" (modified) // %1
: "m" (storage), // %2
"r" (v) // %3
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
return !!exchange(storage, (storage_type)1, order);
}
static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
store(storage, 0, order);
}
static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
{
return true;
}
};
template< >
struct operations< 1u, false > :
public operations< 4u, false >
{
typedef operations< 4u, false > base_type;
typedef base_type::storage_type storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, modified;
fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldl_l %0, %2\n"
"addl %0, %3, %1\n"
"zapnot %1, #1, %1\n"
"stl_c %1, %2\n"
"beq %1, 2f\n"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
: "=&r" (original), // %0
"=&r" (modified) // %1
: "m" (storage), // %2
"r" (v) // %3
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, modified;
fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldl_l %0, %2\n"
"subl %0, %3, %1\n"
"zapnot %1, #1, %1\n"
"stl_c %1, %2\n"
"beq %1, 2f\n"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
: "=&r" (original), // %0
"=&r" (modified) // %1
: "m" (storage), // %2
"r" (v) // %3
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
};
template< >
struct operations< 1u, true > :
public operations< 4u, true >
{
typedef operations< 4u, true > base_type;
typedef base_type::storage_type storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, modified;
fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldl_l %0, %2\n"
"addl %0, %3, %1\n"
"sextb %1, %1\n"
"stl_c %1, %2\n"
"beq %1, 2f\n"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
: "=&r" (original), // %0
"=&r" (modified) // %1
: "m" (storage), // %2
"r" (v) // %3
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, modified;
fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldl_l %0, %2\n"
"subl %0, %3, %1\n"
"sextb %1, %1\n"
"stl_c %1, %2\n"
"beq %1, 2f\n"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
: "=&r" (original), // %0
"=&r" (modified) // %1
: "m" (storage), // %2
"r" (v) // %3
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
};
template< >
struct operations< 2u, false > :
public operations< 4u, false >
{
typedef operations< 4u, false > base_type;
typedef base_type::storage_type storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, modified;
fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldl_l %0, %2\n"
"addl %0, %3, %1\n"
"zapnot %1, #3, %1\n"
"stl_c %1, %2\n"
"beq %1, 2f\n"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
: "=&r" (original), // %0
"=&r" (modified) // %1
: "m" (storage), // %2
"r" (v) // %3
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, modified;
fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldl_l %0, %2\n"
"subl %0, %3, %1\n"
"zapnot %1, #3, %1\n"
"stl_c %1, %2\n"
"beq %1, 2f\n"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
: "=&r" (original), // %0
"=&r" (modified) // %1
: "m" (storage), // %2
"r" (v) // %3
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
};
template< >
struct operations< 2u, true > :
public operations< 4u, true >
{
typedef operations< 4u, true > base_type;
typedef base_type::storage_type storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, modified;
fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldl_l %0, %2\n"
"addl %0, %3, %1\n"
"sextw %1, %1\n"
"stl_c %1, %2\n"
"beq %1, 2f\n"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
: "=&r" (original), // %0
"=&r" (modified) // %1
: "m" (storage), // %2
"r" (v) // %3
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, modified;
fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldl_l %0, %2\n"
"subl %0, %3, %1\n"
"sextw %1, %1\n"
"stl_c %1, %2\n"
"beq %1, 2f\n"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
: "=&r" (original), // %0
"=&r" (modified) // %1
: "m" (storage), // %2
"r" (v) // %3
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
};
template< bool Signed >
struct operations< 8u, Signed > :
public gcc_alpha_operations_base
{
typedef typename make_storage_type< 8u, Signed >::type storage_type;
typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
fence_before(order);
storage = v;
fence_after_store(order);
}
static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
{
storage_type v = storage;
fence_after(order);
return v;
}
static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, tmp;
fence_before(order);
__asm__ __volatile__
(
"1:\n"
"mov %3, %1\n"
"ldq_l %0, %2\n"
"stq_c %1, %2\n"
"beq %1, 2f\n"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
: "=&r" (original), // %0
"=&r" (tmp) // %1
: "m" (storage), // %2
"r" (v) // %3
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE bool compare_exchange_weak(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
fence_before(success_order);
int success;
storage_type current;
__asm__ __volatile__
(
"1:\n"
"ldq_l %2, %4\n" // current = *(&storage)
"cmpeq %2, %0, %3\n" // success = current == expected
"mov %2, %0\n" // expected = current
"beq %3, 2f\n" // if (success == 0) goto end
"stq_c %1, %4\n" // storage = desired; desired = store succeeded
"mov %1, %3\n" // success = desired
"2:\n"
: "+&r" (expected), // %0
"+&r" (desired), // %1
"=&r" (current), // %2
"=&r" (success) // %3
: "m" (storage) // %4
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
if (success)
fence_after(success_order);
else
fence_after(failure_order);
return !!success;
}
static BOOST_FORCEINLINE bool compare_exchange_strong(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
int success;
storage_type current, tmp;
fence_before(success_order);
__asm__ __volatile__
(
"1:\n"
"mov %5, %1\n" // tmp = desired
"ldq_l %2, %4\n" // current = *(&storage)
"cmpeq %2, %0, %3\n" // success = current == expected
"mov %2, %0\n" // expected = current
"beq %3, 2f\n" // if (success == 0) goto end
"stq_c %1, %4\n" // storage = tmp; tmp = store succeeded
"beq %1, 3f\n" // if (tmp == 0) goto retry
"mov %1, %3\n" // success = tmp
"2:\n"
".subsection 2\n"
"3: br 1b\n"
".previous\n"
: "+&r" (expected), // %0
"=&r" (tmp), // %1
"=&r" (current), // %2
"=&r" (success) // %3
: "m" (storage), // %4
"r" (desired) // %5
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
if (success)
fence_after(success_order);
else
fence_after(failure_order);
return !!success;
}
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, modified;
fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldq_l %0, %2\n"
"addq %0, %3, %1\n"
"stq_c %1, %2\n"
"beq %1, 2f\n"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
: "=&r" (original), // %0
"=&r" (modified) // %1
: "m" (storage), // %2
"r" (v) // %3
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, modified;
fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldq_l %0, %2\n"
"subq %0, %3, %1\n"
"stq_c %1, %2\n"
"beq %1, 2f\n"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
: "=&r" (original), // %0
"=&r" (modified) // %1
: "m" (storage), // %2
"r" (v) // %3
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, modified;
fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldq_l %0, %2\n"
"and %0, %3, %1\n"
"stq_c %1, %2\n"
"beq %1, 2f\n"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
: "=&r" (original), // %0
"=&r" (modified) // %1
: "m" (storage), // %2
"r" (v) // %3
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, modified;
fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldq_l %0, %2\n"
"bis %0, %3, %1\n"
"stq_c %1, %2\n"
"beq %1, 2f\n"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
: "=&r" (original), // %0
"=&r" (modified) // %1
: "m" (storage), // %2
"r" (v) // %3
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, modified;
fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldq_l %0, %2\n"
"xor %0, %3, %1\n"
"stq_c %1, %2\n"
"beq %1, 2f\n"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
: "=&r" (original), // %0
"=&r" (modified) // %1
: "m" (storage), // %2
"r" (v) // %3
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
return !!exchange(storage, (storage_type)1, order);
}
static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
store(storage, 0, order);
}
static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
{
return true;
}
};
BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
__asm__ __volatile__ ("mb" ::: "memory");
}
BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
__asm__ __volatile__ ("" ::: "memory");
}
} // namespace detail
} // namespace atomics
} // namespace boost
#endif // BOOST_ATOMIC_DETAIL_OPS_GCC_ALPHA_HPP_INCLUDED_

View File

@@ -0,0 +1,973 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2009 Helge Bahmann
* Copyright (c) 2013 Tim Blechmann
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/ops_gcc_arm.hpp
*
* This header contains implementation of the \c operations template.
*/
#ifndef BOOST_ATOMIC_DETAIL_OPS_GCC_ARM_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_OPS_GCC_ARM_HPP_INCLUDED_
#include <boost/cstdint.hpp>
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/detail/operations_fwd.hpp>
#include <boost/atomic/detail/ops_extending_cas_based.hpp>
#include <boost/atomic/capabilities.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
// From the ARM Architecture Reference Manual for architecture v6:
//
// LDREX{<cond>} <Rd>, [<Rn>]
// <Rd> Specifies the destination register for the memory word addressed by <Rd>
// <Rn> Specifies the register containing the address.
//
// STREX{<cond>} <Rd>, <Rm>, [<Rn>]
// <Rd> Specifies the destination register for the returned status value.
// 0 if the operation updates memory
// 1 if the operation fails to update memory
// <Rm> Specifies the register containing the word to be stored to memory.
// <Rn> Specifies the register containing the address.
// Rd must not be the same register as Rm or Rn.
//
// ARM v7 is like ARM v6 plus:
// There are half-word and byte versions of the LDREX and STREX instructions,
// LDREXH, LDREXB, STREXH and STREXB.
// There are also double-word versions, LDREXD and STREXD.
// (Actually it looks like these are available from version 6k onwards.)
// FIXME these are not yet used; should be mostly a matter of copy-and-paste.
// I think you can supply an immediate offset to the address.
//
// A memory barrier is effected using a "co-processor 15" instruction,
// though a separate assembler mnemonic is available for it in v7.
//
// "Thumb 1" is a subset of the ARM instruction set that uses a 16-bit encoding. It
// doesn't include all instructions and in particular it doesn't include the co-processor
// instruction used for the memory barrier or the load-locked/store-conditional
// instructions. So, if we're compiling in "Thumb 1" mode, we need to wrap all of our
// asm blocks with code to temporarily change to ARM mode.
//
// You can only change between ARM and Thumb modes when branching using the bx instruction.
// bx takes an address specified in a register. The least significant bit of the address
// indicates the mode, so 1 is added to indicate that the destination code is Thumb.
// A temporary register is needed for the address and is passed as an argument to these
// macros. It must be one of the "low" registers accessible to Thumb code, specified
// using the "l" attribute in the asm statement.
//
// Architecture v7 introduces "Thumb 2", which does include (almost?) all of the ARM
// instruction set. (Actually, there was an extension of v6 called v6T2 which supported
// "Thumb 2" mode, but its architecture manual is no longer available, referring to v7.)
// So in v7 we don't need to change to ARM mode; we can write "universal
// assembler" which will assemble to Thumb 2 or ARM code as appropriate. The only thing
// we need to do to make this "universal" assembler mode work is to insert "IT" instructions
// to annotate the conditional instructions. These are ignored in other modes (e.g. v6),
// so they can always be present.
// A note about memory_order_consume. Technically, this architecture allows to avoid
// unnecessary memory barrier after consume load since it supports data dependency ordering.
// However, some compiler optimizations may break a seemingly valid code relying on data
// dependency tracking by injecting bogus branches to aid out of order execution.
// This may happen not only in Boost.Atomic code but also in user's code, which we have no
// control of. See this thread: http://lists.boost.org/Archives/boost/2014/06/213890.php.
// For this reason we promote memory_order_consume to memory_order_acquire.
#if defined(__thumb__) && !defined(__thumb2__)
#define BOOST_ATOMIC_DETAIL_ARM_ASM_START(TMPREG) "adr " #TMPREG ", 8f\n" "bx " #TMPREG "\n" ".arm\n" ".align 4\n" "8:\n"
#define BOOST_ATOMIC_DETAIL_ARM_ASM_END(TMPREG) "adr " #TMPREG ", 9f + 1\n" "bx " #TMPREG "\n" ".thumb\n" ".align 2\n" "9:\n"
#define BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(var) "=&l" (var)
#else
// The tmpreg may be wasted in this case, which is non-optimal.
#define BOOST_ATOMIC_DETAIL_ARM_ASM_START(TMPREG)
#define BOOST_ATOMIC_DETAIL_ARM_ASM_END(TMPREG)
#define BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(var) "=&r" (var)
#endif
struct gcc_arm_operations_base
{
static BOOST_FORCEINLINE void fence_before(memory_order order) BOOST_NOEXCEPT
{
if ((order & memory_order_release) != 0)
hardware_full_fence();
}
static BOOST_FORCEINLINE void fence_after(memory_order order) BOOST_NOEXCEPT
{
if ((order & (memory_order_consume | memory_order_acquire)) != 0)
hardware_full_fence();
}
static BOOST_FORCEINLINE void fence_after_store(memory_order order) BOOST_NOEXCEPT
{
if (order == memory_order_seq_cst)
hardware_full_fence();
}
static BOOST_FORCEINLINE void hardware_full_fence() BOOST_NOEXCEPT
{
#if defined(BOOST_ATOMIC_DETAIL_ARM_HAS_DMB)
// Older binutils (supposedly, older than 2.21.1) didn't support symbolic or numeric arguments of the "dmb" instruction such as "ish" or "#11".
// As a workaround we have to inject encoded bytes of the instruction. There are two encodings for the instruction: ARM and Thumb. See ARM Architecture Reference Manual, A8.8.43.
// Since we cannot detect binutils version at compile time, we'll have to always use this hack.
__asm__ __volatile__
(
#if defined(__thumb2__)
".short 0xF3BF, 0x8F5B\n" // dmb ish
#else
".word 0xF57FF05B\n" // dmb ish
#endif
:
:
: "memory"
);
#else
int tmp;
__asm__ __volatile__
(
BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0)
"mcr\tp15, 0, r0, c7, c10, 5\n"
BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0)
: "=&l" (tmp)
:
: "memory"
);
#endif
}
};
template< bool Signed >
struct operations< 4u, Signed > :
public gcc_arm_operations_base
{
typedef typename make_storage_type< 4u, Signed >::type storage_type;
typedef typename make_storage_type< 4u, Signed >::aligned aligned_storage_type;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
fence_before(order);
storage = v;
fence_after_store(order);
}
static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
{
storage_type v = storage;
fence_after(order);
return v;
}
static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original;
fence_before(order);
uint32_t tmp;
__asm__ __volatile__
(
BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
"1:\n"
"ldrex %[original], %[storage]\n" // load the original value
"strex %[tmp], %[value], %[storage]\n" // store the replacement, tmp = store failed
"teq %[tmp], #0\n" // check if store succeeded
"bne 1b\n"
BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
: [tmp] "=&l" (tmp), [original] "=&r" (original), [storage] "+Q" (storage)
: [value] "r" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE bool compare_exchange_weak(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
fence_before(success_order);
uint32_t success;
uint32_t tmp;
storage_type original;
__asm__ __volatile__
(
BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
"mov %[success], #0\n" // success = 0
"ldrex %[original], %[storage]\n" // original = *(&storage)
"cmp %[original], %[expected]\n" // flags = original==expected
"itt eq\n" // [hint that the following 2 instructions are conditional on flags.equal]
"strexeq %[success], %[desired], %[storage]\n" // if (flags.equal) *(&storage) = desired, success = store failed
"eoreq %[success], %[success], #1\n" // if (flags.equal) success ^= 1 (i.e. make it 1 if store succeeded)
BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
: [original] "=&r" (original), // %0
[success] "=&r" (success), // %1
[tmp] "=&l" (tmp), // %2
[storage] "+Q" (storage) // %3
: [expected] "r" (expected), // %4
[desired] "r" (desired) // %5
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
if (success)
fence_after(success_order);
else
fence_after(failure_order);
expected = original;
return !!success;
}
static BOOST_FORCEINLINE bool compare_exchange_strong(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
fence_before(success_order);
uint32_t success;
uint32_t tmp;
storage_type original;
__asm__ __volatile__
(
BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
"mov %[success], #0\n" // success = 0
"1:\n"
"ldrex %[original], %[storage]\n" // original = *(&storage)
"cmp %[original], %[expected]\n" // flags = original==expected
"bne 2f\n" // if (!flags.equal) goto end
"strex %[success], %[desired], %[storage]\n" // *(&storage) = desired, success = store failed
"eors %[success], %[success], #1\n" // success ^= 1 (i.e. make it 1 if store succeeded); flags.equal = success == 0
"beq 1b\n" // if (flags.equal) goto retry
"2:\n"
BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
: [original] "=&r" (original), // %0
[success] "=&r" (success), // %1
[tmp] "=&l" (tmp), // %2
[storage] "+Q" (storage) // %3
: [expected] "r" (expected), // %4
[desired] "r" (desired) // %5
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
if (success)
fence_after(success_order);
else
fence_after(failure_order);
expected = original;
return !!success;
}
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
fence_before(order);
uint32_t tmp;
storage_type original, result;
__asm__ __volatile__
(
BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
"1:\n"
"ldrex %[original], %[storage]\n" // original = *(&storage)
"add %[result], %[original], %[value]\n" // result = original + value
"strex %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
"teq %[tmp], #0\n" // flags = tmp==0
"bne 1b\n" // if (!flags.equal) goto retry
BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
: [original] "=&r" (original), // %0
[result] "=&r" (result), // %1
[tmp] "=&l" (tmp), // %2
[storage] "+Q" (storage) // %3
: [value] "r" (v) // %4
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
fence_before(order);
uint32_t tmp;
storage_type original, result;
__asm__ __volatile__
(
BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
"1:\n"
"ldrex %[original], %[storage]\n" // original = *(&storage)
"sub %[result], %[original], %[value]\n" // result = original - value
"strex %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
"teq %[tmp], #0\n" // flags = tmp==0
"bne 1b\n" // if (!flags.equal) goto retry
BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
: [original] "=&r" (original), // %0
[result] "=&r" (result), // %1
[tmp] "=&l" (tmp), // %2
[storage] "+Q" (storage) // %3
: [value] "r" (v) // %4
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
fence_before(order);
uint32_t tmp;
storage_type original, result;
__asm__ __volatile__
(
BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
"1:\n"
"ldrex %[original], %[storage]\n" // original = *(&storage)
"and %[result], %[original], %[value]\n" // result = original & value
"strex %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
"teq %[tmp], #0\n" // flags = tmp==0
"bne 1b\n" // if (!flags.equal) goto retry
BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
: [original] "=&r" (original), // %0
[result] "=&r" (result), // %1
[tmp] "=&l" (tmp), // %2
[storage] "+Q" (storage) // %3
: [value] "r" (v) // %4
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
fence_before(order);
uint32_t tmp;
storage_type original, result;
__asm__ __volatile__
(
BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
"1:\n"
"ldrex %[original], %[storage]\n" // original = *(&storage)
"orr %[result], %[original], %[value]\n" // result = original | value
"strex %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
"teq %[tmp], #0\n" // flags = tmp==0
"bne 1b\n" // if (!flags.equal) goto retry
BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
: [original] "=&r" (original), // %0
[result] "=&r" (result), // %1
[tmp] "=&l" (tmp), // %2
[storage] "+Q" (storage) // %3
: [value] "r" (v) // %4
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
fence_before(order);
uint32_t tmp;
storage_type original, result;
__asm__ __volatile__
(
BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
"1:\n"
"ldrex %[original], %[storage]\n" // original = *(&storage)
"eor %[result], %[original], %[value]\n" // result = original ^ value
"strex %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
"teq %[tmp], #0\n" // flags = tmp==0
"bne 1b\n" // if (!flags.equal) goto retry
BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
: [original] "=&r" (original), // %0
[result] "=&r" (result), // %1
[tmp] "=&l" (tmp), // %2
[storage] "+Q" (storage) // %3
: [value] "r" (v) // %4
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
return !!exchange(storage, (storage_type)1, order);
}
static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
store(storage, 0, order);
}
static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
{
return true;
}
};
template< >
struct operations< 1u, false > :
public operations< 4u, false >
{
typedef operations< 4u, false > base_type;
typedef base_type::storage_type storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
fence_before(order);
uint32_t tmp;
storage_type original, result;
__asm__ __volatile__
(
BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
"1:\n"
"ldrex %[original], %[storage]\n" // original = *(&storage)
"add %[result], %[original], %[value]\n" // result = original + value
"uxtb %[result], %[result]\n" // zero extend result from 8 to 32 bits
"strex %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
"teq %[tmp], #0\n" // flags = tmp==0
"bne 1b\n" // if (!flags.equal) goto retry
BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
: [original] "=&r" (original), // %0
[result] "=&r" (result), // %1
[tmp] "=&l" (tmp), // %2
[storage] "+Q" (storage) // %3
: [value] "r" (v) // %4
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
fence_before(order);
uint32_t tmp;
storage_type original, result;
__asm__ __volatile__
(
BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
"1:\n"
"ldrex %[original], %[storage]\n" // original = *(&storage)
"sub %[result], %[original], %[value]\n" // result = original - value
"uxtb %[result], %[result]\n" // zero extend result from 8 to 32 bits
"strex %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
"teq %[tmp], #0\n" // flags = tmp==0
"bne 1b\n" // if (!flags.equal) goto retry
BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
: [original] "=&r" (original), // %0
[result] "=&r" (result), // %1
[tmp] "=&l" (tmp), // %2
[storage] "+Q" (storage) // %3
: [value] "r" (v) // %4
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
};
template< >
struct operations< 1u, true > :
public operations< 4u, true >
{
typedef operations< 4u, true > base_type;
typedef base_type::storage_type storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
fence_before(order);
uint32_t tmp;
storage_type original, result;
__asm__ __volatile__
(
BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
"1:\n"
"ldrex %[original], %[storage]\n" // original = *(&storage)
"add %[result], %[original], %[value]\n" // result = original + value
"sxtb %[result], %[result]\n" // sign extend result from 8 to 32 bits
"strex %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
"teq %[tmp], #0\n" // flags = tmp==0
"bne 1b\n" // if (!flags.equal) goto retry
BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
: [original] "=&r" (original), // %0
[result] "=&r" (result), // %1
[tmp] "=&l" (tmp), // %2
[storage] "+Q" (storage) // %3
: [value] "r" (v) // %4
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
fence_before(order);
uint32_t tmp;
storage_type original, result;
__asm__ __volatile__
(
BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
"1:\n"
"ldrex %[original], %[storage]\n" // original = *(&storage)
"sub %[result], %[original], %[value]\n" // result = original - value
"sxtb %[result], %[result]\n" // sign extend result from 8 to 32 bits
"strex %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
"teq %[tmp], #0\n" // flags = tmp==0
"bne 1b\n" // if (!flags.equal) goto retry
BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
: [original] "=&r" (original), // %0
[result] "=&r" (result), // %1
[tmp] "=&l" (tmp), // %2
[storage] "+Q" (storage) // %3
: [value] "r" (v) // %4
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
};
template< >
struct operations< 2u, false > :
public operations< 4u, false >
{
typedef operations< 4u, false > base_type;
typedef base_type::storage_type storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
fence_before(order);
uint32_t tmp;
storage_type original, result;
__asm__ __volatile__
(
BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
"1:\n"
"ldrex %[original], %[storage]\n" // original = *(&storage)
"add %[result], %[original], %[value]\n" // result = original + value
"uxth %[result], %[result]\n" // zero extend result from 16 to 32 bits
"strex %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
"teq %[tmp], #0\n" // flags = tmp==0
"bne 1b\n" // if (!flags.equal) goto retry
BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
: [original] "=&r" (original), // %0
[result] "=&r" (result), // %1
[tmp] "=&l" (tmp), // %2
[storage] "+Q" (storage) // %3
: [value] "r" (v) // %4
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
fence_before(order);
uint32_t tmp;
storage_type original, result;
__asm__ __volatile__
(
BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
"1:\n"
"ldrex %[original], %[storage]\n" // original = *(&storage)
"sub %[result], %[original], %[value]\n" // result = original - value
"uxth %[result], %[result]\n" // zero extend result from 16 to 32 bits
"strex %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
"teq %[tmp], #0\n" // flags = tmp==0
"bne 1b\n" // if (!flags.equal) goto retry
BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
: [original] "=&r" (original), // %0
[result] "=&r" (result), // %1
[tmp] "=&l" (tmp), // %2
[storage] "+Q" (storage) // %3
: [value] "r" (v) // %4
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
};
template< >
struct operations< 2u, true > :
public operations< 4u, true >
{
typedef operations< 4u, true > base_type;
typedef base_type::storage_type storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
fence_before(order);
uint32_t tmp;
storage_type original, result;
__asm__ __volatile__
(
BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
"1:\n"
"ldrex %[original], %[storage]\n" // original = *(&storage)
"add %[result], %[original], %[value]\n" // result = original + value
"sxth %[result], %[result]\n" // sign extend result from 16 to 32 bits
"strex %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
"teq %[tmp], #0\n" // flags = tmp==0
"bne 1b\n" // if (!flags.equal) goto retry
BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
: [original] "=&r" (original), // %0
[result] "=&r" (result), // %1
[tmp] "=&l" (tmp), // %2
[storage] "+Q" (storage) // %3
: [value] "r" (v) // %4
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
fence_before(order);
uint32_t tmp;
storage_type original, result;
__asm__ __volatile__
(
BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp])
"1:\n"
"ldrex %[original], %[storage]\n" // original = *(&storage)
"sub %[result], %[original], %[value]\n" // result = original - value
"sxth %[result], %[result]\n" // sign extend result from 16 to 32 bits
"strex %[tmp], %[result], %[storage]\n" // *(&storage) = result, tmp = store failed
"teq %[tmp], #0\n" // flags = tmp==0
"bne 1b\n" // if (!flags.equal) goto retry
BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp])
: [original] "=&r" (original), // %0
[result] "=&r" (result), // %1
[tmp] "=&l" (tmp), // %2
[storage] "+Q" (storage) // %3
: [value] "r" (v) // %4
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
};
#if defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXD_STREXD)
// Unlike 32-bit operations, for 64-bit loads and stores we must use ldrexd/strexd.
// Any other instructions result in a non-atomic sequence of 32-bit accesses.
// See "ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition",
// Section A3.5.3 "Atomicity in the ARM architecture".
// In the asm blocks below we have to use 32-bit register pairs to compose 64-bit values.
// In order to pass the 64-bit operands to/from asm blocks, we use undocumented gcc feature:
// the lower half (Rt) of the operand is accessible normally, via the numbered placeholder (e.g. %0),
// and the upper half (Rt2) - via the same placeholder with an 'H' after the '%' sign (e.g. %H0).
// See: http://hardwarebug.org/2010/07/06/arm-inline-asm-secrets/
template< bool Signed >
struct operations< 8u, Signed > :
public gcc_arm_operations_base
{
typedef typename make_storage_type< 8u, Signed >::type storage_type;
typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
exchange(storage, v, order);
}
static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
{
storage_type original;
uint32_t tmp;
__asm__ __volatile__
(
BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0)
"ldrexd %1, %H1, [%2]\n"
BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0)
: BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0
"=&r" (original) // %1
: "r" (&storage) // %2
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original;
fence_before(order);
uint32_t tmp;
__asm__ __volatile__
(
BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0)
"1:\n"
"ldrexd %1, %H1, [%3]\n" // load the original value
"strexd %0, %2, %H2, [%3]\n" // store the replacement, tmp = store failed
"teq %0, #0\n" // check if store succeeded
"bne 1b\n"
BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0)
: BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0
"=&r" (original) // %1
: "r" (v), // %2
"r" (&storage) // %3
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE bool compare_exchange_weak(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
fence_before(success_order);
uint32_t tmp;
storage_type original, old_val = expected;
__asm__ __volatile__
(
BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0)
"ldrexd %1, %H1, [%3]\n" // original = *(&storage)
"cmp %1, %2\n" // flags = original.lo==old_val.lo
"ittt eq\n" // [hint that the following 3 instructions are conditional on flags.equal]
"cmpeq %H1, %H2\n" // if (flags.equal) flags = original.hi==old_val.hi
"strexdeq %0, %4, %H4, [%3]\n" // if (flags.equal) *(&storage) = desired, tmp = store failed
"teqeq %0, #0\n" // if (flags.equal) flags = tmp==0
"ite eq\n" // [hint that the following 2 instructions are conditional on flags.equal]
"moveq %2, #1\n" // if (flags.equal) old_val.lo = 1
"movne %2, #0\n" // if (!flags.equal) old_val.lo = 0
BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0)
: BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0
"=&r" (original), // %1
"+r" (old_val) // %2
: "r" (&storage), // %3
"r" (desired) // %4
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
const uint32_t success = (uint32_t)old_val;
if (success)
fence_after(success_order);
else
fence_after(failure_order);
expected = original;
return !!success;
}
static BOOST_FORCEINLINE bool compare_exchange_strong(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
fence_before(success_order);
uint32_t tmp;
storage_type original, old_val = expected;
__asm__ __volatile__
(
BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0)
"1:\n"
"ldrexd %1, %H1, [%3]\n" // original = *(&storage)
"cmp %1, %2\n" // flags = original.lo==old_val.lo
"it eq\n" // [hint that the following instruction is conditional on flags.equal]
"cmpeq %H1, %H2\n" // if (flags.equal) flags = original.hi==old_val.hi
"bne 2f\n" // if (!flags.equal) goto end
"strexd %0, %4, %H4, [%3]\n" // *(&storage) = desired, tmp = store failed
"teq %0, #0\n" // flags.equal = tmp == 0
"bne 1b\n" // if (flags.equal) goto retry
"2:\n"
"ite eq\n" // [hint that the following 2 instructions are conditional on flags.equal]
"moveq %2, #1\n" // if (flags.equal) old_val.lo = 1
"movne %2, #0\n" // if (!flags.equal) old_val.lo = 0
BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0)
: BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0
"=&r" (original), // %1
"+r" (old_val) // %2
: "r" (&storage), // %3
"r" (desired) // %4
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
const uint32_t success = (uint32_t)old_val;
if (success)
fence_after(success_order);
else
fence_after(failure_order);
expected = original;
return !!success;
}
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
fence_before(order);
storage_type original, result;
uint32_t tmp;
__asm__ __volatile__
(
BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0)
"1:\n"
"ldrexd %1, %H1, [%3]\n" // original = *(&storage)
"adds %2, %1, %4\n" // result = original + value
"adc %H2, %H1, %H4\n"
"strexd %0, %2, %H2, [%3]\n" // *(&storage) = result, tmp = store failed
"teq %0, #0\n" // flags = tmp==0
"bne 1b\n" // if (!flags.equal) goto retry
BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0)
: BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0
"=&r" (original), // %1
"=&r" (result) // %2
: "r" (&storage), // %3
"r" (v) // %4
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
fence_before(order);
storage_type original, result;
uint32_t tmp;
__asm__ __volatile__
(
BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0)
"1:\n"
"ldrexd %1, %H1, [%3]\n" // original = *(&storage)
"subs %2, %1, %4\n" // result = original - value
"sbc %H2, %H1, %H4\n"
"strexd %0, %2, %H2, [%3]\n" // *(&storage) = result, tmp = store failed
"teq %0, #0\n" // flags = tmp==0
"bne 1b\n" // if (!flags.equal) goto retry
BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0)
: BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0
"=&r" (original), // %1
"=&r" (result) // %2
: "r" (&storage), // %3
"r" (v) // %4
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
fence_before(order);
storage_type original, result;
uint32_t tmp;
__asm__ __volatile__
(
BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0)
"1:\n"
"ldrexd %1, %H1, [%3]\n" // original = *(&storage)
"and %2, %1, %4\n" // result = original & value
"and %H2, %H1, %H4\n"
"strexd %0, %2, %H2, [%3]\n" // *(&storage) = result, tmp = store failed
"teq %0, #0\n" // flags = tmp==0
"bne 1b\n" // if (!flags.equal) goto retry
BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0)
: BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0
"=&r" (original), // %1
"=&r" (result) // %2
: "r" (&storage), // %3
"r" (v) // %4
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
fence_before(order);
storage_type original, result;
uint32_t tmp;
__asm__ __volatile__
(
BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0)
"1:\n"
"ldrexd %1, %H1, [%3]\n" // original = *(&storage)
"orr %2, %1, %4\n" // result = original | value
"orr %H2, %H1, %H4\n"
"strexd %0, %2, %H2, [%3]\n" // *(&storage) = result, tmp = store failed
"teq %0, #0\n" // flags = tmp==0
"bne 1b\n" // if (!flags.equal) goto retry
BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0)
: BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0
"=&r" (original), // %1
"=&r" (result) // %2
: "r" (&storage), // %3
"r" (v) // %4
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
fence_before(order);
storage_type original, result;
uint32_t tmp;
__asm__ __volatile__
(
BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0)
"1:\n"
"ldrexd %1, %H1, [%3]\n" // original = *(&storage)
"eor %2, %1, %4\n" // result = original ^ value
"eor %H2, %H1, %H4\n"
"strexd %0, %2, %H2, [%3]\n" // *(&storage) = result, tmp = store failed
"teq %0, #0\n" // flags = tmp==0
"bne 1b\n" // if (!flags.equal) goto retry
BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0)
: BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0
"=&r" (original), // %1
"=&r" (result) // %2
: "r" (&storage), // %3
"r" (v) // %4
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
return !!exchange(storage, (storage_type)1, order);
}
static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
store(storage, 0, order);
}
static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
{
return true;
}
};
#endif // defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXD_STREXD)
BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
gcc_arm_operations_base::hardware_full_fence();
}
BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
__asm__ __volatile__ ("" ::: "memory");
}
} // namespace detail
} // namespace atomics
} // namespace boost
#endif // BOOST_ATOMIC_DETAIL_OPS_GCC_ARM_HPP_INCLUDED_

View File

@@ -0,0 +1,395 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/ops_gcc_atomic.hpp
*
* This header contains implementation of the \c operations template.
*/
#ifndef BOOST_ATOMIC_DETAIL_OPS_GCC_ATOMIC_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_OPS_GCC_ATOMIC_HPP_INCLUDED_
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/detail/operations_fwd.hpp>
#include <boost/atomic/capabilities.hpp>
#if defined(__clang__) && (defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B) || defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B))
#include <boost/atomic/detail/ops_gcc_x86_dcas.hpp>
#include <boost/atomic/detail/ops_cas_based.hpp>
#endif
#if __GCC_ATOMIC_LLONG_LOCK_FREE != BOOST_ATOMIC_LLONG_LOCK_FREE || __GCC_ATOMIC_LONG_LOCK_FREE != BOOST_ATOMIC_LONG_LOCK_FREE ||\
__GCC_ATOMIC_INT_LOCK_FREE != BOOST_ATOMIC_INT_LOCK_FREE || __GCC_ATOMIC_SHORT_LOCK_FREE != BOOST_ATOMIC_SHORT_LOCK_FREE ||\
__GCC_ATOMIC_CHAR_LOCK_FREE != BOOST_ATOMIC_CHAR_LOCK_FREE || __GCC_ATOMIC_BOOL_LOCK_FREE != BOOST_ATOMIC_BOOL_LOCK_FREE ||\
__GCC_ATOMIC_WCHAR_T_LOCK_FREE != BOOST_ATOMIC_WCHAR_T_LOCK_FREE
// There are platforms where we need to use larger storage types
#include <boost/atomic/detail/int_sizes.hpp>
#include <boost/atomic/detail/ops_extending_cas_based.hpp>
#endif
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if defined(__INTEL_COMPILER)
// This is used to suppress warning #32013 described below for Intel Compiler.
// In debug builds the compiler does not inline any functions, so basically
// every atomic function call results in this warning. I don't know any other
// way to selectively disable just this one warning.
#pragma system_header
#endif
namespace boost {
namespace atomics {
namespace detail {
/*!
* The function converts \c boost::memory_order values to the compiler-specific constants.
*
* NOTE: The intention is that the function is optimized away by the compiler, and the
* compiler-specific constants are passed to the intrinsics. I know constexpr doesn't
* work in this case because the standard atomics interface require memory ordering
* constants to be passed as function arguments, at which point they stop being constexpr.
* However it is crucial that the compiler sees constants and not runtime values,
* because otherwise it just ignores the ordering value and always uses seq_cst.
* This is the case with Intel C++ Compiler 14.0.3 (Composer XE 2013 SP1, update 3) and
* gcc 4.8.2. Intel Compiler issues a warning in this case:
*
* warning #32013: Invalid memory order specified. Defaulting to seq_cst memory order.
*
* while gcc acts silently.
*
* To mitigate the problem ALL functions, including the atomic<> members must be
* declared with BOOST_FORCEINLINE. In this case the compilers are able to see that
* all functions are called with constant orderings and call intrinstcts properly.
*
* Unfortunately, this still doesn't work in debug mode as the compiler doesn't
* inline functions even when marked with BOOST_FORCEINLINE. In this case all atomic
* operaions will be executed with seq_cst semantics.
*/
BOOST_FORCEINLINE BOOST_CONSTEXPR int convert_memory_order_to_gcc(memory_order order) BOOST_NOEXCEPT
{
return (order == memory_order_relaxed ? __ATOMIC_RELAXED : (order == memory_order_consume ? __ATOMIC_CONSUME :
(order == memory_order_acquire ? __ATOMIC_ACQUIRE : (order == memory_order_release ? __ATOMIC_RELEASE :
(order == memory_order_acq_rel ? __ATOMIC_ACQ_REL : __ATOMIC_SEQ_CST)))));
}
template< typename T >
struct gcc_atomic_operations
{
typedef T storage_type;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
__atomic_store_n(&storage, v, atomics::detail::convert_memory_order_to_gcc(order));
}
static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
{
return __atomic_load_n(&storage, atomics::detail::convert_memory_order_to_gcc(order));
}
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
return __atomic_fetch_add(&storage, v, atomics::detail::convert_memory_order_to_gcc(order));
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
return __atomic_fetch_sub(&storage, v, atomics::detail::convert_memory_order_to_gcc(order));
}
static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
return __atomic_exchange_n(&storage, v, atomics::detail::convert_memory_order_to_gcc(order));
}
static BOOST_FORCEINLINE bool compare_exchange_strong(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
return __atomic_compare_exchange_n
(
&storage, &expected, desired, false,
atomics::detail::convert_memory_order_to_gcc(success_order),
atomics::detail::convert_memory_order_to_gcc(failure_order)
);
}
static BOOST_FORCEINLINE bool compare_exchange_weak(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
return __atomic_compare_exchange_n
(
&storage, &expected, desired, true,
atomics::detail::convert_memory_order_to_gcc(success_order),
atomics::detail::convert_memory_order_to_gcc(failure_order)
);
}
static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
return __atomic_fetch_and(&storage, v, atomics::detail::convert_memory_order_to_gcc(order));
}
static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
return __atomic_fetch_or(&storage, v, atomics::detail::convert_memory_order_to_gcc(order));
}
static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
return __atomic_fetch_xor(&storage, v, atomics::detail::convert_memory_order_to_gcc(order));
}
static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
return __atomic_test_and_set(&storage, atomics::detail::convert_memory_order_to_gcc(order));
}
static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
__atomic_clear(const_cast< storage_type* >(&storage), atomics::detail::convert_memory_order_to_gcc(order));
}
static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile& storage) BOOST_NOEXCEPT
{
return __atomic_is_lock_free(sizeof(storage_type), &storage);
}
};
#if BOOST_ATOMIC_INT128_LOCK_FREE > 0
#if defined(__clang__) && defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B)
// Workaround for clang bug: http://llvm.org/bugs/show_bug.cgi?id=19149
// Clang 3.4 does not implement 128-bit __atomic* intrinsics even though it defines __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16
template< bool Signed >
struct operations< 16u, Signed > :
public cas_based_operations< gcc_dcas_x86_64< Signed > >
{
};
#else
template< bool Signed >
struct operations< 16u, Signed > :
public gcc_atomic_operations< typename make_storage_type< 16u, Signed >::type >
{
typedef typename make_storage_type< 16u, Signed >::aligned aligned_storage_type;
};
#endif
#endif
#if BOOST_ATOMIC_INT64_LOCK_FREE > 0
#if defined(__clang__) && defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B)
// Workaround for clang bug http://llvm.org/bugs/show_bug.cgi?id=19355
template< bool Signed >
struct operations< 8u, Signed > :
public cas_based_operations< gcc_dcas_x86< Signed > >
{
};
#elif (BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 8 && __GCC_ATOMIC_LLONG_LOCK_FREE != BOOST_ATOMIC_LLONG_LOCK_FREE) ||\
(BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 8 && __GCC_ATOMIC_LONG_LOCK_FREE != BOOST_ATOMIC_LONG_LOCK_FREE) ||\
(BOOST_ATOMIC_DETAIL_SIZEOF_INT == 8 && __GCC_ATOMIC_INT_LOCK_FREE != BOOST_ATOMIC_INT_LOCK_FREE) ||\
(BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 8 && __GCC_ATOMIC_SHORT_LOCK_FREE != BOOST_ATOMIC_SHORT_LOCK_FREE) ||\
(BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 8 && __GCC_ATOMIC_WCHAR_T_LOCK_FREE != BOOST_ATOMIC_WCHAR_T_LOCK_FREE)
#define BOOST_ATOMIC_DETAIL_INT64_EXTENDED
template< bool Signed >
struct operations< 8u, Signed > :
public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 16u, Signed >::type >, 8u, Signed >
{
typedef typename make_storage_type< 16u, Signed >::aligned aligned_storage_type;
};
#else
template< bool Signed >
struct operations< 8u, Signed > :
public gcc_atomic_operations< typename make_storage_type< 8u, Signed >::type >
{
typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type;
};
#endif
#endif
#if BOOST_ATOMIC_INT32_LOCK_FREE > 0
#if (BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 4 && __GCC_ATOMIC_LLONG_LOCK_FREE != BOOST_ATOMIC_LLONG_LOCK_FREE) ||\
(BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 4 && __GCC_ATOMIC_LONG_LOCK_FREE != BOOST_ATOMIC_LONG_LOCK_FREE) ||\
(BOOST_ATOMIC_DETAIL_SIZEOF_INT == 4 && __GCC_ATOMIC_INT_LOCK_FREE != BOOST_ATOMIC_INT_LOCK_FREE) ||\
(BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 4 && __GCC_ATOMIC_SHORT_LOCK_FREE != BOOST_ATOMIC_SHORT_LOCK_FREE) ||\
(BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 4 && __GCC_ATOMIC_WCHAR_T_LOCK_FREE != BOOST_ATOMIC_WCHAR_T_LOCK_FREE)
#define BOOST_ATOMIC_DETAIL_INT32_EXTENDED
#if !defined(BOOST_ATOMIC_DETAIL_INT64_EXTENDED)
template< bool Signed >
struct operations< 4u, Signed > :
public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 8u, Signed >::type >, 4u, Signed >
{
typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type;
};
#else // !defined(BOOST_ATOMIC_DETAIL_INT64_EXTENDED)
template< bool Signed >
struct operations< 4u, Signed > :
public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 16u, Signed >::type >, 4u, Signed >
{
typedef typename make_storage_type< 16u, Signed >::aligned aligned_storage_type;
};
#endif // !defined(BOOST_ATOMIC_DETAIL_INT64_EXTENDED)
#else
template< bool Signed >
struct operations< 4u, Signed > :
public gcc_atomic_operations< typename make_storage_type< 4u, Signed >::type >
{
typedef typename make_storage_type< 4u, Signed >::aligned aligned_storage_type;
};
#endif
#endif
#if BOOST_ATOMIC_INT16_LOCK_FREE > 0
#if (BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 2 && __GCC_ATOMIC_LLONG_LOCK_FREE != BOOST_ATOMIC_LLONG_LOCK_FREE) ||\
(BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 2 && __GCC_ATOMIC_LONG_LOCK_FREE != BOOST_ATOMIC_LONG_LOCK_FREE) ||\
(BOOST_ATOMIC_DETAIL_SIZEOF_INT == 2 && __GCC_ATOMIC_INT_LOCK_FREE != BOOST_ATOMIC_INT_LOCK_FREE) ||\
(BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 2 && __GCC_ATOMIC_SHORT_LOCK_FREE != BOOST_ATOMIC_SHORT_LOCK_FREE) ||\
(BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 2 && __GCC_ATOMIC_WCHAR_T_LOCK_FREE != BOOST_ATOMIC_WCHAR_T_LOCK_FREE)
#define BOOST_ATOMIC_DETAIL_INT16_EXTENDED
#if !defined(BOOST_ATOMIC_DETAIL_INT32_EXTENDED)
template< bool Signed >
struct operations< 2u, Signed > :
public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 4u, Signed >::type >, 2u, Signed >
{
typedef typename make_storage_type< 4u, Signed >::aligned aligned_storage_type;
};
#elif !defined(BOOST_ATOMIC_DETAIL_INT64_EXTENDED)
template< bool Signed >
struct operations< 2u, Signed > :
public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 8u, Signed >::type >, 2u, Signed >
{
typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type;
};
#else
template< bool Signed >
struct operations< 2u, Signed > :
public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 16u, Signed >::type >, 2u, Signed >
{
typedef typename make_storage_type< 16u, Signed >::aligned aligned_storage_type;
};
#endif
#else
template< bool Signed >
struct operations< 2u, Signed > :
public gcc_atomic_operations< typename make_storage_type< 2u, Signed >::type >
{
typedef typename make_storage_type< 2u, Signed >::aligned aligned_storage_type;
};
#endif
#endif
#if BOOST_ATOMIC_INT8_LOCK_FREE > 0
#if (BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 1 && __GCC_ATOMIC_LLONG_LOCK_FREE != BOOST_ATOMIC_LLONG_LOCK_FREE) ||\
(BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 1 && __GCC_ATOMIC_LONG_LOCK_FREE != BOOST_ATOMIC_LONG_LOCK_FREE) ||\
(BOOST_ATOMIC_DETAIL_SIZEOF_INT == 1 && __GCC_ATOMIC_INT_LOCK_FREE != BOOST_ATOMIC_INT_LOCK_FREE) ||\
(BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 1 && __GCC_ATOMIC_SHORT_LOCK_FREE != BOOST_ATOMIC_SHORT_LOCK_FREE) ||\
(BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 1 && __GCC_ATOMIC_WCHAR_T_LOCK_FREE != BOOST_ATOMIC_WCHAR_T_LOCK_FREE) ||\
(__GCC_ATOMIC_CHAR_LOCK_FREE != BOOST_ATOMIC_CHAR_LOCK_FREE) ||\
(__GCC_ATOMIC_BOOL_LOCK_FREE != BOOST_ATOMIC_BOOL_LOCK_FREE)
#if !defined(BOOST_ATOMIC_DETAIL_INT16_EXTENDED)
template< bool Signed >
struct operations< 1u, Signed > :
public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 2u, Signed >::type >, 1u, Signed >
{
typedef typename make_storage_type< 2u, Signed >::aligned aligned_storage_type;
};
#elif !defined(BOOST_ATOMIC_DETAIL_INT32_EXTENDED)
template< bool Signed >
struct operations< 1u, Signed > :
public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 4u, Signed >::type >, 1u, Signed >
{
typedef typename make_storage_type< 4u, Signed >::aligned aligned_storage_type;
};
#elif !defined(BOOST_ATOMIC_DETAIL_INT64_EXTENDED)
template< bool Signed >
struct operations< 1u, Signed > :
public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 8u, Signed >::type >, 1u, Signed >
{
typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type;
};
#else
template< bool Signed >
struct operations< 1u, Signed > :
public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 16u, Signed >::type >, 1u, Signed >
{
typedef typename make_storage_type< 16u, Signed >::aligned aligned_storage_type;
};
#endif
#else
template< bool Signed >
struct operations< 1u, Signed > :
public gcc_atomic_operations< typename make_storage_type< 1u, Signed >::type >
{
typedef typename make_storage_type< 1u, Signed >::aligned aligned_storage_type;
};
#endif
#endif
#undef BOOST_ATOMIC_DETAIL_INT16_EXTENDED
#undef BOOST_ATOMIC_DETAIL_INT32_EXTENDED
#undef BOOST_ATOMIC_DETAIL_INT64_EXTENDED
BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
{
__atomic_thread_fence(atomics::detail::convert_memory_order_to_gcc(order));
}
BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
{
__atomic_signal_fence(atomics::detail::convert_memory_order_to_gcc(order));
}
} // namespace detail
} // namespace atomics
} // namespace boost
#endif // BOOST_ATOMIC_DETAIL_OPS_GCC_ATOMIC_HPP_INCLUDED_

View File

@@ -0,0 +1,802 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2009 Helge Bahmann
* Copyright (c) 2013 Tim Blechmann
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/ops_gcc_ppc.hpp
*
* This header contains implementation of the \c operations template.
*/
#ifndef BOOST_ATOMIC_DETAIL_OPS_GCC_PPC_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_OPS_GCC_PPC_HPP_INCLUDED_
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/detail/operations_fwd.hpp>
#include <boost/atomic/capabilities.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
// The implementation below uses information from this document:
// http://www.rdrop.com/users/paulmck/scalability/paper/N2745r.2010.02.19a.html
/*
Refer to: Motorola: "Programming Environments Manual for 32-Bit
Implementations of the PowerPC Architecture", Appendix E:
"Synchronization Programming Examples" for an explanation of what is
going on here (can be found on the web at various places by the
name "MPCFPE32B.pdf", Google is your friend...)
Most of the atomic operations map to instructions in a relatively
straight-forward fashion, but "load"s may at first glance appear
a bit strange as they map to:
lwz %rX, addr
cmpw %rX, %rX
bne- 1f
1:
That is, the CPU is forced to perform a branch that "formally" depends
on the value retrieved from memory. This scheme has an overhead of
about 1-2 clock cycles per load, but it allows to map "acquire" to
the "isync" instruction instead of "sync" uniformly and for all type
of atomic operations. Since "isync" has a cost of about 15 clock
cycles, while "sync" hast a cost of about 50 clock cycles, the small
penalty to atomic loads more than compensates for this.
Byte- and halfword-sized atomic values are realized by encoding the
value to be represented into a word, performing sign/zero extension
as appropriate. This means that after add/sub operations the value
needs fixing up to accurately preserve the wrap-around semantic of
the smaller type. (Nothing special needs to be done for the bit-wise
and the "exchange type" operators as the compiler already sees to
it that values carried in registers are extended appropriately and
everything falls into place naturally).
The register constraint "b" instructs gcc to use any register
except r0; this is sometimes required because the encoding for
r0 is used to signify "constant zero" in a number of instructions,
making r0 unusable in this place. For simplicity this constraint
is used everywhere since I am to lazy to look this up on a
per-instruction basis, and ppc has enough registers for this not
to pose a problem.
*/
// A note about memory_order_consume. Technically, this architecture allows to avoid
// unnecessary memory barrier after consume load since it supports data dependency ordering.
// However, some compiler optimizations may break a seemingly valid code relying on data
// dependency tracking by injecting bogus branches to aid out of order execution.
// This may happen not only in Boost.Atomic code but also in user's code, which we have no
// control of. See this thread: http://lists.boost.org/Archives/boost/2014/06/213890.php.
// For this reason we promote memory_order_consume to memory_order_acquire.
struct gcc_ppc_operations_base
{
static BOOST_FORCEINLINE void fence_before(memory_order order) BOOST_NOEXCEPT
{
#if defined(__powerpc64__) || defined(__PPC64__)
if (order == memory_order_seq_cst)
__asm__ __volatile__ ("sync" ::: "memory");
else if ((order & memory_order_release) != 0)
__asm__ __volatile__ ("lwsync" ::: "memory");
#else
if ((order & memory_order_release) != 0)
__asm__ __volatile__ ("sync" ::: "memory");
#endif
}
static BOOST_FORCEINLINE void fence_after(memory_order order) BOOST_NOEXCEPT
{
if ((order & (memory_order_consume | memory_order_acquire)) != 0)
__asm__ __volatile__ ("isync" ::: "memory");
}
};
template< bool Signed >
struct operations< 4u, Signed > :
public gcc_ppc_operations_base
{
typedef typename make_storage_type< 4u, Signed >::type storage_type;
typedef typename make_storage_type< 4u, Signed >::aligned aligned_storage_type;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
fence_before(order);
__asm__ __volatile__
(
"stw %1, %0\n\t"
: "+m" (storage)
: "r" (v)
);
}
static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
{
storage_type v;
if (order == memory_order_seq_cst)
__asm__ __volatile__ ("sync" ::: "memory");
if ((order & (memory_order_consume | memory_order_acquire)) != 0)
{
__asm__ __volatile__
(
"lwz %0, %1\n\t"
"cmpw %0, %0\n\t"
"bne- 1f\n\t"
"1:\n\t"
"isync\n\t"
: "=&r" (v)
: "m" (storage)
: "cr0", "memory"
);
}
else
{
__asm__ __volatile__
(
"lwz %0, %1\n\t"
: "=&r" (v)
: "m" (storage)
);
}
return v;
}
static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original;
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
"lwarx %0,%y1\n\t"
"stwcx. %2,%y1\n\t"
"bne- 1b\n\t"
: "=&b" (original), "+Z" (storage)
: "b" (v)
: "cr0"
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE bool compare_exchange_weak(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
int success;
fence_before(success_order);
__asm__ __volatile__
(
"li %1, 0\n\t"
"lwarx %0,%y2\n\t"
"cmpw %0, %3\n\t"
"bne- 1f\n\t"
"stwcx. %4,%y2\n\t"
"bne- 1f\n\t"
"li %1, 1\n\t"
"1:\n\t"
: "=&b" (expected), "=&b" (success), "+Z" (storage)
: "b" (expected), "b" (desired)
: "cr0"
);
if (success)
fence_after(success_order);
else
fence_after(failure_order);
return !!success;
}
static BOOST_FORCEINLINE bool compare_exchange_strong(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
int success;
fence_before(success_order);
__asm__ __volatile__
(
"li %1, 0\n\t"
"0: lwarx %0,%y2\n\t"
"cmpw %0, %3\n\t"
"bne- 1f\n\t"
"stwcx. %4,%y2\n\t"
"bne- 0b\n\t"
"li %1, 1\n\t"
"1:\n\t"
: "=&b" (expected), "=&b" (success), "+Z" (storage)
: "b" (expected), "b" (desired)
: "cr0"
);
if (success)
fence_after(success_order);
else
fence_after(failure_order);
return !!success;
}
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, tmp;
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
"lwarx %0,%y2\n\t"
"add %1,%0,%3\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
: "=&b" (original), "=&b" (tmp), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, tmp;
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
"lwarx %0,%y2\n\t"
"sub %1,%0,%3\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
: "=&b" (original), "=&b" (tmp), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, tmp;
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
"lwarx %0,%y2\n\t"
"and %1,%0,%3\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
: "=&b" (original), "=&b" (tmp), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, tmp;
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
"lwarx %0,%y2\n\t"
"or %1,%0,%3\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
: "=&b" (original), "=&b" (tmp), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, tmp;
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
"lwarx %0,%y2\n\t"
"xor %1,%0,%3\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
: "=&b" (original), "=&b" (tmp), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
return !!exchange(storage, (storage_type)1, order);
}
static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
store(storage, 0, order);
}
static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
{
return true;
}
};
template< >
struct operations< 1u, false > :
public operations< 4u, false >
{
typedef operations< 4u, false > base_type;
typedef base_type::storage_type storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, tmp;
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
"lwarx %0,%y2\n\t"
"add %1,%0,%3\n\t"
"rlwinm %1, %1, 0, 0xff\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
: "=&b" (original), "=&b" (tmp), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, tmp;
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
"lwarx %0,%y2\n\t"
"sub %1,%0,%3\n\t"
"rlwinm %1, %1, 0, 0xff\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
: "=&b" (original), "=&b" (tmp), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
};
template< >
struct operations< 1u, true > :
public operations< 4u, true >
{
typedef operations< 4u, true > base_type;
typedef base_type::storage_type storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, tmp;
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
"lwarx %0,%y2\n\t"
"add %1,%0,%3\n\t"
"extsb %1, %1\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
: "=&b" (original), "=&b" (tmp), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, tmp;
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
"lwarx %0,%y2\n\t"
"sub %1,%0,%3\n\t"
"extsb %1, %1\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
: "=&b" (original), "=&b" (tmp), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
};
template< >
struct operations< 2u, false > :
public operations< 4u, false >
{
typedef operations< 4u, false > base_type;
typedef base_type::storage_type storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, tmp;
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
"lwarx %0,%y2\n\t"
"add %1,%0,%3\n\t"
"rlwinm %1, %1, 0, 0xffff\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
: "=&b" (original), "=&b" (tmp), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, tmp;
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
"lwarx %0,%y2\n\t"
"sub %1,%0,%3\n\t"
"rlwinm %1, %1, 0, 0xffff\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
: "=&b" (original), "=&b" (tmp), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
};
template< >
struct operations< 2u, true > :
public operations< 4u, true >
{
typedef operations< 4u, true > base_type;
typedef base_type::storage_type storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, tmp;
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
"lwarx %0,%y2\n\t"
"add %1,%0,%3\n\t"
"extsh %1, %1\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
: "=&b" (original), "=&b" (tmp), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, tmp;
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
"lwarx %0,%y2\n\t"
"sub %1,%0,%3\n\t"
"extsh %1, %1\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
: "=&b" (original), "=&b" (tmp), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
};
#if defined(__powerpc64__) || defined(__PPC64__)
template< bool Signed >
struct operations< 8u, Signed > :
public gcc_ppc_operations_base
{
typedef typename make_storage_type< 8u, Signed >::type storage_type;
typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
fence_before(order);
__asm__ __volatile__
(
"std %1, %0\n\t"
: "+m" (storage)
: "r" (v)
);
}
static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
{
storage_type v;
if (order == memory_order_seq_cst)
__asm__ __volatile__ ("sync" ::: "memory");
if ((order & (memory_order_consume | memory_order_acquire)) != 0)
{
__asm__ __volatile__
(
"ld %0, %1\n\t"
"cmpd %0, %0\n\t"
"bne- 1f\n\t"
"1:\n\t"
"isync\n\t"
: "=&b" (v)
: "m" (storage)
: "cr0", "memory"
);
}
else
{
__asm__ __volatile__
(
"ld %0, %1\n\t"
: "=&b" (v)
: "m" (storage)
);
}
return v;
}
static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original;
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
"ldarx %0,%y1\n\t"
"stdcx. %2,%y1\n\t"
"bne- 1b\n\t"
: "=&b" (original), "+Z" (storage)
: "b" (v)
: "cr0"
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE bool compare_exchange_weak(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
int success;
fence_before(success_order);
__asm__ __volatile__
(
"li %1, 0\n\t"
"ldarx %0,%y2\n\t"
"cmpd %0, %3\n\t"
"bne- 1f\n\t"
"stdcx. %4,%y2\n\t"
"bne- 1f\n\t"
"li %1, 1\n\t"
"1:"
: "=&b" (expected), "=&b" (success), "+Z" (storage)
: "b" (expected), "b" (desired)
: "cr0"
);
if (success)
fence_after(success_order);
else
fence_after(failure_order);
return !!success;
}
static BOOST_FORCEINLINE bool compare_exchange_strong(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
int success;
fence_before(success_order);
__asm__ __volatile__
(
"li %1, 0\n\t"
"0: ldarx %0,%y2\n\t"
"cmpd %0, %3\n\t"
"bne- 1f\n\t"
"stdcx. %4,%y2\n\t"
"bne- 0b\n\t"
"li %1, 1\n\t"
"1:\n\t"
: "=&b" (expected), "=&b" (success), "+Z" (storage)
: "b" (expected), "b" (desired)
: "cr0"
);
if (success)
fence_after(success_order);
else
fence_after(failure_order);
return !!success;
}
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, tmp;
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
"ldarx %0,%y2\n\t"
"add %1,%0,%3\n\t"
"stdcx. %1,%y2\n\t"
"bne- 1b\n\t"
: "=&b" (original), "=&b" (tmp), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, tmp;
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
"ldarx %0,%y2\n\t"
"sub %1,%0,%3\n\t"
"stdcx. %1,%y2\n\t"
"bne- 1b\n\t"
: "=&b" (original), "=&b" (tmp), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, tmp;
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
"ldarx %0,%y2\n\t"
"and %1,%0,%3\n\t"
"stdcx. %1,%y2\n\t"
"bne- 1b\n\t"
: "=&b" (original), "=&b" (tmp), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, tmp;
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
"ldarx %0,%y2\n\t"
"or %1,%0,%3\n\t"
"stdcx. %1,%y2\n\t"
"bne- 1b\n\t"
: "=&b" (original), "=&b" (tmp), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, tmp;
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
"ldarx %0,%y2\n\t"
"xor %1,%0,%3\n\t"
"stdcx. %1,%y2\n\t"
"bne- 1b\n\t"
: "=&b" (original), "=&b" (tmp), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
return original;
}
static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
return !!exchange(storage, (storage_type)1, order);
}
static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
store(storage, 0, order);
}
static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
{
return true;
}
};
#endif // defined(__powerpc64__) || defined(__PPC64__)
BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
{
switch (order)
{
case memory_order_consume:
case memory_order_acquire:
case memory_order_release:
case memory_order_acq_rel:
#if defined(__powerpc64__) || defined(__PPC64__)
__asm__ __volatile__ ("lwsync" ::: "memory");
break;
#endif
case memory_order_seq_cst:
__asm__ __volatile__ ("sync" ::: "memory");
break;
default:;
}
}
BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
#if defined(__ibmxl__) || defined(__IBMCPP__)
__fence();
#else
__asm__ __volatile__ ("" ::: "memory");
#endif
}
} // namespace detail
} // namespace atomics
} // namespace boost
#endif // BOOST_ATOMIC_DETAIL_OPS_GCC_PPC_HPP_INCLUDED_

View File

@@ -0,0 +1,240 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2010 Helge Bahmann
* Copyright (c) 2013 Tim Blechmann
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/ops_gcc_sparc.hpp
*
* This header contains implementation of the \c operations template.
*/
#ifndef BOOST_ATOMIC_DETAIL_OPS_GCC_SPARC_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_OPS_GCC_SPARC_HPP_INCLUDED_
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/detail/operations_fwd.hpp>
#include <boost/atomic/capabilities.hpp>
#include <boost/atomic/detail/ops_cas_based.hpp>
#include <boost/atomic/detail/ops_extending_cas_based.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
struct gcc_sparc_cas_base
{
static BOOST_FORCEINLINE void fence_before(memory_order order) BOOST_NOEXCEPT
{
if (order == memory_order_seq_cst)
__asm__ __volatile__ ("membar #Sync" ::: "memory");
else if ((order & memory_order_release) != 0)
__asm__ __volatile__ ("membar #StoreStore | #LoadStore" ::: "memory");
}
static BOOST_FORCEINLINE void fence_after(memory_order order) BOOST_NOEXCEPT
{
if (order == memory_order_seq_cst)
__asm__ __volatile__ ("membar #Sync" ::: "memory");
else if ((order & (memory_order_consume | memory_order_acquire)) != 0)
__asm__ __volatile__ ("membar #StoreStore | #LoadStore" ::: "memory");
}
static BOOST_FORCEINLINE void fence_after_store(memory_order order) BOOST_NOEXCEPT
{
if (order == memory_order_seq_cst)
__asm__ __volatile__ ("membar #Sync" ::: "memory");
}
};
template< bool Signed >
struct gcc_sparc_cas32 :
public gcc_sparc_cas_base
{
typedef typename make_storage_type< 4u, Signed >::type storage_type;
typedef typename make_storage_type< 4u, Signed >::aligned aligned_storage_type;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
fence_before_store(order);
storage = v;
fence_after_store(order);
}
static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
{
storage_type v = storage;
fence_after(order);
return v;
}
static BOOST_FORCEINLINE bool compare_exchange_strong(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
fence_before(success_order);
storage_type previous = expected;
__asm__ __volatile__
(
"cas [%1], %2, %0"
: "+r" (desired)
: "r" (&storage), "r" (previous)
: "memory"
);
const bool success = (desired == previous);
if (success)
fence_after(success_order);
else
fence_after(failure_order);
expected = desired;
return success;
}
static BOOST_FORCEINLINE bool compare_exchange_weak(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
return compare_exchange_strong(storage, expected, desired, success_order, failure_order);
}
static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
base_type::fence_before(order);
__asm__ __volatile__
(
"swap [%1], %0"
: "+r" (v)
: "r" (&storage)
: "memory"
);
base_type::fence_after(order);
return v;
}
static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
{
return true;
}
};
template< bool Signed >
struct operations< 4u, Signed > :
public cas_based_operations< gcc_sparc_cas32< Signed > >
{
};
template< bool Signed >
struct operations< 1u, Signed > :
public extending_cas_based_operations< operations< 4u, Signed >, 1u, Signed >
{
};
template< bool Signed >
struct operations< 2u, Signed > :
public extending_cas_based_operations< operations< 4u, Signed >, 2u, Signed >
{
};
template< bool Signed >
struct gcc_sparc_cas64 :
public gcc_sparc_cas_base
{
typedef typename make_storage_type< 8u, Signed >::type storage_type;
typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
fence_before_store(order);
storage = v;
fence_after_store(order);
}
static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
{
storage_type v = storage;
fence_after(order);
return v;
}
static BOOST_FORCEINLINE bool compare_exchange_strong(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
fence_before(success_order);
storage_type previous = expected;
__asm__ __volatile__
(
"casx [%1], %2, %0"
: "+r" (desired)
: "r" (&storage), "r" (previous)
: "memory"
);
const bool success = (desired == previous);
if (success)
fence_after(success_order);
else
fence_after(failure_order);
expected = desired;
return success;
}
static BOOST_FORCEINLINE bool compare_exchange_weak(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
return compare_exchange_strong(storage, expected, desired, success_order, failure_order);
}
static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
{
return true;
}
};
template< bool Signed >
struct operations< 8u, Signed > :
public cas_based_operations< cas_based_exchange< gcc_sparc_cas64< Signed > > >
{
};
BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
{
switch (order)
{
case memory_order_release:
__asm__ __volatile__ ("membar #StoreStore | #LoadStore" ::: "memory");
break;
case memory_order_consume:
case memory_order_acquire:
__asm__ __volatile__ ("membar #LoadLoad | #LoadStore" ::: "memory");
break;
case memory_order_acq_rel:
__asm__ __volatile__ ("membar #LoadLoad | #LoadStore | #StoreStore" ::: "memory");
break;
case memory_order_seq_cst:
__asm__ __volatile__ ("membar #Sync" ::: "memory");
break;
case memory_order_relaxed:
default:
break;
}
}
BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
__asm__ __volatile__ ("" ::: "memory");
}
} // namespace detail
} // namespace atomics
} // namespace boost
#endif // BOOST_ATOMIC_DETAIL_OPS_GCC_SPARC_HPP_INCLUDED_

View File

@@ -0,0 +1,270 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2011 Helge Bahmann
* Copyright (c) 2013 Tim Blechmann
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/ops_gcc_sync.hpp
*
* This header contains implementation of the \c operations template.
*/
#ifndef BOOST_ATOMIC_DETAIL_OPS_GCC_SYNC_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_OPS_GCC_SYNC_HPP_INCLUDED_
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/detail/operations_fwd.hpp>
#include <boost/atomic/detail/ops_extending_cas_based.hpp>
#include <boost/atomic/capabilities.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
struct gcc_sync_operations_base
{
static BOOST_FORCEINLINE void fence_before_store(memory_order order) BOOST_NOEXCEPT
{
if ((order & memory_order_release) != 0)
__sync_synchronize();
}
static BOOST_FORCEINLINE void fence_after_store(memory_order order) BOOST_NOEXCEPT
{
if (order == memory_order_seq_cst)
__sync_synchronize();
}
static BOOST_FORCEINLINE void fence_after_load(memory_order order) BOOST_NOEXCEPT
{
if ((order & (memory_order_acquire | memory_order_consume)) != 0)
__sync_synchronize();
}
};
template< typename T >
struct gcc_sync_operations :
public gcc_sync_operations_base
{
typedef T storage_type;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
fence_before_store(order);
storage = v;
fence_after_store(order);
}
static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
{
storage_type v = storage;
fence_after_load(order);
return v;
}
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
return __sync_fetch_and_add(&storage, v);
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
return __sync_fetch_and_sub(&storage, v);
}
static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
// GCC docs mention that not all architectures may support full exchange semantics for this intrinsic. However, GCC's implementation of
// std::atomic<> uses this intrinsic unconditionally. We do so as well. In case if some architectures actually don't support this, we can always
// add a check here and fall back to a CAS loop.
if ((order & memory_order_release) != 0)
__sync_synchronize();
return __sync_lock_test_and_set(&storage, v);
}
static BOOST_FORCEINLINE bool compare_exchange_strong(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
{
storage_type expected2 = expected;
storage_type old_val = __sync_val_compare_and_swap(&storage, expected2, desired);
if (old_val == expected2)
{
return true;
}
else
{
expected = old_val;
return false;
}
}
static BOOST_FORCEINLINE bool compare_exchange_weak(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
return compare_exchange_strong(storage, expected, desired, success_order, failure_order);
}
static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
return __sync_fetch_and_and(&storage, v);
}
static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
return __sync_fetch_and_or(&storage, v);
}
static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
return __sync_fetch_and_xor(&storage, v);
}
static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
if ((order & memory_order_release) != 0)
__sync_synchronize();
return !!__sync_lock_test_and_set(&storage, 1);
}
static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
__sync_lock_release(&storage);
if (order == memory_order_seq_cst)
__sync_synchronize();
}
static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
{
return true;
}
};
#if BOOST_ATOMIC_INT8_LOCK_FREE > 0
template< bool Signed >
struct operations< 1u, Signed > :
#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1)
public gcc_sync_operations< typename make_storage_type< 1u, Signed >::type >
#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2)
public extending_cas_based_operations< gcc_sync_operations< typename make_storage_type< 2u, Signed >::type >, 1u, Signed >
#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
public extending_cas_based_operations< gcc_sync_operations< typename make_storage_type< 4u, Signed >::type >, 1u, Signed >
#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
public extending_cas_based_operations< gcc_sync_operations< typename make_storage_type< 8u, Signed >::type >, 1u, Signed >
#else
public extending_cas_based_operations< gcc_sync_operations< typename make_storage_type< 16u, Signed >::type >, 1u, Signed >
#endif
{
#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1)
typedef typename make_storage_type< 1u, Signed >::aligned aligned_storage_type;
#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2)
typedef typename make_storage_type< 2u, Signed >::aligned aligned_storage_type;
#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
typedef typename make_storage_type< 4u, Signed >::aligned aligned_storage_type;
#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type;
#else
typedef typename make_storage_type< 16u, Signed >::aligned aligned_storage_type;
#endif
};
#endif
#if BOOST_ATOMIC_INT16_LOCK_FREE > 0
template< bool Signed >
struct operations< 2u, Signed > :
#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2)
public gcc_sync_operations< typename make_storage_type< 2u, Signed >::type >
#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
public extending_cas_based_operations< gcc_sync_operations< typename make_storage_type< 4u, Signed >::type >, 2u, Signed >
#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
public extending_cas_based_operations< gcc_sync_operations< typename make_storage_type< 8u, Signed >::type >, 2u, Signed >
#else
public extending_cas_based_operations< gcc_sync_operations< typename make_storage_type< 16u, Signed >::type >, 2u, Signed >
#endif
{
#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2)
typedef typename make_storage_type< 2u, Signed >::aligned aligned_storage_type;
#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
typedef typename make_storage_type< 4u, Signed >::aligned aligned_storage_type;
#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type;
#else
typedef typename make_storage_type< 16u, Signed >::aligned aligned_storage_type;
#endif
};
#endif
#if BOOST_ATOMIC_INT32_LOCK_FREE > 0
template< bool Signed >
struct operations< 4u, Signed > :
#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
public gcc_sync_operations< typename make_storage_type< 4u, Signed >::type >
#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
public extending_cas_based_operations< gcc_sync_operations< typename make_storage_type< 8u, Signed >::type >, 4u, Signed >
#else
public extending_cas_based_operations< gcc_sync_operations< typename make_storage_type< 16u, Signed >::type >, 4u, Signed >
#endif
{
#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
typedef typename make_storage_type< 4u, Signed >::aligned aligned_storage_type;
#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type;
#else
typedef typename make_storage_type< 16u, Signed >::aligned aligned_storage_type;
#endif
};
#endif
#if BOOST_ATOMIC_INT64_LOCK_FREE > 0
template< bool Signed >
struct operations< 8u, Signed > :
#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
public gcc_sync_operations< typename make_storage_type< 8u, Signed >::type >
#else
public extending_cas_based_operations< gcc_sync_operations< typename make_storage_type< 16u, Signed >::type >, 8u, Signed >
#endif
{
#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type;
#else
typedef typename make_storage_type< 16u, Signed >::aligned aligned_storage_type;
#endif
};
#endif
#if BOOST_ATOMIC_INT128_LOCK_FREE > 0
template< bool Signed >
struct operations< 16u, Signed > :
public gcc_sync_operations< typename make_storage_type< 16u, Signed >::type >
{
typedef typename make_storage_type< 16u, Signed >::aligned aligned_storage_type;
};
#endif
BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
__sync_synchronize();
}
BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
__asm__ __volatile__ ("" ::: "memory");
}
} // namespace detail
} // namespace atomics
} // namespace boost
#endif // BOOST_ATOMIC_DETAIL_OPS_GCC_SYNC_HPP_INCLUDED_

View File

@@ -0,0 +1,514 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2009 Helge Bahmann
* Copyright (c) 2012 Tim Blechmann
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/ops_gcc_x86.hpp
*
* This header contains implementation of the \c operations template.
*/
#ifndef BOOST_ATOMIC_DETAIL_OPS_GCC_X86_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_OPS_GCC_X86_HPP_INCLUDED_
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/detail/operations_fwd.hpp>
#include <boost/atomic/capabilities.hpp>
#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B) || defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B)
#include <boost/atomic/detail/ops_gcc_x86_dcas.hpp>
#include <boost/atomic/detail/ops_cas_based.hpp>
#endif
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if defined(__x86_64__)
#define BOOST_ATOMIC_DETAIL_TEMP_CAS_REGISTER "rdx"
#else
#define BOOST_ATOMIC_DETAIL_TEMP_CAS_REGISTER "edx"
#endif
namespace boost {
namespace atomics {
namespace detail {
struct gcc_x86_operations_base
{
static BOOST_FORCEINLINE void fence_before(memory_order order) BOOST_NOEXCEPT
{
if ((order & memory_order_release) != 0)
__asm__ __volatile__ ("" ::: "memory");
}
static BOOST_FORCEINLINE void fence_after(memory_order order) BOOST_NOEXCEPT
{
if ((order & memory_order_acquire) != 0)
__asm__ __volatile__ ("" ::: "memory");
}
};
template< typename T, typename Derived >
struct gcc_x86_operations :
public gcc_x86_operations_base
{
typedef T storage_type;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_seq_cst)
{
fence_before(order);
storage = v;
fence_after(order);
}
else
{
Derived::exchange(storage, v, order);
}
}
static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
{
storage_type v = storage;
fence_after(order);
return v;
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
return Derived::fetch_add(storage, -v, order);
}
static BOOST_FORCEINLINE bool compare_exchange_weak(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
return Derived::compare_exchange_strong(storage, expected, desired, success_order, failure_order);
}
static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
return !!Derived::exchange(storage, (storage_type)1, order);
}
static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
store(storage, (storage_type)0, order);
}
static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
{
return true;
}
};
template< bool Signed >
struct operations< 1u, Signed > :
public gcc_x86_operations< typename make_storage_type< 1u, Signed >::type, operations< 1u, Signed > >
{
typedef gcc_x86_operations< typename make_storage_type< 1u, Signed >::type, operations< 1u, Signed > > base_type;
typedef typename base_type::storage_type storage_type;
typedef typename make_storage_type< 1u, Signed >::aligned aligned_storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
__asm__ __volatile__
(
"lock; xaddb %0, %1"
: "+q" (v), "+m" (storage)
:
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
return v;
}
static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
__asm__ __volatile__
(
"xchgb %0, %1"
: "+q" (v), "+m" (storage)
:
: "memory"
);
return v;
}
static BOOST_FORCEINLINE bool compare_exchange_strong(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
{
storage_type previous = expected;
bool success;
__asm__ __volatile__
(
"lock; cmpxchgb %3, %1\n\t"
"sete %2"
: "+a" (previous), "+m" (storage), "=q" (success)
: "q" (desired)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
expected = previous;
return success;
}
#define BOOST_ATOMIC_DETAIL_CAS_LOOP(op, argument, result)\
__asm__ __volatile__\
(\
"xor %%" BOOST_ATOMIC_DETAIL_TEMP_CAS_REGISTER ", %%" BOOST_ATOMIC_DETAIL_TEMP_CAS_REGISTER "\n\t"\
".align 16\n\t"\
"1: movb %[arg], %%dl\n\t"\
op " %%al, %%dl\n\t"\
"lock; cmpxchgb %%dl, %[storage]\n\t"\
"jne 1b"\
: [res] "+a" (result), [storage] "+m" (storage)\
: [arg] "q" (argument)\
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA BOOST_ATOMIC_DETAIL_TEMP_CAS_REGISTER, "memory"\
)
static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
storage_type res = storage;
BOOST_ATOMIC_DETAIL_CAS_LOOP("andb", v, res);
return res;
}
static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
storage_type res = storage;
BOOST_ATOMIC_DETAIL_CAS_LOOP("orb", v, res);
return res;
}
static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
storage_type res = storage;
BOOST_ATOMIC_DETAIL_CAS_LOOP("xorb", v, res);
return res;
}
#undef BOOST_ATOMIC_DETAIL_CAS_LOOP
};
template< bool Signed >
struct operations< 2u, Signed > :
public gcc_x86_operations< typename make_storage_type< 2u, Signed >::type, operations< 2u, Signed > >
{
typedef gcc_x86_operations< typename make_storage_type< 2u, Signed >::type, operations< 2u, Signed > > base_type;
typedef typename base_type::storage_type storage_type;
typedef typename make_storage_type< 2u, Signed >::aligned aligned_storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
__asm__ __volatile__
(
"lock; xaddw %0, %1"
: "+q" (v), "+m" (storage)
:
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
return v;
}
static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
__asm__ __volatile__
(
"xchgw %0, %1"
: "+q" (v), "+m" (storage)
:
: "memory"
);
return v;
}
static BOOST_FORCEINLINE bool compare_exchange_strong(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
{
storage_type previous = expected;
bool success;
__asm__ __volatile__
(
"lock; cmpxchgw %3, %1\n\t"
"sete %2"
: "+a" (previous), "+m" (storage), "=q" (success)
: "q" (desired)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
expected = previous;
return success;
}
#define BOOST_ATOMIC_DETAIL_CAS_LOOP(op, argument, result)\
__asm__ __volatile__\
(\
"xor %%" BOOST_ATOMIC_DETAIL_TEMP_CAS_REGISTER ", %%" BOOST_ATOMIC_DETAIL_TEMP_CAS_REGISTER "\n\t"\
".align 16\n\t"\
"1: movw %[arg], %%dx\n\t"\
op " %%ax, %%dx\n\t"\
"lock; cmpxchgw %%dx, %[storage]\n\t"\
"jne 1b"\
: [res] "+a" (result), [storage] "+m" (storage)\
: [arg] "q" (argument)\
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA BOOST_ATOMIC_DETAIL_TEMP_CAS_REGISTER, "memory"\
)
static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
storage_type res = storage;
BOOST_ATOMIC_DETAIL_CAS_LOOP("andw", v, res);
return res;
}
static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
storage_type res = storage;
BOOST_ATOMIC_DETAIL_CAS_LOOP("orw", v, res);
return res;
}
static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
storage_type res = storage;
BOOST_ATOMIC_DETAIL_CAS_LOOP("xorw", v, res);
return res;
}
#undef BOOST_ATOMIC_DETAIL_CAS_LOOP
};
template< bool Signed >
struct operations< 4u, Signed > :
public gcc_x86_operations< typename make_storage_type< 4u, Signed >::type, operations< 4u, Signed > >
{
typedef gcc_x86_operations< typename make_storage_type< 4u, Signed >::type, operations< 4u, Signed > > base_type;
typedef typename base_type::storage_type storage_type;
typedef typename make_storage_type< 4u, Signed >::aligned aligned_storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
__asm__ __volatile__
(
"lock; xaddl %0, %1"
: "+r" (v), "+m" (storage)
:
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
return v;
}
static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
__asm__ __volatile__
(
"xchgl %0, %1"
: "+r" (v), "+m" (storage)
:
: "memory"
);
return v;
}
static BOOST_FORCEINLINE bool compare_exchange_strong(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
{
storage_type previous = expected;
bool success;
__asm__ __volatile__
(
"lock; cmpxchgl %3, %1\n\t"
"sete %2"
: "+a" (previous), "+m" (storage), "=q" (success)
: "r" (desired)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
expected = previous;
return success;
}
#define BOOST_ATOMIC_DETAIL_CAS_LOOP(op, argument, result)\
__asm__ __volatile__\
(\
"xor %%" BOOST_ATOMIC_DETAIL_TEMP_CAS_REGISTER ", %%" BOOST_ATOMIC_DETAIL_TEMP_CAS_REGISTER "\n\t"\
".align 16\n\t"\
"1: movl %[arg], %%edx\n\t"\
op " %%eax, %%edx\n\t"\
"lock; cmpxchgl %%edx, %[storage]\n\t"\
"jne 1b"\
: [res] "+a" (result), [storage] "+m" (storage)\
: [arg] "r" (argument)\
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA BOOST_ATOMIC_DETAIL_TEMP_CAS_REGISTER, "memory"\
)
static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
storage_type res = storage;
BOOST_ATOMIC_DETAIL_CAS_LOOP("andl", v, res);
return res;
}
static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
storage_type res = storage;
BOOST_ATOMIC_DETAIL_CAS_LOOP("orl", v, res);
return res;
}
static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
storage_type res = storage;
BOOST_ATOMIC_DETAIL_CAS_LOOP("xorl", v, res);
return res;
}
#undef BOOST_ATOMIC_DETAIL_CAS_LOOP
};
#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B)
template< bool Signed >
struct operations< 8u, Signed > :
public cas_based_operations< gcc_dcas_x86< Signed > >
{
};
#elif defined(__x86_64__)
template< bool Signed >
struct operations< 8u, Signed > :
public gcc_x86_operations< typename make_storage_type< 8u, Signed >::type, operations< 8u, Signed > >
{
typedef gcc_x86_operations< typename make_storage_type< 8u, Signed >::type, operations< 8u, Signed > > base_type;
typedef typename base_type::storage_type storage_type;
typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
__asm__ __volatile__
(
"lock; xaddq %0, %1"
: "+r" (v), "+m" (storage)
:
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
return v;
}
static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
__asm__ __volatile__
(
"xchgq %0, %1"
: "+r" (v), "+m" (storage)
:
: "memory"
);
return v;
}
static BOOST_FORCEINLINE bool compare_exchange_strong(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
{
storage_type previous = expected;
bool success;
__asm__ __volatile__
(
"lock; cmpxchgq %3, %1\n\t"
"sete %2"
: "+a" (previous), "+m" (storage), "=q" (success)
: "r" (desired)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
expected = previous;
return success;
}
#define BOOST_ATOMIC_DETAIL_CAS_LOOP(op, argument, result)\
__asm__ __volatile__\
(\
"xor %%" BOOST_ATOMIC_DETAIL_TEMP_CAS_REGISTER ", %%" BOOST_ATOMIC_DETAIL_TEMP_CAS_REGISTER "\n\t"\
".align 16\n\t"\
"1: movq %[arg], %%rdx\n\t"\
op " %%rax, %%rdx\n\t"\
"lock; cmpxchgq %%rdx, %[storage]\n\t"\
"jne 1b"\
: [res] "+a" (result), [storage] "+m" (storage)\
: [arg] "r" (argument)\
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA BOOST_ATOMIC_DETAIL_TEMP_CAS_REGISTER, "memory"\
)
static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
storage_type res = storage;
BOOST_ATOMIC_DETAIL_CAS_LOOP("andq", v, res);
return res;
}
static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
storage_type res = storage;
BOOST_ATOMIC_DETAIL_CAS_LOOP("orq", v, res);
return res;
}
static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
storage_type res = storage;
BOOST_ATOMIC_DETAIL_CAS_LOOP("xorq", v, res);
return res;
}
#undef BOOST_ATOMIC_DETAIL_CAS_LOOP
};
#endif
#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B)
template< bool Signed >
struct operations< 16u, Signed > :
public cas_based_operations< gcc_dcas_x86_64< Signed > >
{
};
#endif // defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B)
BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
{
if (order == memory_order_seq_cst)
{
__asm__ __volatile__
(
#if defined(__x86_64__) || defined(__SSE2__)
"mfence\n"
#else
"lock; addl $0, (%%esp)\n"
#endif
::: "memory"
);
}
else if ((order & (memory_order_acquire | memory_order_release)) != 0)
{
__asm__ __volatile__ ("" ::: "memory");
}
}
BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
__asm__ __volatile__ ("" ::: "memory");
}
} // namespace detail
} // namespace atomics
} // namespace boost
#undef BOOST_ATOMIC_DETAIL_TEMP_CAS_REGISTER
#endif // BOOST_ATOMIC_DETAIL_OPS_GCC_X86_HPP_INCLUDED_

View File

@@ -0,0 +1,616 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2009 Helge Bahmann
* Copyright (c) 2012 Tim Blechmann
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/ops_gcc_x86_dcas.hpp
*
* This header contains implementation of the double-width CAS primitive for x86.
*/
#ifndef BOOST_ATOMIC_DETAIL_OPS_GCC_X86_DCAS_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_OPS_GCC_X86_DCAS_HPP_INCLUDED_
#include <boost/cstdint.hpp>
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/capabilities.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B)
template< bool Signed >
struct gcc_dcas_x86
{
typedef typename make_storage_type< 8u, Signed >::type storage_type;
typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
if ((((uint32_t)&storage) & 0x00000007) == 0)
{
#if defined(__SSE2__)
__asm__ __volatile__
(
#if defined(__AVX__)
"vmovq %1, %%xmm4\n\t"
"vmovq %%xmm4, %0\n\t"
#else
"movq %1, %%xmm4\n\t"
"movq %%xmm4, %0\n\t"
#endif
: "=m" (storage)
: "m" (v)
: "memory", "xmm4"
);
#else
__asm__ __volatile__
(
"fildll %1\n\t"
"fistpll %0\n\t"
: "=m" (storage)
: "m" (v)
: "memory"
);
#endif
}
else
{
#if !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
#if defined(__PIC__)
uint32_t scratch;
__asm__ __volatile__
(
"movl %%ebx, %[scratch]\n\t"
"movl %[value_lo], %%ebx\n\t"
"movl %[dest], %%eax\n\t"
"movl 4+%[dest], %%edx\n\t"
".align 16\n\t"
"1: lock; cmpxchg8b %[dest]\n\t"
"jne 1b\n\t"
"movl %[scratch], %%ebx\n\t"
: [scratch] "=m" (scratch), [dest] "=o" (storage)
: [value_lo] "a" ((uint32_t)v), "c" ((uint32_t)(v >> 32))
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "edx", "memory"
);
#else // defined(__PIC__)
__asm__ __volatile__
(
"movl %[dest], %%eax\n\t"
"movl 4+%[dest], %%edx\n\t"
".align 16\n\t"
"1: lock; cmpxchg8b %[dest]\n\t"
"jne 1b\n\t"
: [dest] "=o" (storage)
: [value_lo] "b" ((uint32_t)v), "c" ((uint32_t)(v >> 32))
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "eax", "edx", "memory"
);
#endif // defined(__PIC__)
#else // !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
#if defined(__PIC__)
uint32_t scratch;
__asm__ __volatile__
(
"movl %%ebx, %[scratch]\n\t"
"movl %[value_lo], %%ebx\n\t"
"movl 0(%[dest]), %%eax\n\t"
"movl 4(%[dest]), %%edx\n\t"
".align 16\n\t"
"1: lock; cmpxchg8b 0(%[dest])\n\t"
"jne 1b\n\t"
"movl %[scratch], %%ebx\n\t"
#if !defined(BOOST_ATOMIC_DETAIL_NO_ASM_CONSTRAINT_ALTERNATIVES)
: [scratch] "=m,m" (scratch)
: [value_lo] "a,a" ((uint32_t)v), "c,c" ((uint32_t)(v >> 32)), [dest] "D,S" (&storage)
#else
: [scratch] "=m" (scratch)
: [value_lo] "a" ((uint32_t)v), "c" ((uint32_t)(v >> 32)), [dest] "D" (&storage)
#endif
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "edx", "memory"
);
#else // defined(__PIC__)
__asm__ __volatile__
(
"movl 0(%[dest]), %%eax\n\t"
"movl 4(%[dest]), %%edx\n\t"
".align 16\n\t"
"1: lock; cmpxchg8b 0(%[dest])\n\t"
"jne 1b\n\t"
:
#if !defined(BOOST_ATOMIC_DETAIL_NO_ASM_CONSTRAINT_ALTERNATIVES)
: [value_lo] "b,b" ((uint32_t)v), "c,c" ((uint32_t)(v >> 32)), [dest] "D,S" (&storage)
#else
: [value_lo] "b" ((uint32_t)v), "c" ((uint32_t)(v >> 32)), [dest] "D" (&storage)
#endif
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "eax", "edx", "memory"
);
#endif // defined(__PIC__)
#endif // !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
}
}
static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order) BOOST_NOEXCEPT
{
storage_type value;
if ((((uint32_t)&storage) & 0x00000007) == 0)
{
#if defined(__SSE2__)
__asm__ __volatile__
(
#if defined(__AVX__)
"vmovq %1, %%xmm4\n\t"
"vmovq %%xmm4, %0\n\t"
#else
"movq %1, %%xmm4\n\t"
"movq %%xmm4, %0\n\t"
#endif
: "=m" (value)
: "m" (storage)
: "memory", "xmm4"
);
#else
__asm__ __volatile__
(
"fildll %1\n\t"
"fistpll %0\n\t"
: "=m" (value)
: "m" (storage)
: "memory"
);
#endif
}
else
{
#if defined(__clang__)
// Clang cannot allocate eax:edx register pairs but it has sync intrinsics
value = __sync_val_compare_and_swap(&storage, (storage_type)0, (storage_type)0);
#else
// We don't care for comparison result here; the previous value will be stored into value anyway.
// Also we don't care for ebx and ecx values, they just have to be equal to eax and edx before cmpxchg8b.
__asm__ __volatile__
(
"movl %%ebx, %%eax\n\t"
"movl %%ecx, %%edx\n\t"
"lock; cmpxchg8b %[storage]\n\t"
: "=&A" (value)
: [storage] "m" (storage)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
#endif
}
return value;
}
static BOOST_FORCEINLINE bool compare_exchange_strong(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
{
#if defined(__clang__)
// Clang cannot allocate eax:edx register pairs but it has sync intrinsics
storage_type old_expected = expected;
expected = __sync_val_compare_and_swap(&storage, old_expected, desired);
return expected == old_expected;
#elif defined(__PIC__)
// Make sure ebx is saved and restored properly in case
// of position independent code. To make this work
// setup register constraints such that ebx can not be
// used by accident e.g. as base address for the variable
// to be modified. Accessing "scratch" should always be okay,
// as it can only be placed on the stack (and therefore
// accessed through ebp or esp only).
//
// In theory, could push/pop ebx onto/off the stack, but movs
// to a prepared stack slot turn out to be faster.
uint32_t scratch;
bool success;
__asm__ __volatile__
(
"movl %%ebx, %[scratch]\n\t"
"movl %[desired_lo], %%ebx\n\t"
"lock; cmpxchg8b %[dest]\n\t"
"movl %[scratch], %%ebx\n\t"
"sete %[success]\n\t"
#if !defined(BOOST_ATOMIC_DETAIL_NO_ASM_CONSTRAINT_ALTERNATIVES)
: "+A,A,A,A,A,A" (expected), [dest] "+m,m,m,m,m,m" (storage), [scratch] "=m,m,m,m,m,m" (scratch), [success] "=q,m,q,m,q,m" (success)
: [desired_lo] "S,S,D,D,m,m" ((uint32_t)desired), "c,c,c,c,c,c" ((uint32_t)(desired >> 32))
#else
: "+A" (expected), [dest] "+m" (storage), [scratch] "=m" (scratch), [success] "=q" (success)
: [desired_lo] "S" ((uint32_t)desired), "c" ((uint32_t)(desired >> 32))
#endif
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
return success;
#else
bool success;
__asm__ __volatile__
(
"lock; cmpxchg8b %[dest]\n\t"
"sete %[success]\n\t"
#if !defined(BOOST_ATOMIC_DETAIL_NO_ASM_CONSTRAINT_ALTERNATIVES)
: "+A,A" (expected), [dest] "+m,m" (storage), [success] "=q,m" (success)
: "b,b" ((uint32_t)desired), "c,c" ((uint32_t)(desired >> 32))
#else
: "+A" (expected), [dest] "+m" (storage), [success] "=q" (success)
: "b" ((uint32_t)desired), "c" ((uint32_t)(desired >> 32))
#endif
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
return success;
#endif
}
static BOOST_FORCEINLINE bool compare_exchange_weak(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
return compare_exchange_strong(storage, expected, desired, success_order, failure_order);
}
static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
#if defined(__clang__)
// Clang cannot allocate eax:edx register pairs but it has sync intrinsics
storage_type old_val = storage;
while (true)
{
storage_type val = __sync_val_compare_and_swap(&storage, old_val, v);
if (val == old_val)
return val;
old_val = val;
}
#elif !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
#if defined(__PIC__)
uint32_t scratch;
__asm__ __volatile__
(
"movl %%ebx, %[scratch]\n\t"
"movl %%eax, %%ebx\n\t"
"movl %%edx, %%ecx\n\t"
"movl %[dest], %%eax\n\t"
"movl 4+%[dest], %%edx\n\t"
".align 16\n\t"
"1: lock; cmpxchg8b %[dest]\n\t"
"jne 1b\n\t"
"movl %[scratch], %%ebx\n\t"
: "+A" (v), [scratch] "=m" (scratch), [dest] "+o" (storage)
:
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "ecx", "memory"
);
return v;
#else // defined(__PIC__)
__asm__ __volatile__
(
"movl %[dest], %%eax\n\t"
"movl 4+%[dest], %%edx\n\t"
".align 16\n\t"
"1: lock; cmpxchg8b %[dest]\n\t"
"jne 1b\n\t"
: "=A" (v), [dest] "+o" (storage)
: "b" ((uint32_t)v), "c" ((uint32_t)(v >> 32))
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
return v;
#endif // defined(__PIC__)
#else // !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
#if defined(__PIC__)
uint32_t scratch;
__asm__ __volatile__
(
"movl %%ebx, %[scratch]\n\t"
"movl %%eax, %%ebx\n\t"
"movl %%edx, %%ecx\n\t"
"movl 0(%[dest]), %%eax\n\t"
"movl 4(%[dest]), %%edx\n\t"
".align 16\n\t"
"1: lock; cmpxchg8b 0(%[dest])\n\t"
"jne 1b\n\t"
"movl %[scratch], %%ebx\n\t"
#if !defined(BOOST_ATOMIC_DETAIL_NO_ASM_CONSTRAINT_ALTERNATIVES)
: "+A,A" (v), [scratch] "=m,m" (scratch)
: [dest] "D,S" (&storage)
#else
: "+A" (v), [scratch] "=m" (scratch)
: [dest] "D" (&storage)
#endif
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "ecx", "memory"
);
return v;
#else // defined(__PIC__)
__asm__ __volatile__
(
"movl 0(%[dest]), %%eax\n\t"
"movl 4(%[dest]), %%edx\n\t"
".align 16\n\t"
"1: lock; cmpxchg8b 0(%[dest])\n\t"
"jne 1b\n\t"
#if !defined(BOOST_ATOMIC_DETAIL_NO_ASM_CONSTRAINT_ALTERNATIVES)
: "=A,A" (v)
: "b,b" ((uint32_t)v), "c,c" ((uint32_t)(v >> 32)), [dest] "D,S" (&storage)
#else
: "=A" (v)
: "b" ((uint32_t)v), "c" ((uint32_t)(v >> 32)), [dest] "D" (&storage)
#endif
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
return v;
#endif // defined(__PIC__)
#endif
}
static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
{
return true;
}
};
#endif // defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B)
#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B)
template< bool Signed >
struct gcc_dcas_x86_64
{
typedef typename make_storage_type< 16u, Signed >::type storage_type;
typedef typename make_storage_type< 16u, Signed >::aligned aligned_storage_type;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
uint64_t const* p_value = (uint64_t const*)&v;
#if !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
__asm__ __volatile__
(
"movq %[dest], %%rax\n\t"
"movq 8+%[dest], %%rdx\n\t"
".align 16\n\t"
"1: lock; cmpxchg16b %[dest]\n\t"
"jne 1b\n\t"
: [dest] "=o" (storage)
: "b" (p_value[0]), "c" (p_value[1])
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "rax", "rdx", "memory"
);
#else // !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
__asm__ __volatile__
(
"movq 0(%[dest]), %%rax\n\t"
"movq 8(%[dest]), %%rdx\n\t"
".align 16\n\t"
"1: lock; cmpxchg16b 0(%[dest])\n\t"
"jne 1b\n\t"
:
: "b" (p_value[0]), "c" (p_value[1]), [dest] "r" (&storage)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "rax", "rdx", "memory"
);
#endif // !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
}
static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order) BOOST_NOEXCEPT
{
#if defined(__clang__)
// Clang cannot allocate rax:rdx register pairs but it has sync intrinsics
storage_type value = storage_type();
return __sync_val_compare_and_swap(&storage, value, value);
#elif defined(BOOST_ATOMIC_DETAIL_NO_ASM_RAX_RDX_PAIRS)
// GCC 4.4 can't allocate rax:rdx register pair either but it also doesn't support 128-bit __sync_val_compare_and_swap
storage_type value;
// We don't care for comparison result here; the previous value will be stored into value anyway.
// Also we don't care for rbx and rcx values, they just have to be equal to rax and rdx before cmpxchg16b.
#if !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
__asm__ __volatile__
(
"movq %%rbx, %%rax\n\t"
"movq %%rcx, %%rdx\n\t"
"lock; cmpxchg16b %[storage]\n\t"
"movq %%rax, %[value]\n\t"
"movq %%rdx, 8+%[value]\n\t"
: [value] "=o" (value)
: [storage] "m" (storage)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory", "rax", "rdx"
);
#else // !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
__asm__ __volatile__
(
"movq %%rbx, %%rax\n\t"
"movq %%rcx, %%rdx\n\t"
"lock; cmpxchg16b %[storage]\n\t"
"movq %%rax, 0(%[value])\n\t"
"movq %%rdx, 8(%[value])\n\t"
:
: [storage] "m" (storage), [value] "r" (&value)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory", "rax", "rdx"
);
#endif // !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
return value;
#else // defined(BOOST_ATOMIC_DETAIL_NO_ASM_RAX_RDX_PAIRS)
storage_type value;
// We don't care for comparison result here; the previous value will be stored into value anyway.
// Also we don't care for rbx and rcx values, they just have to be equal to rax and rdx before cmpxchg16b.
__asm__ __volatile__
(
"movq %%rbx, %%rax\n\t"
"movq %%rcx, %%rdx\n\t"
"lock; cmpxchg16b %[storage]\n\t"
: "=&A" (value)
: [storage] "m" (storage)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
return value;
#endif
}
static BOOST_FORCEINLINE bool compare_exchange_strong(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
{
#if defined(__clang__)
// Clang cannot allocate rax:rdx register pairs but it has sync intrinsics
storage_type old_expected = expected;
expected = __sync_val_compare_and_swap(&storage, old_expected, desired);
return expected == old_expected;
#elif defined(BOOST_ATOMIC_DETAIL_NO_ASM_RAX_RDX_PAIRS)
// GCC 4.4 can't allocate rax:rdx register pair either but it also doesn't support 128-bit __sync_val_compare_and_swap
uint64_t const* p_desired = (uint64_t const*)&desired;
bool success;
#if !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
__asm__ __volatile__
(
"movq %[expected], %%rax\n\t"
"movq 8+%[expected], %%rdx\n\t"
"lock; cmpxchg16b %[dest]\n\t"
"sete %[success]\n\t"
"movq %%rax, %[expected]\n\t"
"movq %%rdx, 8+%[expected]\n\t"
: [dest] "+m" (storage), [expected] "+o" (expected), [success] "=q" (success)
: "b" (p_desired[0]), "c" (p_desired[1])
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory", "rax", "rdx"
);
#else // !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
__asm__ __volatile__
(
"movq 0(%[expected]), %%rax\n\t"
"movq 8(%[expected]), %%rdx\n\t"
"lock; cmpxchg16b %[dest]\n\t"
"sete %[success]\n\t"
"movq %%rax, 0(%[expected])\n\t"
"movq %%rdx, 8(%[expected])\n\t"
: [dest] "+m" (storage), [success] "=q" (success)
: "b" (p_desired[0]), "c" (p_desired[1]), [expected] "r" (&expected)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory", "rax", "rdx"
);
#endif // !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
return success;
#else // defined(BOOST_ATOMIC_DETAIL_NO_ASM_RAX_RDX_PAIRS)
uint64_t const* p_desired = (uint64_t const*)&desired;
bool success;
__asm__ __volatile__
(
"lock; cmpxchg16b %[dest]\n\t"
"sete %[success]\n\t"
#if !defined(BOOST_ATOMIC_DETAIL_NO_ASM_CONSTRAINT_ALTERNATIVES)
: "+A,A" (expected), [dest] "+m,m" (storage), [success] "=q,m" (success)
: "b,b" (p_desired[0]), "c,c" (p_desired[1])
#else
: "+A" (expected), [dest] "+m" (storage), [success] "=q" (success)
: "b" (p_desired[0]), "c" (p_desired[1])
#endif
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
return success;
#endif
}
static BOOST_FORCEINLINE bool compare_exchange_weak(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
return compare_exchange_strong(storage, expected, desired, success_order, failure_order);
}
static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
#if defined(__clang__)
// Clang cannot allocate eax:edx register pairs but it has sync intrinsics
storage_type old_val = storage;
while (true)
{
storage_type val = __sync_val_compare_and_swap(&storage, old_val, v);
if (val == old_val)
return val;
old_val = val;
}
#elif defined(BOOST_ATOMIC_DETAIL_NO_ASM_RAX_RDX_PAIRS)
// GCC 4.4 can't allocate rax:rdx register pair either but it also doesn't support 128-bit __sync_val_compare_and_swap
storage_type old_value;
uint64_t const* p_value = (uint64_t const*)&v;
#if !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
__asm__ __volatile__
(
"movq %[dest], %%rax\n\t"
"movq 8+%[dest], %%rdx\n\t"
".align 16\n\t"
"1: lock; cmpxchg16b %[dest]\n\t"
"jne 1b\n\t"
"movq %%rax, %[old_value]\n\t"
"movq %%rdx, 8+%[old_value]\n\t"
: [dest] "+o" (storage), [old_value] "=o" (old_value)
: "b" (p_value[0]), "c" (p_value[1])
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory", "rax", "rdx"
);
#else // !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
__asm__ __volatile__
(
"movq 0(%[dest]), %%rax\n\t"
"movq 8(%[dest]), %%rdx\n\t"
".align 16\n\t"
"1: lock; cmpxchg16b 0(%[dest])\n\t"
"jne 1b\n\t"
"movq %%rax, 0(%[old_value])\n\t"
"movq %%rdx, 8(%[old_value])\n\t"
:
: "b" (p_value[0]), "c" (p_value[1]), [dest] "r" (&storage), [old_value] "r" (&old_value)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory", "rax", "rdx"
);
#endif // !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
return old_value;
#else // defined(BOOST_ATOMIC_DETAIL_NO_ASM_RAX_RDX_PAIRS)
uint64_t const* p_value = (uint64_t const*)&v;
#if !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
__asm__ __volatile__
(
"movq %[dest], %%rax\n\t"
"movq 8+%[dest], %%rdx\n\t"
".align 16\n\t"
"1: lock; cmpxchg16b %[dest]\n\t"
"jne 1b\n\t"
: "=&A" (v), [dest] "+o" (storage)
: "b" (p_value[0]), "c" (p_value[1])
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
#else // !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
__asm__ __volatile__
(
"movq 0(%[dest]), %%rax\n\t"
"movq 8(%[dest]), %%rdx\n\t"
".align 16\n\t"
"1: lock; cmpxchg16b 0(%[dest])\n\t"
"jne 1b\n\t"
: "=&A" (v)
: "b" (p_value[0]), "c" (p_value[1]), [dest] "r" (&storage)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
#endif // !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
return v;
#endif
}
static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
{
return true;
}
};
#endif // defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B)
} // namespace detail
} // namespace atomics
} // namespace boost
#endif // BOOST_ATOMIC_DETAIL_OPS_GCC_X86_DCAS_HPP_INCLUDED_

View File

@@ -0,0 +1,178 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2009, 2011 Helge Bahmann
* Copyright (c) 2009 Phil Endecott
* Copyright (c) 2013 Tim Blechmann
* Linux-specific code by Phil Endecott
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/ops_linux_arm.hpp
*
* This header contains implementation of the \c operations template.
*/
#ifndef BOOST_ATOMIC_DETAIL_OPS_LINUX_ARM_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_OPS_LINUX_ARM_HPP_INCLUDED_
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/detail/operations_fwd.hpp>
#include <boost/atomic/capabilities.hpp>
#include <boost/atomic/detail/ops_cas_based.hpp>
#include <boost/atomic/detail/ops_extending_cas_based.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
// Different ARM processors have different atomic instructions. In particular,
// architecture versions before v6 (which are still in widespread use, e.g. the
// Intel/Marvell XScale chips like the one in the NSLU2) have only atomic swap.
// On Linux the kernel provides some support that lets us abstract away from
// these differences: it provides emulated CAS and barrier functions at special
// addresses that are guaranteed not to be interrupted by the kernel. Using
// this facility is slightly slower than inline assembler would be, but much
// faster than a system call.
//
// While this emulated CAS is "strong" in the sense that it does not fail
// "spuriously" (i.e.: it never fails to perform the exchange when the value
// found equals the value expected), it does not return the found value on
// failure. To satisfy the atomic API, compare_exchange_{weak|strong} must
// return the found value on failure, and we have to manually load this value
// after the emulated CAS reports failure. This in turn introduces a race
// between the CAS failing (due to the "wrong" value being found) and subsequently
// loading (which might turn up the "right" value). From an application's
// point of view this looks like "spurious failure", and therefore the
// emulated CAS is only good enough to provide compare_exchange_weak
// semantics.
struct linux_arm_cas_base
{
static BOOST_FORCEINLINE void fence_before_store(memory_order order) BOOST_NOEXCEPT
{
if ((order & memory_order_release) != 0)
hardware_full_fence();
}
static BOOST_FORCEINLINE void fence_after_store(memory_order order) BOOST_NOEXCEPT
{
if (order == memory_order_seq_cst)
hardware_full_fence();
}
static BOOST_FORCEINLINE void fence_after_load(memory_order order) BOOST_NOEXCEPT
{
if ((order & (memory_order_consume | memory_order_acquire)) != 0)
hardware_full_fence();
}
static BOOST_FORCEINLINE void hardware_full_fence() BOOST_NOEXCEPT
{
typedef void (*kernel_dmb_t)(void);
((kernel_dmb_t)0xffff0fa0)();
}
};
template< bool Signed >
struct linux_arm_cas :
public linux_arm_cas_base
{
typedef typename make_storage_type< 4u, Signed >::type storage_type;
typedef typename make_storage_type< 4u, Signed >::aligned aligned_storage_type;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
fence_before_store(order);
storage = v;
fence_after_store(order);
}
static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
{
storage_type v = storage;
fence_after_load(order);
return v;
}
static BOOST_FORCEINLINE bool compare_exchange_strong(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
while (true)
{
storage_type tmp = expected;
if (compare_exchange_weak(storage, tmp, desired, success_order, failure_order))
return true;
if (tmp != expected)
{
expected = tmp;
return false;
}
}
}
static BOOST_FORCEINLINE bool compare_exchange_weak(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
{
typedef storage_type (*kernel_cmpxchg32_t)(storage_type oldval, storage_type newval, volatile storage_type* ptr);
if (((kernel_cmpxchg32_t)0xffff0fc0)(expected, desired, &storage) == 0)
{
return true;
}
else
{
expected = storage;
return false;
}
}
static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
{
return true;
}
};
template< bool Signed >
struct operations< 1u, Signed > :
public extending_cas_based_operations< cas_based_operations< cas_based_exchange< linux_arm_cas< Signed > > >, 1u, Signed >
{
};
template< bool Signed >
struct operations< 2u, Signed > :
public extending_cas_based_operations< cas_based_operations< cas_based_exchange< linux_arm_cas< Signed > > >, 2u, Signed >
{
};
template< bool Signed >
struct operations< 4u, Signed > :
public cas_based_operations< cas_based_exchange< linux_arm_cas< Signed > > >
{
};
BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
linux_arm_cas_base::hardware_full_fence();
}
BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
__asm__ __volatile__ ("" ::: "memory");
}
} // namespace detail
} // namespace atomics
} // namespace boost
#endif // BOOST_ATOMIC_DETAIL_OPS_LINUX_ARM_HPP_INCLUDED_

View File

@@ -0,0 +1,824 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2009 Helge Bahmann
* Copyright (c) 2012 Tim Blechmann
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/ops_msvc_arm.hpp
*
* This header contains implementation of the \c operations template.
*/
#ifndef BOOST_ATOMIC_DETAIL_OPS_MSVC_ARM_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_OPS_MSVC_ARM_HPP_INCLUDED_
#include <intrin.h>
#include <boost/memory_order.hpp>
#include <boost/type_traits/make_signed.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/interlocked.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/detail/operations_fwd.hpp>
#include <boost/atomic/capabilities.hpp>
#include <boost/atomic/detail/ops_msvc_common.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#define BOOST_ATOMIC_DETAIL_ARM_LOAD8(p) __iso_volatile_load8((const volatile __int8*)(p))
#define BOOST_ATOMIC_DETAIL_ARM_LOAD16(p) __iso_volatile_load16((const volatile __int16*)(p))
#define BOOST_ATOMIC_DETAIL_ARM_LOAD32(p) __iso_volatile_load32((const volatile __int32*)(p))
#define BOOST_ATOMIC_DETAIL_ARM_LOAD64(p) __iso_volatile_load64((const volatile __int64*)(p))
#define BOOST_ATOMIC_DETAIL_ARM_STORE8(p, v) __iso_volatile_store8((volatile __int8*)(p), (__int8)(v))
#define BOOST_ATOMIC_DETAIL_ARM_STORE16(p, v) __iso_volatile_store16((volatile __int16*)(p), (__int16)(v))
#define BOOST_ATOMIC_DETAIL_ARM_STORE32(p, v) __iso_volatile_store32((volatile __int32*)(p), (__int32)(v))
#define BOOST_ATOMIC_DETAIL_ARM_STORE64(p, v) __iso_volatile_store64((volatile __int64*)(p), (__int64)(v))
namespace boost {
namespace atomics {
namespace detail {
// A note about memory_order_consume. Technically, this architecture allows to avoid
// unnecessary memory barrier after consume load since it supports data dependency ordering.
// However, some compiler optimizations may break a seemingly valid code relying on data
// dependency tracking by injecting bogus branches to aid out of order execution.
// This may happen not only in Boost.Atomic code but also in user's code, which we have no
// control of. See this thread: http://lists.boost.org/Archives/boost/2014/06/213890.php.
// For this reason we promote memory_order_consume to memory_order_acquire.
struct msvc_arm_operations_base
{
static BOOST_FORCEINLINE void hardware_full_fence() BOOST_NOEXCEPT
{
__dmb(0xB); // _ARM_BARRIER_ISH, see armintr.h from MSVC 11 and later
}
static BOOST_FORCEINLINE void fence_before_store(memory_order order) BOOST_NOEXCEPT
{
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
if ((order & memory_order_release) != 0)
hardware_full_fence();
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
}
static BOOST_FORCEINLINE void fence_after_store(memory_order order) BOOST_NOEXCEPT
{
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
if (order == memory_order_seq_cst)
hardware_full_fence();
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
}
static BOOST_FORCEINLINE void fence_after_load(memory_order order) BOOST_NOEXCEPT
{
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
if ((order & (memory_order_consume | memory_order_acquire)) != 0)
hardware_full_fence();
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
}
static BOOST_FORCEINLINE BOOST_CONSTEXPR memory_order cas_common_order(memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
// Combine order flags together and promote memory_order_consume to memory_order_acquire
return static_cast< memory_order >(((failure_order | success_order) & ~memory_order_consume) | (((failure_order | success_order) & memory_order_consume) << 1u));
}
};
template< typename T, typename Derived >
struct msvc_arm_operations :
public msvc_arm_operations_base
{
typedef T storage_type;
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
typedef typename make_signed< storage_type >::type signed_storage_type;
return Derived::fetch_add(storage, static_cast< storage_type >(-static_cast< signed_storage_type >(v)), order);
}
static BOOST_FORCEINLINE bool compare_exchange_weak(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
return Derived::compare_exchange_strong(storage, expected, desired, success_order, failure_order);
}
static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
return !!Derived::exchange(storage, (storage_type)1, order);
}
static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
Derived::store(storage, (storage_type)0, order);
}
static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
{
return true;
}
};
template< bool Signed >
struct operations< 1u, Signed > :
public msvc_arm_operations< typename make_storage_type< 1u, Signed >::type, operations< 1u, Signed > >
{
typedef msvc_arm_operations< typename make_storage_type< 1u, Signed >::type, operations< 1u, Signed > > base_type;
typedef typename base_type::storage_type storage_type;
typedef typename make_storage_type< 1u, Signed >::aligned aligned_storage_type;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
base_type::fence_before_store(order);
BOOST_ATOMIC_DETAIL_ARM_STORE8(&storage, v);
base_type::fence_after_store(order);
}
static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
{
storage_type v = BOOST_ATOMIC_DETAIL_ARM_LOAD8(&storage);
base_type::fence_after_load(order);
return v;
}
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
switch (order)
{
case memory_order_relaxed:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD8_RELAXED(&storage, v));
break;
case memory_order_consume:
case memory_order_acquire:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD8_ACQUIRE(&storage, v));
break;
case memory_order_release:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD8_RELEASE(&storage, v));
break;
case memory_order_acq_rel:
case memory_order_seq_cst:
default:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD8(&storage, v));
break;
}
return v;
}
static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
switch (order)
{
case memory_order_relaxed:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE8_RELAXED(&storage, v));
break;
case memory_order_consume:
case memory_order_acquire:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE8_ACQUIRE(&storage, v));
break;
case memory_order_release:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE8_RELEASE(&storage, v));
break;
case memory_order_acq_rel:
case memory_order_seq_cst:
default:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE8(&storage, v));
break;
}
return v;
}
static BOOST_FORCEINLINE bool compare_exchange_strong(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
storage_type previous = expected, old_val;
switch (cas_common_order(success_order, failure_order))
{
case memory_order_relaxed:
old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE8_RELAXED(&storage, desired, previous));
break;
case memory_order_consume:
case memory_order_acquire:
old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE8_ACQUIRE(&storage, desired, previous));
break;
case memory_order_release:
old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE8_RELEASE(&storage, desired, previous));
break;
case memory_order_acq_rel:
case memory_order_seq_cst:
default:
old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE8(&storage, desired, previous));
break;
}
expected = old_val;
return (previous == old_val);
}
static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
switch (order)
{
case memory_order_relaxed:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND8_RELAXED(&storage, v));
break;
case memory_order_consume:
case memory_order_acquire:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND8_ACQUIRE(&storage, v));
break;
case memory_order_release:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND8_RELEASE(&storage, v));
break;
case memory_order_acq_rel:
case memory_order_seq_cst:
default:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND8(&storage, v));
break;
}
return v;
}
static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
switch (order)
{
case memory_order_relaxed:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR8_RELAXED(&storage, v));
break;
case memory_order_consume:
case memory_order_acquire:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR8_ACQUIRE(&storage, v));
break;
case memory_order_release:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR8_RELEASE(&storage, v));
break;
case memory_order_acq_rel:
case memory_order_seq_cst:
default:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR8(&storage, v));
break;
}
return v;
}
static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
switch (order)
{
case memory_order_relaxed:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR8_RELAXED(&storage, v));
break;
case memory_order_consume:
case memory_order_acquire:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR8_ACQUIRE(&storage, v));
break;
case memory_order_release:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR8_RELEASE(&storage, v));
break;
case memory_order_acq_rel:
case memory_order_seq_cst:
default:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR8(&storage, v));
break;
}
return v;
}
};
template< bool Signed >
struct operations< 2u, Signed > :
public msvc_arm_operations< typename make_storage_type< 2u, Signed >::type, operations< 2u, Signed > >
{
typedef msvc_arm_operations< typename make_storage_type< 2u, Signed >::type, operations< 2u, Signed > > base_type;
typedef typename base_type::storage_type storage_type;
typedef typename make_storage_type< 2u, Signed >::aligned aligned_storage_type;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
base_type::fence_before_store(order);
BOOST_ATOMIC_DETAIL_ARM_STORE16(&storage, v);
base_type::fence_after_store(order);
}
static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
{
storage_type v = BOOST_ATOMIC_DETAIL_ARM_LOAD16(&storage);
base_type::fence_after_load(order);
return v;
}
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
switch (order)
{
case memory_order_relaxed:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD16_RELAXED(&storage, v));
break;
case memory_order_consume:
case memory_order_acquire:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD16_ACQUIRE(&storage, v));
break;
case memory_order_release:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD16_RELEASE(&storage, v));
break;
case memory_order_acq_rel:
case memory_order_seq_cst:
default:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD16(&storage, v));
break;
}
return v;
}
static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
switch (order)
{
case memory_order_relaxed:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE16_RELAXED(&storage, v));
break;
case memory_order_consume:
case memory_order_acquire:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE16_ACQUIRE(&storage, v));
break;
case memory_order_release:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE16_RELEASE(&storage, v));
break;
case memory_order_acq_rel:
case memory_order_seq_cst:
default:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE16(&storage, v));
break;
}
return v;
}
static BOOST_FORCEINLINE bool compare_exchange_strong(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
storage_type previous = expected, old_val;
switch (cas_common_order(success_order, failure_order))
{
case memory_order_relaxed:
old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE16_RELAXED(&storage, desired, previous));
break;
case memory_order_consume:
case memory_order_acquire:
old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE16_ACQUIRE(&storage, desired, previous));
break;
case memory_order_release:
old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE16_RELEASE(&storage, desired, previous));
break;
case memory_order_acq_rel:
case memory_order_seq_cst:
default:
old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE16(&storage, desired, previous));
break;
}
expected = old_val;
return (previous == old_val);
}
static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
switch (order)
{
case memory_order_relaxed:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND16_RELAXED(&storage, v));
break;
case memory_order_consume:
case memory_order_acquire:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND16_ACQUIRE(&storage, v));
break;
case memory_order_release:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND16_RELEASE(&storage, v));
break;
case memory_order_acq_rel:
case memory_order_seq_cst:
default:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND16(&storage, v));
break;
}
return v;
}
static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
switch (order)
{
case memory_order_relaxed:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR16_RELAXED(&storage, v));
break;
case memory_order_consume:
case memory_order_acquire:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR16_ACQUIRE(&storage, v));
break;
case memory_order_release:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR16_RELEASE(&storage, v));
break;
case memory_order_acq_rel:
case memory_order_seq_cst:
default:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR16(&storage, v));
break;
}
return v;
}
static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
switch (order)
{
case memory_order_relaxed:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR16_RELAXED(&storage, v));
break;
case memory_order_consume:
case memory_order_acquire:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR16_ACQUIRE(&storage, v));
break;
case memory_order_release:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR16_RELEASE(&storage, v));
break;
case memory_order_acq_rel:
case memory_order_seq_cst:
default:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR16(&storage, v));
break;
}
return v;
}
};
template< bool Signed >
struct operations< 4u, Signed > :
public msvc_arm_operations< typename make_storage_type< 4u, Signed >::type, operations< 4u, Signed > >
{
typedef msvc_arm_operations< typename make_storage_type< 4u, Signed >::type, operations< 4u, Signed > > base_type;
typedef typename base_type::storage_type storage_type;
typedef typename make_storage_type< 4u, Signed >::aligned aligned_storage_type;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
base_type::fence_before_store(order);
BOOST_ATOMIC_DETAIL_ARM_STORE32(&storage, v);
base_type::fence_after_store(order);
}
static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
{
storage_type v = BOOST_ATOMIC_DETAIL_ARM_LOAD32(&storage);
base_type::fence_after_load(order);
return v;
}
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
switch (order)
{
case memory_order_relaxed:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_RELAXED(&storage, v));
break;
case memory_order_consume:
case memory_order_acquire:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_ACQUIRE(&storage, v));
break;
case memory_order_release:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_RELEASE(&storage, v));
break;
case memory_order_acq_rel:
case memory_order_seq_cst:
default:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(&storage, v));
break;
}
return v;
}
static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
switch (order)
{
case memory_order_relaxed:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_RELAXED(&storage, v));
break;
case memory_order_consume:
case memory_order_acquire:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ACQUIRE(&storage, v));
break;
case memory_order_release:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_RELEASE(&storage, v));
break;
case memory_order_acq_rel:
case memory_order_seq_cst:
default:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE(&storage, v));
break;
}
return v;
}
static BOOST_FORCEINLINE bool compare_exchange_strong(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
storage_type previous = expected, old_val;
switch (cas_common_order(success_order, failure_order))
{
case memory_order_relaxed:
old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_RELAXED(&storage, desired, previous));
break;
case memory_order_consume:
case memory_order_acquire:
old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_ACQUIRE(&storage, desired, previous));
break;
case memory_order_release:
old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_RELEASE(&storage, desired, previous));
break;
case memory_order_acq_rel:
case memory_order_seq_cst:
default:
old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(&storage, desired, previous));
break;
}
expected = old_val;
return (previous == old_val);
}
static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
switch (order)
{
case memory_order_relaxed:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND_RELAXED(&storage, v));
break;
case memory_order_consume:
case memory_order_acquire:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND_ACQUIRE(&storage, v));
break;
case memory_order_release:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND_RELEASE(&storage, v));
break;
case memory_order_acq_rel:
case memory_order_seq_cst:
default:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND(&storage, v));
break;
}
return v;
}
static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
switch (order)
{
case memory_order_relaxed:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR_RELAXED(&storage, v));
break;
case memory_order_consume:
case memory_order_acquire:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR_ACQUIRE(&storage, v));
break;
case memory_order_release:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR_RELEASE(&storage, v));
break;
case memory_order_acq_rel:
case memory_order_seq_cst:
default:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR(&storage, v));
break;
}
return v;
}
static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
switch (order)
{
case memory_order_relaxed:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR_RELAXED(&storage, v));
break;
case memory_order_consume:
case memory_order_acquire:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR_ACQUIRE(&storage, v));
break;
case memory_order_release:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR_RELEASE(&storage, v));
break;
case memory_order_acq_rel:
case memory_order_seq_cst:
default:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR(&storage, v));
break;
}
return v;
}
};
template< bool Signed >
struct operations< 8u, Signed > :
public msvc_arm_operations< typename make_storage_type< 8u, Signed >::type, operations< 8u, Signed > >
{
typedef msvc_arm_operations< typename make_storage_type< 8u, Signed >::type, operations< 8u, Signed > > base_type;
typedef typename base_type::storage_type storage_type;
typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
base_type::fence_before_store(order);
BOOST_ATOMIC_DETAIL_ARM_STORE64(&storage, v);
base_type::fence_after_store(order);
}
static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
{
storage_type v = BOOST_ATOMIC_DETAIL_ARM_LOAD64(&storage);
base_type::fence_after_load(order);
return v;
}
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
switch (order)
{
case memory_order_relaxed:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64_RELAXED(&storage, v));
break;
case memory_order_consume:
case memory_order_acquire:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64_ACQUIRE(&storage, v));
break;
case memory_order_release:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64_RELEASE(&storage, v));
break;
case memory_order_acq_rel:
case memory_order_seq_cst:
default:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64(&storage, v));
break;
}
return v;
}
static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
switch (order)
{
case memory_order_relaxed:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE64_RELAXED(&storage, v));
break;
case memory_order_consume:
case memory_order_acquire:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE64_ACQUIRE(&storage, v));
break;
case memory_order_release:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE64_RELEASE(&storage, v));
break;
case memory_order_acq_rel:
case memory_order_seq_cst:
default:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE64(&storage, v));
break;
}
return v;
}
static BOOST_FORCEINLINE bool compare_exchange_strong(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
storage_type previous = expected, old_val;
switch (cas_common_order(success_order, failure_order))
{
case memory_order_relaxed:
old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64_RELAXED(&storage, desired, previous));
break;
case memory_order_consume:
case memory_order_acquire:
old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64_ACQUIRE(&storage, desired, previous));
break;
case memory_order_release:
old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64_RELEASE(&storage, desired, previous));
break;
case memory_order_acq_rel:
case memory_order_seq_cst:
default:
old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64(&storage, desired, previous));
break;
}
expected = old_val;
return (previous == old_val);
}
static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
switch (order)
{
case memory_order_relaxed:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND64_RELAXED(&storage, v));
break;
case memory_order_consume:
case memory_order_acquire:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND64_ACQUIRE(&storage, v));
break;
case memory_order_release:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND64_RELEASE(&storage, v));
break;
case memory_order_acq_rel:
case memory_order_seq_cst:
default:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND64(&storage, v));
break;
}
return v;
}
static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
switch (order)
{
case memory_order_relaxed:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR64_RELAXED(&storage, v));
break;
case memory_order_consume:
case memory_order_acquire:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR64_ACQUIRE(&storage, v));
break;
case memory_order_release:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR64_RELEASE(&storage, v));
break;
case memory_order_acq_rel:
case memory_order_seq_cst:
default:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR64(&storage, v));
break;
}
return v;
}
static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
switch (order)
{
case memory_order_relaxed:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR64_RELAXED(&storage, v));
break;
case memory_order_consume:
case memory_order_acquire:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR64_ACQUIRE(&storage, v));
break;
case memory_order_release:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR64_RELEASE(&storage, v));
break;
case memory_order_acq_rel:
case memory_order_seq_cst:
default:
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR64(&storage, v));
break;
}
return v;
}
};
BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
{
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
if (order != memory_order_relaxed)
msvc_arm_operations_base::hardware_full_fence();
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
}
BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
}
} // namespace detail
} // namespace atomics
} // namespace boost
#undef BOOST_ATOMIC_DETAIL_ARM_LOAD8
#undef BOOST_ATOMIC_DETAIL_ARM_LOAD16
#undef BOOST_ATOMIC_DETAIL_ARM_LOAD32
#undef BOOST_ATOMIC_DETAIL_ARM_LOAD64
#undef BOOST_ATOMIC_DETAIL_ARM_STORE8
#undef BOOST_ATOMIC_DETAIL_ARM_STORE16
#undef BOOST_ATOMIC_DETAIL_ARM_STORE32
#undef BOOST_ATOMIC_DETAIL_ARM_STORE64
#endif // BOOST_ATOMIC_DETAIL_OPS_MSVC_ARM_HPP_INCLUDED_

View File

@@ -0,0 +1,38 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2009 Helge Bahmann
* Copyright (c) 2012 Tim Blechmann
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/ops_msvc_common.hpp
*
* This header contains common tools for MSVC implementation of the \c operations template.
*/
#ifndef BOOST_ATOMIC_DETAIL_OPS_MSVC_COMMON_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_OPS_MSVC_COMMON_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
// Define compiler barriers
#if defined(__INTEL_COMPILER)
#define BOOST_ATOMIC_DETAIL_COMPILER_BARRIER() __memory_barrier()
#elif defined(_MSC_VER) && !defined(_WIN32_WCE)
extern "C" void _ReadWriteBarrier(void);
#pragma intrinsic(_ReadWriteBarrier)
#define BOOST_ATOMIC_DETAIL_COMPILER_BARRIER() _ReadWriteBarrier()
#endif
#ifndef BOOST_ATOMIC_DETAIL_COMPILER_BARRIER
#define BOOST_ATOMIC_DETAIL_COMPILER_BARRIER()
#endif
#endif // BOOST_ATOMIC_DETAIL_OPS_MSVC_COMMON_HPP_INCLUDED_

View File

@@ -0,0 +1,928 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2009 Helge Bahmann
* Copyright (c) 2012 Tim Blechmann
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/ops_msvc_x86.hpp
*
* This header contains implementation of the \c operations template.
*/
#ifndef BOOST_ATOMIC_DETAIL_OPS_MSVC_X86_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_OPS_MSVC_X86_HPP_INCLUDED_
#include <boost/memory_order.hpp>
#include <boost/type_traits/make_signed.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/interlocked.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/detail/operations_fwd.hpp>
#include <boost/atomic/capabilities.hpp>
#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B) || defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B)
#include <boost/cstdint.hpp>
#include <boost/atomic/detail/ops_cas_based.hpp>
#endif
#include <boost/atomic/detail/ops_msvc_common.hpp>
#if !defined(_M_IX86) && !(defined(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE8) && defined(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE16))
#include <boost/atomic/detail/ops_extending_cas_based.hpp>
#endif
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if defined(BOOST_MSVC)
#pragma warning(push)
// frame pointer register 'ebx' modified by inline assembly code. See the note below.
#pragma warning(disable: 4731)
#endif
#if defined(_MSC_VER) && (defined(_M_AMD64) || (defined(_M_IX86) && defined(_M_IX86_FP) && _M_IX86_FP >= 2))
extern "C" void _mm_mfence(void);
#if defined(BOOST_MSVC)
#pragma intrinsic(_mm_mfence)
#endif
#endif
namespace boost {
namespace atomics {
namespace detail {
/*
* Implementation note for asm blocks.
*
* http://msdn.microsoft.com/en-us/data/k1a8ss06%28v=vs.105%29
*
* Some SSE types require eight-byte stack alignment, forcing the compiler to emit dynamic stack-alignment code.
* To be able to access both the local variables and the function parameters after the alignment, the compiler
* maintains two frame pointers. If the compiler performs frame pointer omission (FPO), it will use EBP and ESP.
* If the compiler does not perform FPO, it will use EBX and EBP. To ensure code runs correctly, do not modify EBX
* in asm code if the function requires dynamic stack alignment as it could modify the frame pointer.
* Either move the eight-byte aligned types out of the function, or avoid using EBX.
*
* Since we have no way of knowing that the compiler uses FPO, we have to always save and restore ebx
* whenever we have to clobber it. Additionally, we disable warning C4731 above so that the compiler
* doesn't spam about ebx use.
*/
struct msvc_x86_operations_base
{
static BOOST_FORCEINLINE void hardware_full_fence() BOOST_NOEXCEPT
{
#if defined(_MSC_VER) && (defined(_M_AMD64) || (defined(_M_IX86) && defined(_M_IX86_FP) && _M_IX86_FP >= 2))
// Use mfence only if SSE2 is available
_mm_mfence();
#else
long tmp;
BOOST_ATOMIC_INTERLOCKED_EXCHANGE(&tmp, 0);
#endif
}
static BOOST_FORCEINLINE void fence_before(memory_order) BOOST_NOEXCEPT
{
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
}
static BOOST_FORCEINLINE void fence_after(memory_order) BOOST_NOEXCEPT
{
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
}
static BOOST_FORCEINLINE void fence_after_load(memory_order) BOOST_NOEXCEPT
{
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
// On x86 and x86_64 there is no need for a hardware barrier,
// even if seq_cst memory order is requested, because all
// seq_cst writes are implemented with lock-prefixed operations
// or xchg which has implied lock prefix. Therefore normal loads
// are already ordered with seq_cst stores on these architectures.
}
};
template< typename T, typename Derived >
struct msvc_x86_operations :
public msvc_x86_operations_base
{
typedef T storage_type;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_seq_cst)
{
fence_before(order);
storage = v;
fence_after(order);
}
else
{
Derived::exchange(storage, v, order);
}
}
static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
{
storage_type v = storage;
fence_after_load(order);
return v;
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
typedef typename make_signed< storage_type >::type signed_storage_type;
return Derived::fetch_add(storage, static_cast< storage_type >(-static_cast< signed_storage_type >(v)), order);
}
static BOOST_FORCEINLINE bool compare_exchange_weak(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
return Derived::compare_exchange_strong(storage, expected, desired, success_order, failure_order);
}
static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
return !!Derived::exchange(storage, (storage_type)1, order);
}
static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
store(storage, (storage_type)0, order);
}
static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
{
return true;
}
};
template< bool Signed >
struct operations< 4u, Signed > :
public msvc_x86_operations< typename make_storage_type< 4u, Signed >::type, operations< 4u, Signed > >
{
typedef msvc_x86_operations< typename make_storage_type< 4u, Signed >::type, operations< 4u, Signed > > base_type;
typedef typename base_type::storage_type storage_type;
typedef typename make_storage_type< 4u, Signed >::aligned aligned_storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(&storage, v));
}
static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE(&storage, v));
}
static BOOST_FORCEINLINE bool compare_exchange_strong(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
{
storage_type previous = expected;
storage_type old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(&storage, desired, previous));
expected = old_val;
return (previous == old_val);
}
#if defined(BOOST_ATOMIC_INTERLOCKED_AND)
static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND(&storage, v));
}
#else
static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type res = storage;
while (!compare_exchange_strong(storage, res, res & v, order, memory_order_relaxed)) {}
return res;
}
#endif
#if defined(BOOST_ATOMIC_INTERLOCKED_OR)
static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR(&storage, v));
}
#else
static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type res = storage;
while (!compare_exchange_strong(storage, res, res | v, order, memory_order_relaxed)) {}
return res;
}
#endif
#if defined(BOOST_ATOMIC_INTERLOCKED_XOR)
static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR(&storage, v));
}
#else
static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type res = storage;
while (!compare_exchange_strong(storage, res, res ^ v, order, memory_order_relaxed)) {}
return res;
}
#endif
};
#if defined(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE8)
template< bool Signed >
struct operations< 1u, Signed > :
public msvc_x86_operations< typename make_storage_type< 1u, Signed >::type, operations< 1u, Signed > >
{
typedef msvc_x86_operations< typename make_storage_type< 1u, Signed >::type, operations< 1u, Signed > > base_type;
typedef typename base_type::storage_type storage_type;
typedef typename make_storage_type< 1u, Signed >::aligned aligned_storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD8(&storage, v));
}
static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE8(&storage, v));
}
static BOOST_FORCEINLINE bool compare_exchange_strong(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
{
storage_type previous = expected;
storage_type old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE8(&storage, desired, previous));
expected = old_val;
return (previous == old_val);
}
static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND8(&storage, v));
}
static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR8(&storage, v));
}
static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR8(&storage, v));
}
};
#elif defined(_M_IX86)
template< bool Signed >
struct operations< 1u, Signed > :
public msvc_x86_operations< typename make_storage_type< 1u, Signed >::type, operations< 1u, Signed > >
{
typedef msvc_x86_operations< typename make_storage_type< 1u, Signed >::type, operations< 1u, Signed > > base_type;
typedef typename base_type::storage_type storage_type;
typedef typename make_storage_type< 1u, Signed >::aligned aligned_storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
base_type::fence_before(order);
__asm
{
mov edx, storage
movzx eax, v
lock xadd byte ptr [edx], al
mov v, al
};
base_type::fence_after(order);
return v;
}
static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
base_type::fence_before(order);
__asm
{
mov edx, storage
movzx eax, v
xchg byte ptr [edx], al
mov v, al
};
base_type::fence_after(order);
return v;
}
static BOOST_FORCEINLINE bool compare_exchange_strong(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order) BOOST_NOEXCEPT
{
base_type::fence_before(success_order);
bool success;
__asm
{
mov esi, expected
mov edi, storage
movzx eax, byte ptr [esi]
movzx edx, desired
lock cmpxchg byte ptr [edi], dl
mov byte ptr [esi], al
sete success
};
// The success and failure fences are equivalent anyway
base_type::fence_after(success_order);
return success;
}
static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
base_type::fence_before(order);
int backup;
__asm
{
mov backup, ebx
xor edx, edx
mov edi, storage
movzx ebx, v
movzx eax, byte ptr [edi]
align 16
again:
mov dl, al
and dl, bl
lock cmpxchg byte ptr [edi], dl
jne again
mov v, al
mov ebx, backup
};
base_type::fence_after(order);
return v;
}
static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
base_type::fence_before(order);
int backup;
__asm
{
mov backup, ebx
xor edx, edx
mov edi, storage
movzx ebx, v
movzx eax, byte ptr [edi]
align 16
again:
mov dl, al
or dl, bl
lock cmpxchg byte ptr [edi], dl
jne again
mov v, al
mov ebx, backup
};
base_type::fence_after(order);
return v;
}
static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
base_type::fence_before(order);
int backup;
__asm
{
mov backup, ebx
xor edx, edx
mov edi, storage
movzx ebx, v
movzx eax, byte ptr [edi]
align 16
again:
mov dl, al
xor dl, bl
lock cmpxchg byte ptr [edi], dl
jne again
mov v, al
mov ebx, backup
};
base_type::fence_after(order);
return v;
}
};
#else
template< bool Signed >
struct operations< 1u, Signed > :
public extending_cas_based_operations< operations< 4u, Signed >, 1u, Signed >
{
};
#endif
#if defined(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE16)
template< bool Signed >
struct operations< 2u, Signed > :
public msvc_x86_operations< typename make_storage_type< 2u, Signed >::type, operations< 2u, Signed > >
{
typedef msvc_x86_operations< typename make_storage_type< 2u, Signed >::type, operations< 2u, Signed > > base_type;
typedef typename base_type::storage_type storage_type;
typedef typename make_storage_type< 2u, Signed >::aligned aligned_storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD16(&storage, v));
}
static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE16(&storage, v));
}
static BOOST_FORCEINLINE bool compare_exchange_strong(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
{
storage_type previous = expected;
storage_type old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE16(&storage, desired, previous));
expected = old_val;
return (previous == old_val);
}
static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND16(&storage, v));
}
static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR16(&storage, v));
}
static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR16(&storage, v));
}
};
#elif defined(_M_IX86)
template< bool Signed >
struct operations< 2u, Signed > :
public msvc_x86_operations< typename make_storage_type< 2u, Signed >::type, operations< 2u, Signed > >
{
typedef msvc_x86_operations< typename make_storage_type< 2u, Signed >::type, operations< 2u, Signed > > base_type;
typedef typename base_type::storage_type storage_type;
typedef typename make_storage_type< 2u, Signed >::aligned aligned_storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
base_type::fence_before(order);
__asm
{
mov edx, storage
movzx eax, v
lock xadd word ptr [edx], ax
mov v, ax
};
base_type::fence_after(order);
return v;
}
static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
base_type::fence_before(order);
__asm
{
mov edx, storage
movzx eax, v
xchg word ptr [edx], ax
mov v, ax
};
base_type::fence_after(order);
return v;
}
static BOOST_FORCEINLINE bool compare_exchange_strong(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order) BOOST_NOEXCEPT
{
base_type::fence_before(success_order);
bool success;
__asm
{
mov esi, expected
mov edi, storage
movzx eax, word ptr [esi]
movzx edx, desired
lock cmpxchg word ptr [edi], dx
mov word ptr [esi], ax
sete success
};
// The success and failure fences are equivalent anyway
base_type::fence_after(success_order);
return success;
}
static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
base_type::fence_before(order);
int backup;
__asm
{
mov backup, ebx
xor edx, edx
mov edi, storage
movzx ebx, v
movzx eax, word ptr [edi]
align 16
again:
mov dx, ax
and dx, bx
lock cmpxchg word ptr [edi], dx
jne again
mov v, ax
mov ebx, backup
};
base_type::fence_after(order);
return v;
}
static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
base_type::fence_before(order);
int backup;
__asm
{
mov backup, ebx
xor edx, edx
mov edi, storage
movzx ebx, v
movzx eax, word ptr [edi]
align 16
again:
mov dx, ax
or dx, bx
lock cmpxchg word ptr [edi], dx
jne again
mov v, ax
mov ebx, backup
};
base_type::fence_after(order);
return v;
}
static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
base_type::fence_before(order);
int backup;
__asm
{
mov backup, ebx
xor edx, edx
mov edi, storage
movzx ebx, v
movzx eax, word ptr [edi]
align 16
again:
mov dx, ax
xor dx, bx
lock cmpxchg word ptr [edi], dx
jne again
mov v, ax
mov ebx, backup
};
base_type::fence_after(order);
return v;
}
};
#else
template< bool Signed >
struct operations< 2u, Signed > :
public extending_cas_based_operations< operations< 4u, Signed >, 2u, Signed >
{
};
#endif
#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B)
template< bool Signed >
struct msvc_dcas_x86
{
typedef typename make_storage_type< 8u, Signed >::type storage_type;
typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type;
// Intel 64 and IA-32 Architectures Software Developer's Manual, Volume 3A, 8.1.1. Guaranteed Atomic Operations:
//
// The Pentium processor (and newer processors since) guarantees that the following additional memory operations will always be carried out atomically:
// * Reading or writing a quadword aligned on a 64-bit boundary
//
// Luckily, the memory is almost always 8-byte aligned in our case because atomic<> uses 64 bit native types for storage and dynamic memory allocations
// have at least 8 byte alignment. The only unfortunate case is when atomic is placed on the stack and it is not 8-byte aligned (like on 32 bit Windows).
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
storage_type volatile* p = &storage;
if (((uint32_t)p & 0x00000007) == 0)
{
#if defined(_M_IX86_FP) && _M_IX86_FP >= 2
#if defined(__AVX__)
__asm
{
mov edx, p
vmovq xmm4, v
vmovq qword ptr [edx], xmm4
};
#else
__asm
{
mov edx, p
movq xmm4, v
movq qword ptr [edx], xmm4
};
#endif
#else
__asm
{
mov edx, p
fild v
fistp qword ptr [edx]
};
#endif
}
else
{
int backup;
__asm
{
mov backup, ebx
mov edi, p
mov ebx, dword ptr [v]
mov ecx, dword ptr [v + 4]
mov eax, dword ptr [edi]
mov edx, dword ptr [edi + 4]
align 16
again:
lock cmpxchg8b qword ptr [edi]
jne again
mov ebx, backup
};
}
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
}
static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order) BOOST_NOEXCEPT
{
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
storage_type const volatile* p = &storage;
storage_type value;
if (((uint32_t)p & 0x00000007) == 0)
{
#if defined(_M_IX86_FP) && _M_IX86_FP >= 2
#if defined(__AVX__)
__asm
{
mov edx, p
vmovq xmm4, qword ptr [edx]
vmovq value, xmm4
};
#else
__asm
{
mov edx, p
movq xmm4, qword ptr [edx]
movq value, xmm4
};
#endif
#else
__asm
{
mov edx, p
fild qword ptr [edx]
fistp value
};
#endif
}
else
{
// We don't care for comparison result here; the previous value will be stored into value anyway.
// Also we don't care for ebx and ecx values, they just have to be equal to eax and edx before cmpxchg8b.
__asm
{
mov edi, p
mov eax, ebx
mov edx, ecx
lock cmpxchg8b qword ptr [edi]
mov dword ptr [value], eax
mov dword ptr [value + 4], edx
};
}
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
return value;
}
static BOOST_FORCEINLINE bool compare_exchange_strong(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
{
// MSVC-11 in 32-bit mode sometimes generates messed up code without compiler barriers,
// even though the _InterlockedCompareExchange64 intrinsic already provides one.
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
storage_type volatile* p = &storage;
#if defined(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64)
const storage_type old_val = (storage_type)BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64(p, desired, expected);
const bool result = (old_val == expected);
expected = old_val;
#else
bool result;
int backup;
__asm
{
mov backup, ebx
mov edi, p
mov esi, expected
mov ebx, dword ptr [desired]
mov ecx, dword ptr [desired + 4]
mov eax, dword ptr [esi]
mov edx, dword ptr [esi + 4]
lock cmpxchg8b qword ptr [edi]
mov dword ptr [esi], eax
mov dword ptr [esi + 4], edx
mov ebx, backup
sete result
};
#endif
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
return result;
}
static BOOST_FORCEINLINE bool compare_exchange_weak(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
return compare_exchange_strong(storage, expected, desired, success_order, failure_order);
}
static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
storage_type volatile* p = &storage;
int backup;
__asm
{
mov backup, ebx
mov edi, p
mov ebx, dword ptr [v]
mov ecx, dword ptr [v + 4]
mov eax, dword ptr [edi]
mov edx, dword ptr [edi + 4]
align 16
again:
lock cmpxchg8b qword ptr [edi]
jne again
mov ebx, backup
mov dword ptr [v], eax
mov dword ptr [v + 4], edx
};
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
return v;
}
static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
{
return true;
}
};
template< bool Signed >
struct operations< 8u, Signed > :
public cas_based_operations< msvc_dcas_x86< Signed > >
{
};
#elif defined(_M_AMD64)
template< bool Signed >
struct operations< 8u, Signed > :
public msvc_x86_operations< typename make_storage_type< 8u, Signed >::type, operations< 8u, Signed > >
{
typedef msvc_x86_operations< typename make_storage_type< 8u, Signed >::type, operations< 8u, Signed > > base_type;
typedef typename base_type::storage_type storage_type;
typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64(&storage, v));
}
static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE64(&storage, v));
}
static BOOST_FORCEINLINE bool compare_exchange_strong(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
{
storage_type previous = expected;
storage_type old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64(&storage, desired, previous));
expected = old_val;
return (previous == old_val);
}
static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND64(&storage, v));
}
static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR64(&storage, v));
}
static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR64(&storage, v));
}
};
#endif
#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B)
template< bool Signed >
struct msvc_dcas_x86_64
{
typedef typename make_storage_type< 16u, Signed >::type storage_type;
typedef typename make_storage_type< 16u, Signed >::aligned aligned_storage_type;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
storage_type value = const_cast< storage_type& >(storage);
while (!BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE128(&storage, v, &value)) {}
}
static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order) BOOST_NOEXCEPT
{
storage_type value = storage_type();
BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE128(&storage, value, &value);
return value;
}
static BOOST_FORCEINLINE bool compare_exchange_strong(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
{
return !!BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE128(&storage, desired, &expected);
}
static BOOST_FORCEINLINE bool compare_exchange_weak(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
return compare_exchange_strong(storage, expected, desired, success_order, failure_order);
}
static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
{
return true;
}
};
template< bool Signed >
struct operations< 16u, Signed > :
public cas_based_operations< cas_based_exchange< msvc_dcas_x86_64< Signed > > >
{
};
#endif // defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B)
BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
{
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
if (order == memory_order_seq_cst)
msvc_x86_operations_base::hardware_full_fence();
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
}
BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
}
} // namespace detail
} // namespace atomics
} // namespace boost
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
#endif // BOOST_ATOMIC_DETAIL_OPS_MSVC_X86_HPP_INCLUDED_

Some files were not shown because too many files have changed in this diff Show More