mirror of
https://github.com/Vita3K/ext-boost.git
synced 2024-11-23 05:29:39 +00:00
Initial commit
This commit is contained in:
commit
aea6b5c416
340
Jamroot
Normal file
340
Jamroot
Normal file
@ -0,0 +1,340 @@
|
||||
# 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 ;
|
||||
import notfile ;
|
||||
import virtual-target ;
|
||||
import "class" : new ;
|
||||
import property-set ;
|
||||
import threadapi-feature ;
|
||||
import option ;
|
||||
|
||||
path-constant BOOST_ROOT : . ;
|
||||
constant BOOST_VERSION : 1.67.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
|
||||
<conditional>@threadapi-feature.detect
|
||||
: 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 python-tag ( name : type ? : property-set )
|
||||
{
|
||||
return [ boostcpp.python-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) )
|
||||
{
|
||||
if ! $(.shared-static-warning-emitted)
|
||||
{
|
||||
ECHO "warning: skipping configuration link=shared, runtime-link=static" ;
|
||||
ECHO "warning: this combination is either impossible or too dangerous" ;
|
||||
ECHO "warning: to be of any use" ;
|
||||
.shared-static-warning-emitted = 1 ;
|
||||
}
|
||||
|
||||
return <build>no ;
|
||||
}
|
||||
}
|
||||
|
||||
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 ;
|
||||
|
||||
rule do-nothing { }
|
||||
|
||||
rule generate-alias ( project name : property-set : sources * )
|
||||
{
|
||||
local action-name = [ $(property-set).get <action> ] ;
|
||||
local m = [ MATCH ^@(.*) : $(action-name) ] ;
|
||||
property-set = [ property-set.empty ] ;
|
||||
local action = [ new action $(sources) : $(m[1]) : $(property-set) ] ;
|
||||
local t = [ new notfile-target $(name) : $(project) : $(action) ] ;
|
||||
return [ virtual-target.register $(t) ] ;
|
||||
}
|
||||
|
||||
generate headers : $(all-headers)-headers : <generating-rule>@generate-alias <action>@do-nothing : : <include>. ;
|
||||
|
||||
#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/build ]
|
||||
{
|
||||
use-project /boost/tools/inspect : tools/inspect/build ;
|
||||
}
|
||||
|
||||
if [ path.exists $(BOOST_ROOT)/libs/wave/tool/build ]
|
||||
{
|
||||
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.
|
||||
;
|
||||
|
||||
local stage-locate = [ option.get stagedir : $(BOOST_ROOT)/stage ] ;
|
||||
|
||||
install stage : $(libraries) : <location>$(stage-locate)/lib ;
|
||||
|
||||
module [ CALLER_MODULE ]
|
||||
{
|
||||
explicit stage ;
|
||||
explicit install ;
|
||||
}
|
||||
}
|
||||
|
||||
# Creates a library target, adding autolink support and also creates
|
||||
# stage and install targets via boost-install, above.
|
||||
rule boost-lib ( name : sources * : requirements * : default-build * : usage-requirements * )
|
||||
{
|
||||
name = boost_$(name) ;
|
||||
autolink = <link>shared:<define>$(name:U)_DYN_LINK=1 ;
|
||||
lib $(name)
|
||||
: $(sources)
|
||||
: $(requirements) $(autolink)
|
||||
: $(default-build)
|
||||
: $(usage-requirements) $(autolink)
|
||||
;
|
||||
boost-install $(name) ;
|
||||
}
|
||||
|
||||
|
||||
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_ROOT)/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) : $(all-headers) ;
|
23
LICENSE_1_0.txt
Normal file
23
LICENSE_1_0.txt
Normal 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.
|
24
README.md
Normal file
24
README.md
Normal file
@ -0,0 +1,24 @@
|
||||
Boost libraries - trimmed down for Vita3K
|
||||
========================================
|
||||
|
||||
This is a subset of Boost v1.67.0 generated using the bcp tool. To get a list of boost modules guaranteed to exist, check the build script.
|
||||
Adapted from [citra-emu/ext-boost](https://github.com/citra-emu/ext-boost).
|
||||
|
||||
Updating this repo (on Windows)
|
||||
===============================
|
||||
|
||||
To update the Boost version (or to add a new library) follow these steps:
|
||||
|
||||
- Download Boost and extract the package, then launch Powershell and `cd` to the `boost_1_xx_0` directory.
|
||||
- Build the `bcp` tool:
|
||||
```
|
||||
.\boostrap.bat
|
||||
.\b2 tools\bcp
|
||||
```
|
||||
|
||||
- Store the boost directory in a variable for later use: `$boost_dir = $pwd`.
|
||||
- `cd` to this repo's directory (`...\externals\boost\`)
|
||||
- Remove the existing boost from the repo: `rm -r boost` (This is only necessary if doing a Boost version upgrade, in case they removed any files in the new version.)
|
||||
- Run `.\build.cmd $boost_dir` to build a new trimmed down distro.
|
||||
- Copy the `tools/build/` directory from the untouched `boost_1_xx_0` zip to `./tools/build`. Alternatively we could include it with `bcp`'s files, but it would also include a bunch of build files (since we've built Boost build tools) that unecessarily increase the size.
|
||||
- Add/remove all files in git and commit.
|
17
boost-build.jam
Normal file
17
boost-build.jam
Normal file
@ -0,0 +1,17 @@
|
||||
# Copyright (C) 2002-2003 David Abrahams.
|
||||
# Copyright (C) 2002-2003 Vladimir Prus.
|
||||
# Copyright (C) 2003,2007 Rene Rivera.
|
||||
# Use, modification and distribution are subject to 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 is the initial file loaded by Boost Jam when run from any Boost library
|
||||
# folder. It allows us to choose which Boost Build installation to use for
|
||||
# building Boost libraries. Unless explicitly selected using a command-line
|
||||
# option, the version included with the Boost library distribution is used (as
|
||||
# opposed to any other Boost Build version installed on the user's sytem).
|
||||
|
||||
BOOST_ROOT = $(.boost-build-file:D) ;
|
||||
BOOST_BUILD = [ MATCH --boost-build=(.*) : $(ARGV) ] ;
|
||||
BOOST_BUILD ?= tools/build/src ;
|
||||
boost-build $(BOOST_BUILD) ;
|
83
boost/algorithm/cxx11/all_of.hpp
Normal file
83
boost/algorithm/cxx11/all_of.hpp
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
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 <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.
|
||||
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
|
312
boost/algorithm/string/classification.hpp
Normal file
312
boost/algorithm/string/classification.hpp
Normal 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
|
199
boost/algorithm/string/compare.hpp
Normal file
199
boost/algorithm/string/compare.hpp
Normal 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
|
83
boost/algorithm/string/concept.hpp
Normal file
83
boost/algorithm/string/concept.hpp
Normal 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
|
28
boost/algorithm/string/config.hpp
Normal file
28
boost/algorithm/string/config.hpp
Normal 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
|
36
boost/algorithm/string/constants.hpp
Normal file
36
boost/algorithm/string/constants.hpp
Normal 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
|
||||
|
353
boost/algorithm/string/detail/classification.hpp
Normal file
353
boost/algorithm/string/detail/classification.hpp
Normal 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
|
87
boost/algorithm/string/detail/find_iterator.hpp
Normal file
87
boost/algorithm/string/detail/find_iterator.hpp
Normal 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
|
639
boost/algorithm/string/detail/finder.hpp
Normal file
639
boost/algorithm/string/detail/finder.hpp
Normal 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
|
95
boost/algorithm/string/detail/trim.hpp
Normal file
95
boost/algorithm/string/detail/trim.hpp
Normal 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
|
107
boost/algorithm/string/detail/util.hpp
Normal file
107
boost/algorithm/string/detail/util.hpp
Normal file
@ -0,0 +1,107 @@
|
||||
// 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
|
||||
{
|
||||
typedef iterator_range<IteratorT> argument_type;
|
||||
typedef SeqT result_type;
|
||||
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
|
388
boost/algorithm/string/find_iterator.hpp
Normal file
388
boost/algorithm/string/find_iterator.hpp
Normal 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
|
270
boost/algorithm/string/finder.hpp
Normal file
270
boost/algorithm/string/finder.hpp
Normal 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
|
193
boost/algorithm/string/iter_find.hpp
Normal file
193
boost/algorithm/string/iter_find.hpp
Normal 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
|
42
boost/algorithm/string/predicate_facade.hpp
Normal file
42
boost/algorithm/string/predicate_facade.hpp
Normal 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
|
163
boost/algorithm/string/split.hpp
Normal file
163
boost/algorithm/string/split.hpp
Normal 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
|
||||
|
398
boost/algorithm/string/trim.hpp
Normal file
398
boost/algorithm/string/trim.hpp
Normal 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
|
18
boost/aligned_storage.hpp
Normal file
18
boost/aligned_storage.hpp
Normal 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
|
337
boost/any.hpp
Normal file
337
boost/any.hpp
Normal file
@ -0,0 +1,337 @@
|
||||
// See http://www.boost.org/libs/any for Documentation.
|
||||
|
||||
#ifndef BOOST_ANY_INCLUDED
|
||||
#define BOOST_ANY_INCLUDED
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
// what: variant type boost::any
|
||||
// who: contributed by Kevlin Henney,
|
||||
// with features contributed and bugs found by
|
||||
// Antony Polukhin, Ed Brey, Mark Rodgers,
|
||||
// Peter Dimov, and James Curran
|
||||
// when: July 2001, April 2013 - May 2013
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/type_index.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/type_traits/decay.hpp>
|
||||
#include <boost/type_traits/remove_cv.hpp>
|
||||
#include <boost/type_traits/add_reference.hpp>
|
||||
#include <boost/type_traits/is_reference.hpp>
|
||||
#include <boost/type_traits/is_const.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/core/addressof.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/is_const.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
class any
|
||||
{
|
||||
public: // structors
|
||||
|
||||
any() BOOST_NOEXCEPT
|
||||
: content(0)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename ValueType>
|
||||
any(const ValueType & value)
|
||||
: content(new holder<
|
||||
BOOST_DEDUCED_TYPENAME remove_cv<BOOST_DEDUCED_TYPENAME decay<const ValueType>::type>::type
|
||||
>(value))
|
||||
{
|
||||
}
|
||||
|
||||
any(const any & other)
|
||||
: content(other.content ? other.content->clone() : 0)
|
||||
{
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
// Move constructor
|
||||
any(any&& other) BOOST_NOEXCEPT
|
||||
: content(other.content)
|
||||
{
|
||||
other.content = 0;
|
||||
}
|
||||
|
||||
// Perfect forwarding of ValueType
|
||||
template<typename ValueType>
|
||||
any(ValueType&& value
|
||||
, typename boost::disable_if<boost::is_same<any&, ValueType> >::type* = 0 // disable if value has type `any&`
|
||||
, typename boost::disable_if<boost::is_const<ValueType> >::type* = 0) // disable if value has type `const ValueType&&`
|
||||
: content(new holder< typename decay<ValueType>::type >(static_cast<ValueType&&>(value)))
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
~any() BOOST_NOEXCEPT
|
||||
{
|
||||
delete content;
|
||||
}
|
||||
|
||||
public: // modifiers
|
||||
|
||||
any & swap(any & rhs) BOOST_NOEXCEPT
|
||||
{
|
||||
std::swap(content, rhs.content);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
template<typename ValueType>
|
||||
any & operator=(const ValueType & rhs)
|
||||
{
|
||||
any(rhs).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
any & operator=(any rhs)
|
||||
{
|
||||
any(rhs).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#else
|
||||
any & operator=(const any& rhs)
|
||||
{
|
||||
any(rhs).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// move assignement
|
||||
any & operator=(any&& rhs) BOOST_NOEXCEPT
|
||||
{
|
||||
rhs.swap(*this);
|
||||
any().swap(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Perfect forwarding of ValueType
|
||||
template <class ValueType>
|
||||
any & operator=(ValueType&& rhs)
|
||||
{
|
||||
any(static_cast<ValueType&&>(rhs)).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
public: // queries
|
||||
|
||||
bool empty() const BOOST_NOEXCEPT
|
||||
{
|
||||
return !content;
|
||||
}
|
||||
|
||||
void clear() BOOST_NOEXCEPT
|
||||
{
|
||||
any().swap(*this);
|
||||
}
|
||||
|
||||
const boost::typeindex::type_info& type() const BOOST_NOEXCEPT
|
||||
{
|
||||
return content ? content->type() : boost::typeindex::type_id<void>().type_info();
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
|
||||
private: // types
|
||||
#else
|
||||
public: // types (public so any_cast can be non-friend)
|
||||
#endif
|
||||
|
||||
class placeholder
|
||||
{
|
||||
public: // structors
|
||||
|
||||
virtual ~placeholder()
|
||||
{
|
||||
}
|
||||
|
||||
public: // queries
|
||||
|
||||
virtual const boost::typeindex::type_info& type() const BOOST_NOEXCEPT = 0;
|
||||
|
||||
virtual placeholder * clone() const = 0;
|
||||
|
||||
};
|
||||
|
||||
template<typename ValueType>
|
||||
class holder : public placeholder
|
||||
{
|
||||
public: // structors
|
||||
|
||||
holder(const ValueType & value)
|
||||
: held(value)
|
||||
{
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
holder(ValueType&& value)
|
||||
: held(static_cast< ValueType&& >(value))
|
||||
{
|
||||
}
|
||||
#endif
|
||||
public: // queries
|
||||
|
||||
virtual const boost::typeindex::type_info& type() const BOOST_NOEXCEPT
|
||||
{
|
||||
return boost::typeindex::type_id<ValueType>().type_info();
|
||||
}
|
||||
|
||||
virtual placeholder * clone() const
|
||||
{
|
||||
return new holder(held);
|
||||
}
|
||||
|
||||
public: // representation
|
||||
|
||||
ValueType held;
|
||||
|
||||
private: // intentionally left unimplemented
|
||||
holder & operator=(const holder &);
|
||||
};
|
||||
|
||||
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
|
||||
|
||||
private: // representation
|
||||
|
||||
template<typename ValueType>
|
||||
friend ValueType * any_cast(any *) BOOST_NOEXCEPT;
|
||||
|
||||
template<typename ValueType>
|
||||
friend ValueType * unsafe_any_cast(any *) BOOST_NOEXCEPT;
|
||||
|
||||
#else
|
||||
|
||||
public: // representation (public so any_cast can be non-friend)
|
||||
|
||||
#endif
|
||||
|
||||
placeholder * content;
|
||||
|
||||
};
|
||||
|
||||
inline void swap(any & lhs, any & rhs) BOOST_NOEXCEPT
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE bad_any_cast :
|
||||
#ifndef BOOST_NO_RTTI
|
||||
public std::bad_cast
|
||||
#else
|
||||
public std::exception
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
virtual const char * what() const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
return "boost::bad_any_cast: "
|
||||
"failed conversion using boost::any_cast";
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ValueType>
|
||||
ValueType * any_cast(any * operand) BOOST_NOEXCEPT
|
||||
{
|
||||
return operand && operand->type() == boost::typeindex::type_id<ValueType>()
|
||||
? boost::addressof(
|
||||
static_cast<any::holder<BOOST_DEDUCED_TYPENAME remove_cv<ValueType>::type> *>(operand->content)->held
|
||||
)
|
||||
: 0;
|
||||
}
|
||||
|
||||
template<typename ValueType>
|
||||
inline const ValueType * any_cast(const any * operand) BOOST_NOEXCEPT
|
||||
{
|
||||
return any_cast<ValueType>(const_cast<any *>(operand));
|
||||
}
|
||||
|
||||
template<typename ValueType>
|
||||
ValueType any_cast(any & operand)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref;
|
||||
|
||||
|
||||
nonref * result = any_cast<nonref>(boost::addressof(operand));
|
||||
if(!result)
|
||||
boost::throw_exception(bad_any_cast());
|
||||
|
||||
// Attempt to avoid construction of a temporary object in cases when
|
||||
// `ValueType` is not a reference. Example:
|
||||
// `static_cast<std::string>(*result);`
|
||||
// which is equal to `std::string(*result);`
|
||||
typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_<
|
||||
boost::is_reference<ValueType>,
|
||||
ValueType,
|
||||
BOOST_DEDUCED_TYPENAME boost::add_reference<ValueType>::type
|
||||
>::type ref_type;
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4172) // "returning address of local variable or temporary" but *result is not local!
|
||||
#endif
|
||||
return static_cast<ref_type>(*result);
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename ValueType>
|
||||
inline ValueType any_cast(const any & operand)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref;
|
||||
return any_cast<const nonref &>(const_cast<any &>(operand));
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
template<typename ValueType>
|
||||
inline ValueType any_cast(any&& operand)
|
||||
{
|
||||
BOOST_STATIC_ASSERT_MSG(
|
||||
boost::is_rvalue_reference<ValueType&&>::value /*true if ValueType is rvalue or just a value*/
|
||||
|| boost::is_const< typename boost::remove_reference<ValueType>::type >::value,
|
||||
"boost::any_cast shall not be used for getting nonconst references to temporary objects"
|
||||
);
|
||||
return any_cast<ValueType>(operand);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Note: The "unsafe" versions of any_cast are not part of the
|
||||
// public interface and may be removed at any time. They are
|
||||
// required where we know what type is stored in the any and can't
|
||||
// use typeid() comparison, e.g., when our types may travel across
|
||||
// different shared libraries.
|
||||
template<typename ValueType>
|
||||
inline ValueType * unsafe_any_cast(any * operand) BOOST_NOEXCEPT
|
||||
{
|
||||
return boost::addressof(
|
||||
static_cast<any::holder<ValueType> *>(operand->content)->held
|
||||
);
|
||||
}
|
||||
|
||||
template<typename ValueType>
|
||||
inline const ValueType * unsafe_any_cast(const any * operand) BOOST_NOEXCEPT
|
||||
{
|
||||
return unsafe_any_cast<ValueType>(const_cast<any *>(operand));
|
||||
}
|
||||
}
|
||||
|
||||
// Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved.
|
||||
//
|
||||
// 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)
|
||||
|
||||
#endif
|
457
boost/array.hpp
Normal file
457
boost/array.hpp
Normal file
@ -0,0 +1,457 @@
|
||||
/* 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)
|
||||
*
|
||||
* 9 Jan 2013 - (mtc) Added constexpr
|
||||
* 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/static_assert.hpp>
|
||||
#include <boost/swap.hpp>
|
||||
|
||||
// Handles broken standard libraries better than <iterator>
|
||||
#include <boost/detail/iterator.hpp>
|
||||
#include <boost/throw_exception.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_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(_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 BOOST_ASSERT_MSG( i < N, "out of range" ), elems[i];
|
||||
}
|
||||
|
||||
/*BOOST_CONSTEXPR*/ const_reference operator[](size_type i) const
|
||||
{
|
||||
return BOOST_ASSERT_MSG( i < N, "out of range" ), elems[i];
|
||||
}
|
||||
|
||||
// at() with range check
|
||||
reference at(size_type i) { return rangecheck(i), elems[i]; }
|
||||
/*BOOST_CONSTEXPR*/ const_reference at(size_type i) const { return rangecheck(i), elems[i]; }
|
||||
|
||||
// front() and back()
|
||||
reference front()
|
||||
{
|
||||
return elems[0];
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR const_reference front() const
|
||||
{
|
||||
return elems[0];
|
||||
}
|
||||
|
||||
reference back()
|
||||
{
|
||||
return elems[N-1];
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR const_reference back() const
|
||||
{
|
||||
return elems[N-1];
|
||||
}
|
||||
|
||||
// size is constant
|
||||
static BOOST_CONSTEXPR size_type size() { return N; }
|
||||
static BOOST_CONSTEXPR bool empty() { return false; }
|
||||
static BOOST_CONSTEXPR 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 BOOST_CONSTEXPR bool rangecheck (size_type i) {
|
||||
return i > size() ? boost::throw_exception(std::out_of_range ("array<>: index out of range")), true : true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
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_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(_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();
|
||||
}
|
||||
|
||||
/*BOOST_CONSTEXPR*/ const_reference operator[](size_type /*i*/) const
|
||||
{
|
||||
return failed_rangecheck();
|
||||
}
|
||||
|
||||
// at() with range check
|
||||
reference at(size_type /*i*/) { return failed_rangecheck(); }
|
||||
/*BOOST_CONSTEXPR*/ const_reference at(size_type /*i*/) const { return failed_rangecheck(); }
|
||||
|
||||
// front() and back()
|
||||
reference front()
|
||||
{
|
||||
return failed_rangecheck();
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR const_reference front() const
|
||||
{
|
||||
return failed_rangecheck();
|
||||
}
|
||||
|
||||
reference back()
|
||||
{
|
||||
return failed_rangecheck();
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR const_reference back() const
|
||||
{
|
||||
return failed_rangecheck();
|
||||
}
|
||||
|
||||
// size is constant
|
||||
static BOOST_CONSTEXPR size_type size() { return 0; }
|
||||
static BOOST_CONSTEXPR bool empty() { return true; }
|
||||
static BOOST_CONSTEXPR 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
|
||||
}
|
||||
};
|
||||
|
||||
// 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 detail::c_array<T,N>::type const& 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 It> std::size_t hash_range(It, It);
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
template <size_t Idx, typename T, size_t N>
|
||||
T &get(boost::array<T,N> &arr) BOOST_NOEXCEPT {
|
||||
BOOST_STATIC_ASSERT_MSG ( Idx < N, "boost::get<>(boost::array &) index out of range" );
|
||||
return arr[Idx];
|
||||
}
|
||||
|
||||
template <size_t Idx, typename T, size_t N>
|
||||
const T &get(const boost::array<T,N> &arr) BOOST_NOEXCEPT {
|
||||
BOOST_STATIC_ASSERT_MSG ( Idx < N, "boost::get<>(const boost::array &) index out of range" );
|
||||
return arr[Idx];
|
||||
}
|
||||
|
||||
} /* namespace boost */
|
||||
|
||||
#ifndef BOOST_NO_CXX11_HDR_ARRAY
|
||||
// If we don't have std::array, I'm assuming that we don't have std::get
|
||||
namespace std {
|
||||
template <size_t Idx, typename T, size_t N>
|
||||
T &get(boost::array<T,N> &arr) BOOST_NOEXCEPT {
|
||||
BOOST_STATIC_ASSERT_MSG ( Idx < N, "std::get<>(boost::array &) index out of range" );
|
||||
return arr[Idx];
|
||||
}
|
||||
|
||||
template <size_t Idx, typename T, size_t N>
|
||||
const T &get(const boost::array<T,N> &arr) BOOST_NOEXCEPT {
|
||||
BOOST_STATIC_ASSERT_MSG ( Idx < N, "std::get<>(const boost::array &) index out of range" );
|
||||
return arr[Idx];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif /*BOOST_ARRAY_HPP*/
|
85
boost/assert.hpp
Normal file
85
boost/assert.hpp
Normal 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
|
18
boost/atomic.hpp
Normal file
18
boost/atomic.hpp
Normal 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
|
104
boost/atomic/atomic.hpp
Normal file
104
boost/atomic/atomic.hpp
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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>
|
||||
#include <boost/atomic/detail/extra_operations.hpp>
|
||||
#if !defined(BOOST_ATOMIC_NO_FLOATING_POINT)
|
||||
#include <boost/atomic/detail/fp_operations.hpp>
|
||||
#include <boost/atomic/detail/extra_fp_operations.hpp>
|
||||
#endif
|
||||
|
||||
#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;
|
||||
|
||||
#if !defined(BOOST_ATOMIC_NO_FLOATING_POINT)
|
||||
using atomics::atomic_float_t;
|
||||
using atomics::atomic_double_t;
|
||||
using atomics::atomic_long_double_t;
|
||||
#endif
|
||||
|
||||
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_
|
33
boost/atomic/atomic_flag.hpp
Normal file
33
boost/atomic/atomic_flag.hpp
Normal 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_
|
210
boost/atomic/capabilities.hpp
Normal file
210
boost/atomic/capabilities.hpp
Normal file
@ -0,0 +1,210 @@
|
||||
/*
|
||||
* 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_NO_FLOATING_POINT)
|
||||
#include <boost/atomic/detail/float_sizes.hpp>
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_ATOMIC_EMULATED)
|
||||
#include BOOST_ATOMIC_DETAIL_BACKEND_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
|
||||
|
||||
#if !defined(BOOST_ATOMIC_NO_FLOATING_POINT)
|
||||
|
||||
#if !defined(BOOST_ATOMIC_FLOAT_LOCK_FREE) && defined(BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT)
|
||||
#if BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT == 2
|
||||
#define BOOST_ATOMIC_FLOAT_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE
|
||||
#elif BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT == 4
|
||||
#define BOOST_ATOMIC_FLOAT_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
|
||||
#elif BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT == 8
|
||||
#define BOOST_ATOMIC_FLOAT_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE
|
||||
#elif BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT == 16
|
||||
#define BOOST_ATOMIC_FLOAT_LOCK_FREE BOOST_ATOMIC_INT128_LOCK_FREE
|
||||
#else
|
||||
#define BOOST_ATOMIC_FLOAT_LOCK_FREE 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_ATOMIC_DOUBLE_LOCK_FREE) && defined(BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE)
|
||||
#if BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE == 2
|
||||
#define BOOST_ATOMIC_DOUBLE_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE
|
||||
#elif BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE == 4
|
||||
#define BOOST_ATOMIC_DOUBLE_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
|
||||
#elif BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE == 8
|
||||
#define BOOST_ATOMIC_DOUBLE_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE
|
||||
#elif BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE == 16
|
||||
#define BOOST_ATOMIC_DOUBLE_LOCK_FREE BOOST_ATOMIC_INT128_LOCK_FREE
|
||||
#else
|
||||
#define BOOST_ATOMIC_DOUBLE_LOCK_FREE 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_ATOMIC_LONG_DOUBLE_LOCK_FREE) && defined(BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE)
|
||||
#if BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE == 2
|
||||
#define BOOST_ATOMIC_LONG_DOUBLE_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE
|
||||
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE == 4
|
||||
#define BOOST_ATOMIC_LONG_DOUBLE_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
|
||||
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE == 8
|
||||
#define BOOST_ATOMIC_LONG_DOUBLE_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE
|
||||
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE == 16
|
||||
#define BOOST_ATOMIC_LONG_DOUBLE_LOCK_FREE BOOST_ATOMIC_INT128_LOCK_FREE
|
||||
#else
|
||||
#define BOOST_ATOMIC_LONG_DOUBLE_LOCK_FREE 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // !defined(BOOST_ATOMIC_NO_FLOATING_POINT)
|
||||
|
||||
#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_
|
58
boost/atomic/detail/addressof.hpp
Normal file
58
boost/atomic/detail/addressof.hpp
Normal 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) 2018 Andrey Semashev
|
||||
*/
|
||||
/*!
|
||||
* \file atomic/detail/addressof.hpp
|
||||
*
|
||||
* This header defines \c addressof helper function. It is similar to \c boost::addressof but it is more
|
||||
* lightweight and also contains a workaround for some compiler warnings.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ATOMIC_DETAIL_ADDRESSOF_HPP_INCLUDED_
|
||||
#define BOOST_ATOMIC_DETAIL_ADDRESSOF_HPP_INCLUDED_
|
||||
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
// Detection logic is based on boost/core/addressof.hpp
|
||||
#if defined(BOOST_MSVC_FULL_VER) && BOOST_MSVC_FULL_VER >= 190024215
|
||||
#define BOOST_ATOMIC_DETAIL_HAS_BUILTIN_ADDRESSOF
|
||||
#elif defined(BOOST_GCC) && BOOST_GCC >= 70000
|
||||
#define BOOST_ATOMIC_DETAIL_HAS_BUILTIN_ADDRESSOF
|
||||
#elif defined(__has_builtin)
|
||||
#if __has_builtin(__builtin_addressof)
|
||||
#define BOOST_ATOMIC_DETAIL_HAS_BUILTIN_ADDRESSOF
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
template< typename T >
|
||||
BOOST_FORCEINLINE T* addressof(T& value) BOOST_NOEXCEPT
|
||||
{
|
||||
#if defined(BOOST_ATOMIC_DETAIL_HAS_BUILTIN_ADDRESSOF)
|
||||
return __builtin_addressof(value);
|
||||
#else
|
||||
// Note: The point of using a local struct as the intermediate type instead of char is to avoid gcc warnings
|
||||
// if T is a const volatile char*:
|
||||
// warning: casting 'const volatile char* const' to 'const volatile char&' does not dereference pointer
|
||||
// The local struct makes sure T is not related to the cast target type.
|
||||
struct opaque_type;
|
||||
return reinterpret_cast< T* >(&const_cast< opaque_type& >(reinterpret_cast< const volatile opaque_type& >(value)));
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace atomics
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_ADDRESSOF_HPP_INCLUDED_
|
71
boost/atomic/detail/atomic_flag.hpp
Normal file
71
boost/atomic/detail/atomic_flag.hpp
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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_consume);
|
||||
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_
|
1248
boost/atomic/detail/atomic_template.hpp
Normal file
1248
boost/atomic/detail/atomic_template.hpp
Normal file
File diff suppressed because it is too large
Load Diff
68
boost/atomic/detail/bitwise_cast.hpp
Normal file
68
boost/atomic/detail/bitwise_cast.hpp
Normal 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) 2009 Helge Bahmann
|
||||
* Copyright (c) 2012 Tim Blechmann
|
||||
* Copyright (c) 2013 - 2018 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 <cstddef>
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
#include <boost/atomic/detail/addressof.hpp>
|
||||
#include <boost/atomic/detail/string_ops.hpp>
|
||||
#include <boost/atomic/detail/type_traits/integral_constant.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
template< std::size_t FromSize, typename To >
|
||||
BOOST_FORCEINLINE void clear_padding(To& to, atomics::detail::true_type) BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_ATOMIC_DETAIL_MEMSET(reinterpret_cast< unsigned char* >(atomics::detail::addressof(to)) + FromSize, 0, sizeof(To) - FromSize);
|
||||
}
|
||||
|
||||
template< std::size_t FromSize, typename To >
|
||||
BOOST_FORCEINLINE void clear_padding(To&, atomics::detail::false_type) BOOST_NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
template< typename To, std::size_t FromSize, typename From >
|
||||
BOOST_FORCEINLINE To bitwise_cast(From const& from) BOOST_NOEXCEPT
|
||||
{
|
||||
To to;
|
||||
BOOST_ATOMIC_DETAIL_MEMCPY
|
||||
(
|
||||
atomics::detail::addressof(to),
|
||||
atomics::detail::addressof(from),
|
||||
(FromSize < sizeof(To) ? FromSize : sizeof(To))
|
||||
);
|
||||
atomics::detail::clear_padding< FromSize >(to, atomics::detail::integral_constant< bool, FromSize < sizeof(To) >());
|
||||
return to;
|
||||
}
|
||||
|
||||
template< typename To, typename From >
|
||||
BOOST_FORCEINLINE To bitwise_cast(From const& from) BOOST_NOEXCEPT
|
||||
{
|
||||
return atomics::detail::bitwise_cast< To, sizeof(From) >(from);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace atomics
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_BITWISE_CAST_HPP_INCLUDED_
|
86
boost/atomic/detail/bitwise_fp_cast.hpp
Normal file
86
boost/atomic/detail/bitwise_fp_cast.hpp
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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) 2018 Andrey Semashev
|
||||
*/
|
||||
/*!
|
||||
* \file atomic/detail/bitwise_fp_cast.hpp
|
||||
*
|
||||
* This header defines \c bitwise_fp_cast used to convert between storage and floating point value types
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ATOMIC_DETAIL_BITWISE_FP_CAST_HPP_INCLUDED_
|
||||
#define BOOST_ATOMIC_DETAIL_BITWISE_FP_CAST_HPP_INCLUDED_
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
#include <boost/atomic/detail/float_sizes.hpp>
|
||||
#include <boost/atomic/detail/bitwise_cast.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
/*!
|
||||
* \brief The type trait returns the size of the value of the specified floating point type
|
||||
*
|
||||
* This size may be less than <tt>sizeof(T)</tt> if the implementation uses padding bytes for a particular FP type. This is
|
||||
* often the case with 80-bit extended double, which is stored in 12 or 16 bytes with padding filled with garbage.
|
||||
*/
|
||||
template< typename T >
|
||||
struct value_sizeof
|
||||
{
|
||||
static BOOST_CONSTEXPR_OR_CONST std::size_t value = sizeof(T);
|
||||
};
|
||||
|
||||
#if defined(BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT_VALUE)
|
||||
template< >
|
||||
struct value_sizeof< float >
|
||||
{
|
||||
static BOOST_CONSTEXPR_OR_CONST std::size_t value = BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT_VALUE;
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE_VALUE)
|
||||
template< >
|
||||
struct value_sizeof< double >
|
||||
{
|
||||
static BOOST_CONSTEXPR_OR_CONST std::size_t value = BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE_VALUE;
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE_VALUE)
|
||||
template< >
|
||||
struct value_sizeof< long double >
|
||||
{
|
||||
static BOOST_CONSTEXPR_OR_CONST std::size_t value = BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE_VALUE;
|
||||
};
|
||||
#endif
|
||||
|
||||
template< typename T >
|
||||
struct value_sizeof< const T > : value_sizeof< T > {};
|
||||
|
||||
template< typename T >
|
||||
struct value_sizeof< volatile T > : value_sizeof< T > {};
|
||||
|
||||
template< typename T >
|
||||
struct value_sizeof< const volatile T > : value_sizeof< T > {};
|
||||
|
||||
|
||||
template< typename To, typename From >
|
||||
BOOST_FORCEINLINE To bitwise_fp_cast(From const& from) BOOST_NOEXCEPT
|
||||
{
|
||||
return atomics::detail::bitwise_cast< To, atomics::detail::value_sizeof< From >::value >(from);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace atomics
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_BITWISE_FP_CAST_HPP_INCLUDED_
|
34
boost/atomic/detail/caps_gcc_alpha.hpp
Normal file
34
boost/atomic/detail/caps_gcc_alpha.hpp
Normal 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_
|
39
boost/atomic/detail/caps_gcc_arm.hpp
Normal file
39
boost/atomic/detail/caps_gcc_arm.hpp
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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>
|
||||
#include <boost/atomic/detail/hwcaps_gcc_arm.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(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_
|
133
boost/atomic/detail/caps_gcc_atomic.hpp
Normal file
133
boost/atomic/detail/caps_gcc_atomic.hpp
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* 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>
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
#include <boost/atomic/detail/hwcaps_gcc_x86.hpp>
|
||||
#elif defined(__arm__)
|
||||
#include <boost/atomic/detail/hwcaps_gcc_arm.hpp>
|
||||
#elif defined(__POWERPC__) || defined(__PPC__)
|
||||
#include <boost/atomic/detail/hwcaps_gcc_ppc.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#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) || (defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B) && BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 8)
|
||||
#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) || (defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B) && BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 8)
|
||||
#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_
|
37
boost/atomic/detail/caps_gcc_ppc.hpp
Normal file
37
boost/atomic/detail/caps_gcc_ppc.hpp
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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>
|
||||
#include <boost/atomic/detail/hwcaps_gcc_ppc.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(BOOST_ATOMIC_DETAIL_PPC_HAS_LDARX_STDCX)
|
||||
#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_
|
34
boost/atomic/detail/caps_gcc_sparc.hpp
Normal file
34
boost/atomic/detail/caps_gcc_sparc.hpp
Normal 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_
|
61
boost/atomic/detail/caps_gcc_sync.hpp
Normal file
61
boost/atomic/detail/caps_gcc_sync.hpp
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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>
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
#include <boost/atomic/detail/hwcaps_gcc_x86.hpp>
|
||||
#elif defined(__arm__)
|
||||
#include <boost/atomic/detail/hwcaps_gcc_arm.hpp>
|
||||
#elif defined(__POWERPC__) || defined(__PPC__)
|
||||
#include <boost/atomic/detail/hwcaps_gcc_ppc.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#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_
|
40
boost/atomic/detail/caps_gcc_x86.hpp
Normal file
40
boost/atomic/detail/caps_gcc_x86.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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>
|
||||
#include <boost/atomic/detail/hwcaps_gcc_x86.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(__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_
|
35
boost/atomic/detail/caps_linux_arm.hpp
Normal file
35
boost/atomic/detail/caps_linux_arm.hpp
Normal 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_
|
34
boost/atomic/detail/caps_msvc_arm.hpp
Normal file
34
boost/atomic/detail/caps_msvc_arm.hpp
Normal 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_
|
55
boost/atomic/detail/caps_msvc_x86.hpp
Normal file
55
boost/atomic/detail/caps_msvc_x86.hpp
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
#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
|
||||
#define BOOST_ATOMIC_DETAIL_X86_HAS_MFENCE 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_
|
33
boost/atomic/detail/caps_windows.hpp
Normal file
33
boost/atomic/detail/caps_windows.hpp
Normal 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_
|
150
boost/atomic/detail/config.hpp
Normal file
150
boost/atomic/detail/config.hpp
Normal file
@ -0,0 +1,150 @@
|
||||
/*
|
||||
* 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(__CUDACC__)
|
||||
// nvcc does not support alternatives ("q,m") 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(__i386__) || defined(__x86_64__)) && (defined(__clang__) || (defined(BOOST_GCC) && (BOOST_GCC+0) < 40500) || defined(__SUNPRO_CC))
|
||||
// This macro indicates that the compiler does not support allocating eax:edx or rax:rdx register pairs ("A") in asm blocks
|
||||
#define BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS
|
||||
#endif
|
||||
|
||||
#if defined(__i386__) && (defined(__PIC__) || defined(__PIE__)) && !(defined(__clang__) || (defined(BOOST_GCC) && (BOOST_GCC+0) >= 50100))
|
||||
// This macro indicates that asm blocks should preserve ebx value unchanged. Some compilers are able to maintain ebx themselves
|
||||
// around the asm blocks. For those compilers we don't need to save/restore ebx in asm blocks.
|
||||
#define BOOST_ATOMIC_DETAIL_X86_ASM_PRESERVE_EBX
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
|
||||
#if !(defined(BOOST_LIBSTDCXX11) && (BOOST_LIBSTDCXX_VERSION+0) >= 40700) /* libstdc++ from gcc >= 4.7 in C++11 mode */
|
||||
// This macro indicates that there is not even a basic <type_traits> standard header that is sufficient for most Boost.Atomic needs.
|
||||
#define BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS
|
||||
#endif
|
||||
#endif // defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
|
||||
|
||||
// Enable pointer/reference casts between storage and value when possible.
|
||||
// Note: Despite that MSVC does not employ strict aliasing rules for optimizations
|
||||
// and does not require an explicit markup for types that may alias, we still don't
|
||||
// enable the optimization for this compiler because at least MSVC-8 and 9 are known
|
||||
// to generate broken code sometimes when casts are used.
|
||||
#define BOOST_ATOMIC_DETAIL_MAY_ALIAS BOOST_MAY_ALIAS
|
||||
#if !defined(BOOST_NO_MAY_ALIAS)
|
||||
#define BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS
|
||||
#endif
|
||||
|
||||
#if defined(__GCC_ASM_FLAG_OUTPUTS__)
|
||||
// The compiler supports output values in flag registers.
|
||||
// See: https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html, Section 6.44.3.
|
||||
#define BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS
|
||||
#endif
|
||||
|
||||
#if defined(__has_builtin)
|
||||
#if __has_builtin(__builtin_constant_p)
|
||||
#define BOOST_ATOMIC_DETAIL_IS_CONSTANT(x) __builtin_constant_p(x)
|
||||
#endif
|
||||
#elif defined(__GNUC__)
|
||||
#define BOOST_ATOMIC_DETAIL_IS_CONSTANT(x) __builtin_constant_p(x)
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_ATOMIC_DETAIL_IS_CONSTANT)
|
||||
#define BOOST_ATOMIC_DETAIL_IS_CONSTANT(x) false
|
||||
#endif
|
||||
|
||||
#if (defined(__BYTE_ORDER__) && defined(__FLOAT_WORD_ORDER__) && (__BYTE_ORDER__+0) == (__FLOAT_WORD_ORDER__+0)) ||\
|
||||
defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)
|
||||
// This macro indicates that integer and floating point endianness is the same
|
||||
#define BOOST_ATOMIC_DETAIL_INT_FP_ENDIAN_MATCH
|
||||
#endif
|
||||
|
||||
// Deprecated symbols markup
|
||||
#if !defined(BOOST_ATOMIC_DETAIL_DEPRECATED) && defined(_MSC_VER)
|
||||
#if (_MSC_VER) >= 1400
|
||||
#define BOOST_ATOMIC_DETAIL_DEPRECATED(msg) __declspec(deprecated(msg))
|
||||
#else
|
||||
// MSVC 7.1 only supports the attribute without a message
|
||||
#define BOOST_ATOMIC_DETAIL_DEPRECATED(msg) __declspec(deprecated)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_ATOMIC_DETAIL_DEPRECATED) && defined(__has_extension)
|
||||
#if __has_extension(attribute_deprecated_with_message)
|
||||
#define BOOST_ATOMIC_DETAIL_DEPRECATED(msg) __attribute__((deprecated(msg)))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// gcc since 4.5 supports deprecated attribute with a message; older versions support the attribute without a message.
|
||||
// Oracle Studio 12.4 supports deprecated attribute with a message; this is the first release that supports the attribute.
|
||||
#if !defined(BOOST_ATOMIC_DETAIL_DEPRECATED) && (\
|
||||
(defined(__GNUC__) && ((__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0)) >= 405) ||\
|
||||
(defined(__SUNPRO_CC) && (__SUNPRO_CC + 0) >= 0x5130))
|
||||
#define BOOST_ATOMIC_DETAIL_DEPRECATED(msg) __attribute__((deprecated(msg)))
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_ATOMIC_DETAIL_DEPRECATED) && __cplusplus >= 201402
|
||||
#define BOOST_ATOMIC_DETAIL_DEPRECATED(msg) [[deprecated(msg)]]
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_ATOMIC_DETAIL_DEPRECATED) && defined(__GNUC__)
|
||||
#define BOOST_ATOMIC_DETAIL_DEPRECATED(msg) __attribute__((deprecated))
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_ATOMIC_DETAIL_DEPRECATED) && defined(__has_attribute)
|
||||
#if __has_attribute(deprecated)
|
||||
#define BOOST_ATOMIC_DETAIL_DEPRECATED(msg) __attribute__((deprecated))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_ATOMIC_DETAIL_DEPRECATED)
|
||||
#define BOOST_ATOMIC_DETAIL_DEPRECATED(msg)
|
||||
#endif
|
||||
|
||||
// In Boost.Atomic 1.67 we changed (op)_and_test methods to return true when the result is non-zero. This would be more consistent
|
||||
// with the other names used in Boost.Atomic and the C++ standard library. Since the methods were announced as experimental and
|
||||
// the previous behavior was released only in Boost 1.66, it was decided to change the result without changing the method names.
|
||||
// By defining BOOST_ATOMIC_HIGHLIGHT_OP_AND_TEST the user has a way to highlight all uses of the affected functions so
|
||||
// that it is easier to find and update the affected code (which is typically adding or removing negation of the result). This
|
||||
// highlighting functionality is a temporary measure to help users upgrade from Boost 1.66 to newer Boost versions. It will
|
||||
// be removed eventually.
|
||||
//
|
||||
// More info at:
|
||||
// https://github.com/boostorg/atomic/issues/11
|
||||
// http://boost.2283326.n4.nabble.com/atomic-op-and-test-naming-tc4701445.html
|
||||
#if defined(BOOST_ATOMIC_HIGHLIGHT_OP_AND_TEST)
|
||||
#define BOOST_ATOMIC_DETAIL_HIGHLIGHT_OP_AND_TEST BOOST_ATOMIC_DETAIL_DEPRECATED("Boost.Atomic 1.67 has changed (op)_and_test result to the opposite. The functions now return true when the result is non-zero. Please, verify your use of the operation and undefine BOOST_ATOMIC_HIGHLIGHT_OP_AND_TEST.")
|
||||
#else
|
||||
#define BOOST_ATOMIC_DETAIL_HIGHLIGHT_OP_AND_TEST
|
||||
#endif
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_CONFIG_HPP_INCLUDED_
|
28
boost/atomic/detail/extra_fp_operations.hpp
Normal file
28
boost/atomic/detail/extra_fp_operations.hpp
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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) 2018 Andrey Semashev
|
||||
*/
|
||||
/*!
|
||||
* \file atomic/detail/extra_fp_operations.hpp
|
||||
*
|
||||
* This header defines extra floating point atomic operations, including the generic version.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ATOMIC_DETAIL_EXTRA_FP_OPERATIONS_HPP_INCLUDED_
|
||||
#define BOOST_ATOMIC_DETAIL_EXTRA_FP_OPERATIONS_HPP_INCLUDED_
|
||||
|
||||
#include <boost/atomic/detail/extra_fp_ops_generic.hpp>
|
||||
#include <boost/atomic/detail/extra_fp_ops_emulated.hpp>
|
||||
|
||||
#if !defined(BOOST_ATOMIC_DETAIL_EXTRA_FP_BACKEND_GENERIC)
|
||||
#include BOOST_ATOMIC_DETAIL_EXTRA_FP_BACKEND_HEADER(boost/atomic/detail/extra_fp_ops_)
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_EXTRA_FP_OPERATIONS_HPP_INCLUDED_
|
35
boost/atomic/detail/extra_fp_operations_fwd.hpp
Normal file
35
boost/atomic/detail/extra_fp_operations_fwd.hpp
Normal 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) 2018 Andrey Semashev
|
||||
*/
|
||||
/*!
|
||||
* \file atomic/detail/extra_fp_operations_fwd.hpp
|
||||
*
|
||||
* This header contains forward declaration of the \c extra_fp_operations template.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ATOMIC_DETAIL_EXTRA_FP_OPERATIONS_FWD_HPP_INCLUDED_
|
||||
#define BOOST_ATOMIC_DETAIL_EXTRA_FP_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< typename Base, typename Value, std::size_t Size, bool = Base::is_always_lock_free >
|
||||
struct extra_fp_operations;
|
||||
|
||||
} // namespace detail
|
||||
} // namespace atomics
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_EXTRA_FP_OPERATIONS_FWD_HPP_INCLUDED_
|
107
boost/atomic/detail/extra_fp_ops_emulated.hpp
Normal file
107
boost/atomic/detail/extra_fp_ops_emulated.hpp
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 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) 2018 Andrey Semashev
|
||||
*/
|
||||
/*!
|
||||
* \file atomic/detail/extra_fp_ops_emulated.hpp
|
||||
*
|
||||
* This header contains emulated (lock-based) implementation of the extra floating point atomic operations.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ATOMIC_DETAIL_EXTRA_FP_OPS_EMULATED_HPP_INCLUDED_
|
||||
#define BOOST_ATOMIC_DETAIL_EXTRA_FP_OPS_EMULATED_HPP_INCLUDED_
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/memory_order.hpp>
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
#include <boost/atomic/detail/bitwise_fp_cast.hpp>
|
||||
#include <boost/atomic/detail/extra_fp_operations_fwd.hpp>
|
||||
#include <boost/atomic/detail/lockpool.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
//! Generic implementation of extra floating point operations
|
||||
template< typename Base, typename Value, std::size_t Size >
|
||||
struct emulated_extra_fp_operations :
|
||||
public Base
|
||||
{
|
||||
typedef Base base_type;
|
||||
typedef typename base_type::storage_type storage_type;
|
||||
typedef Value value_type;
|
||||
|
||||
static BOOST_FORCEINLINE value_type fetch_negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type& s = const_cast< storage_type& >(storage);
|
||||
lockpool::scoped_lock lock(&storage);
|
||||
value_type old_val = atomics::detail::bitwise_fp_cast< value_type >(s);
|
||||
value_type new_val = -old_val;
|
||||
s = atomics::detail::bitwise_fp_cast< storage_type >(new_val);
|
||||
return old_val;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE value_type negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type& s = const_cast< storage_type& >(storage);
|
||||
lockpool::scoped_lock lock(&storage);
|
||||
value_type old_val = atomics::detail::bitwise_fp_cast< value_type >(s);
|
||||
value_type new_val = -old_val;
|
||||
s = atomics::detail::bitwise_fp_cast< storage_type >(new_val);
|
||||
return new_val;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE value_type add(storage_type volatile& storage, value_type v, memory_order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type& s = const_cast< storage_type& >(storage);
|
||||
lockpool::scoped_lock lock(&storage);
|
||||
value_type old_val = atomics::detail::bitwise_fp_cast< value_type >(s);
|
||||
value_type new_val = old_val + v;
|
||||
s = atomics::detail::bitwise_fp_cast< storage_type >(new_val);
|
||||
return new_val;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE value_type sub(storage_type volatile& storage, value_type v, memory_order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type& s = const_cast< storage_type& >(storage);
|
||||
lockpool::scoped_lock lock(&storage);
|
||||
value_type old_val = atomics::detail::bitwise_fp_cast< value_type >(s);
|
||||
value_type new_val = old_val - v;
|
||||
s = atomics::detail::bitwise_fp_cast< storage_type >(new_val);
|
||||
return new_val;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
fetch_negate(storage, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE void opaque_add(storage_type volatile& storage, value_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
base_type::fetch_add(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE void opaque_sub(storage_type volatile& storage, value_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
base_type::fetch_sub(storage, v, order);
|
||||
}
|
||||
};
|
||||
|
||||
template< typename Base, typename Value, std::size_t Size >
|
||||
struct extra_fp_operations< Base, Value, Size, false > :
|
||||
public emulated_extra_fp_operations< Base, Value, Size >
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace atomics
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_EXTRA_FP_OPS_EMULATED_HPP_INCLUDED_
|
189
boost/atomic/detail/extra_fp_ops_generic.hpp
Normal file
189
boost/atomic/detail/extra_fp_ops_generic.hpp
Normal file
@ -0,0 +1,189 @@
|
||||
/*
|
||||
* 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) 2018 Andrey Semashev
|
||||
*/
|
||||
/*!
|
||||
* \file atomic/detail/extra_fp_ops_generic.hpp
|
||||
*
|
||||
* This header contains generic implementation of the extra floating point atomic operations.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ATOMIC_DETAIL_EXTRA_FP_OPS_GENERIC_HPP_INCLUDED_
|
||||
#define BOOST_ATOMIC_DETAIL_EXTRA_FP_OPS_GENERIC_HPP_INCLUDED_
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/memory_order.hpp>
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
#include <boost/atomic/detail/bitwise_fp_cast.hpp>
|
||||
#include <boost/atomic/detail/storage_type.hpp>
|
||||
#include <boost/atomic/detail/extra_fp_operations_fwd.hpp>
|
||||
#include <boost/atomic/detail/type_traits/is_iec559.hpp>
|
||||
#include <boost/atomic/detail/type_traits/is_integral.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_GCC) && (BOOST_GCC+0) >= 60000
|
||||
#pragma GCC diagnostic push
|
||||
// ignoring attributes on template argument X - this warning is because we need to pass storage_type as a template argument; no problem in this case
|
||||
#pragma GCC diagnostic ignored "-Wignored-attributes"
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
//! Negate implementation
|
||||
template<
|
||||
typename Base,
|
||||
typename Value,
|
||||
std::size_t Size
|
||||
#if defined(BOOST_ATOMIC_DETAIL_INT_FP_ENDIAN_MATCH)
|
||||
, bool = atomics::detail::is_iec559< Value >::value && atomics::detail::is_integral< typename Base::storage_type >::value
|
||||
#endif
|
||||
>
|
||||
struct generic_extra_fp_negate :
|
||||
public Base
|
||||
{
|
||||
typedef Base base_type;
|
||||
typedef typename base_type::storage_type storage_type;
|
||||
typedef Value value_type;
|
||||
|
||||
static BOOST_FORCEINLINE value_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type old_storage, new_storage;
|
||||
value_type old_val, new_val;
|
||||
atomics::detail::non_atomic_load(storage, old_storage);
|
||||
do
|
||||
{
|
||||
old_val = atomics::detail::bitwise_fp_cast< value_type >(old_storage);
|
||||
new_val = -old_val;
|
||||
new_storage = atomics::detail::bitwise_fp_cast< storage_type >(new_val);
|
||||
}
|
||||
while (!base_type::compare_exchange_weak(storage, old_storage, new_storage, order, memory_order_relaxed));
|
||||
return old_val;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE value_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type old_storage, new_storage;
|
||||
value_type old_val, new_val;
|
||||
atomics::detail::non_atomic_load(storage, old_storage);
|
||||
do
|
||||
{
|
||||
old_val = atomics::detail::bitwise_fp_cast< value_type >(old_storage);
|
||||
new_val = -old_val;
|
||||
new_storage = atomics::detail::bitwise_fp_cast< storage_type >(new_val);
|
||||
}
|
||||
while (!base_type::compare_exchange_weak(storage, old_storage, new_storage, order, memory_order_relaxed));
|
||||
return new_val;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
fetch_negate(storage, order);
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(BOOST_ATOMIC_DETAIL_INT_FP_ENDIAN_MATCH)
|
||||
|
||||
//! Negate implementation for IEEE 754 / IEC 559 floating point types. We leverage the fact that the sign bit is the most significant bit in the value.
|
||||
template< typename Base, typename Value, std::size_t Size >
|
||||
struct generic_extra_fp_negate< Base, Value, Size, true > :
|
||||
public Base
|
||||
{
|
||||
typedef Base base_type;
|
||||
typedef typename base_type::storage_type storage_type;
|
||||
typedef Value value_type;
|
||||
|
||||
//! The mask with only one sign bit set to 1
|
||||
static BOOST_CONSTEXPR_OR_CONST storage_type sign_mask = static_cast< storage_type >(1u) << (atomics::detail::value_sizeof< value_type >::value * 8u - 1u);
|
||||
|
||||
static BOOST_FORCEINLINE value_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return atomics::detail::bitwise_fp_cast< value_type >(base_type::fetch_xor(storage, sign_mask, order));
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE value_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return atomics::detail::bitwise_fp_cast< value_type >(base_type::bitwise_xor(storage, sign_mask, order));
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
base_type::opaque_xor(storage, sign_mask, order);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // defined(BOOST_ATOMIC_DETAIL_INT_FP_ENDIAN_MATCH)
|
||||
|
||||
//! Generic implementation of floating point operations
|
||||
template< typename Base, typename Value, std::size_t Size >
|
||||
struct generic_extra_fp_operations :
|
||||
public generic_extra_fp_negate< Base, Value, Size >
|
||||
{
|
||||
typedef generic_extra_fp_negate< Base, Value, Size > base_type;
|
||||
typedef typename base_type::storage_type storage_type;
|
||||
typedef Value value_type;
|
||||
|
||||
static BOOST_FORCEINLINE value_type add(storage_type volatile& storage, value_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type old_storage, new_storage;
|
||||
value_type old_val, new_val;
|
||||
atomics::detail::non_atomic_load(storage, old_storage);
|
||||
do
|
||||
{
|
||||
old_val = atomics::detail::bitwise_fp_cast< value_type >(old_storage);
|
||||
new_val = old_val + v;
|
||||
new_storage = atomics::detail::bitwise_fp_cast< storage_type >(new_val);
|
||||
}
|
||||
while (!base_type::compare_exchange_weak(storage, old_storage, new_storage, order, memory_order_relaxed));
|
||||
return new_val;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE value_type sub(storage_type volatile& storage, value_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type old_storage, new_storage;
|
||||
value_type old_val, new_val;
|
||||
atomics::detail::non_atomic_load(storage, old_storage);
|
||||
do
|
||||
{
|
||||
old_val = atomics::detail::bitwise_fp_cast< value_type >(old_storage);
|
||||
new_val = old_val - v;
|
||||
new_storage = atomics::detail::bitwise_fp_cast< storage_type >(new_val);
|
||||
}
|
||||
while (!base_type::compare_exchange_weak(storage, old_storage, new_storage, order, memory_order_relaxed));
|
||||
return new_val;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE void opaque_add(storage_type volatile& storage, value_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
base_type::fetch_add(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE void opaque_sub(storage_type volatile& storage, value_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
base_type::fetch_sub(storage, v, order);
|
||||
}
|
||||
};
|
||||
|
||||
// Default extra_fp_operations template definition will be used unless specialized for a specific platform
|
||||
template< typename Base, typename Value, std::size_t Size >
|
||||
struct extra_fp_operations< Base, Value, Size, true > :
|
||||
public generic_extra_fp_operations< Base, Value, Size >
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace atomics
|
||||
} // namespace boost
|
||||
|
||||
#if defined(BOOST_GCC) && (BOOST_GCC+0) >= 60000
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_FP_OPS_GENERIC_HPP_INCLUDED_
|
28
boost/atomic/detail/extra_operations.hpp
Normal file
28
boost/atomic/detail/extra_operations.hpp
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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) 2017 Andrey Semashev
|
||||
*/
|
||||
/*!
|
||||
* \file atomic/detail/extra_operations.hpp
|
||||
*
|
||||
* This header defines extra atomic operations, including the generic version.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ATOMIC_DETAIL_EXTRA_OPERATIONS_HPP_INCLUDED_
|
||||
#define BOOST_ATOMIC_DETAIL_EXTRA_OPERATIONS_HPP_INCLUDED_
|
||||
|
||||
#include <boost/atomic/detail/extra_ops_generic.hpp>
|
||||
#include <boost/atomic/detail/extra_ops_emulated.hpp>
|
||||
|
||||
#if !defined(BOOST_ATOMIC_DETAIL_EXTRA_BACKEND_GENERIC)
|
||||
#include BOOST_ATOMIC_DETAIL_EXTRA_BACKEND_HEADER(boost/atomic/detail/extra_ops_)
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_EXTRA_OPERATIONS_HPP_INCLUDED_
|
35
boost/atomic/detail/extra_operations_fwd.hpp
Normal file
35
boost/atomic/detail/extra_operations_fwd.hpp
Normal 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) 2017 Andrey Semashev
|
||||
*/
|
||||
/*!
|
||||
* \file atomic/detail/extra_operations_fwd.hpp
|
||||
*
|
||||
* This header contains forward declaration of the \c extra_operations template.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ATOMIC_DETAIL_EXTRA_OPERATIONS_FWD_HPP_INCLUDED_
|
||||
#define BOOST_ATOMIC_DETAIL_EXTRA_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< typename Base, std::size_t Size, bool Signed, bool = Base::is_always_lock_free >
|
||||
struct extra_operations;
|
||||
|
||||
} // namespace detail
|
||||
} // namespace atomics
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_EXTRA_OPERATIONS_FWD_HPP_INCLUDED_
|
238
boost/atomic/detail/extra_ops_emulated.hpp
Normal file
238
boost/atomic/detail/extra_ops_emulated.hpp
Normal file
@ -0,0 +1,238 @@
|
||||
/*
|
||||
* 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) 2018 Andrey Semashev
|
||||
*/
|
||||
/*!
|
||||
* \file atomic/detail/extra_ops_emulated.hpp
|
||||
*
|
||||
* This header contains emulated (lock-based) implementation of the extra atomic operations.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ATOMIC_DETAIL_EXTRA_OPS_EMULATED_HPP_INCLUDED_
|
||||
#define BOOST_ATOMIC_DETAIL_EXTRA_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/extra_operations_fwd.hpp>
|
||||
#include <boost/atomic/detail/lockpool.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(push)
|
||||
// unary minus operator applied to unsigned type, result still unsigned
|
||||
#pragma warning(disable: 4146)
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
//! Generic implementation of extra operations
|
||||
template< typename Base, std::size_t Size, bool Signed >
|
||||
struct emulated_extra_operations :
|
||||
public Base
|
||||
{
|
||||
typedef Base base_type;
|
||||
typedef typename base_type::storage_type storage_type;
|
||||
|
||||
static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type& s = const_cast< storage_type& >(storage);
|
||||
lockpool::scoped_lock lock(&storage);
|
||||
storage_type old_val = s;
|
||||
s = static_cast< storage_type >(-old_val);
|
||||
return old_val;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type& s = const_cast< storage_type& >(storage);
|
||||
lockpool::scoped_lock lock(&storage);
|
||||
storage_type new_val = static_cast< storage_type >(-s);
|
||||
s = new_val;
|
||||
return new_val;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type 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 new_val = s;
|
||||
new_val += v;
|
||||
s = new_val;
|
||||
return new_val;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type 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 new_val = s;
|
||||
new_val -= v;
|
||||
s = new_val;
|
||||
return new_val;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type bitwise_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 new_val = s;
|
||||
new_val &= v;
|
||||
s = new_val;
|
||||
return new_val;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type bitwise_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 new_val = s;
|
||||
new_val |= v;
|
||||
s = new_val;
|
||||
return new_val;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type bitwise_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 new_val = s;
|
||||
new_val ^= v;
|
||||
s = new_val;
|
||||
return new_val;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type& s = const_cast< storage_type& >(storage);
|
||||
lockpool::scoped_lock lock(&storage);
|
||||
storage_type old_val = s;
|
||||
s = static_cast< storage_type >(~old_val);
|
||||
return old_val;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type& s = const_cast< storage_type& >(storage);
|
||||
lockpool::scoped_lock lock(&storage);
|
||||
storage_type new_val = static_cast< storage_type >(~s);
|
||||
s = new_val;
|
||||
return new_val;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE void opaque_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
Base::fetch_add(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE void opaque_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
Base::fetch_sub(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
fetch_negate(storage, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE void opaque_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
Base::fetch_and(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE void opaque_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
Base::fetch_or(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE void opaque_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
Base::fetch_xor(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
fetch_complement(storage, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool add_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return !!add(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool sub_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return !!sub(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool negate_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return !!negate(storage, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool and_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return !!bitwise_and(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool or_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return !!bitwise_or(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool xor_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return !!bitwise_xor(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool complement_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return !!bitwise_complement(storage, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type mask = static_cast< storage_type >(static_cast< storage_type >(1u) << bit_number);
|
||||
storage_type old_val = Base::fetch_or(storage, mask, order);
|
||||
return !!(old_val & mask);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type mask = static_cast< storage_type >(static_cast< storage_type >(1u) << bit_number);
|
||||
storage_type old_val = Base::fetch_and(storage, ~mask, order);
|
||||
return !!(old_val & mask);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool bit_test_and_complement(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type mask = static_cast< storage_type >(static_cast< storage_type >(1u) << bit_number);
|
||||
storage_type old_val = Base::fetch_xor(storage, mask, order);
|
||||
return !!(old_val & mask);
|
||||
}
|
||||
};
|
||||
|
||||
template< typename Base, std::size_t Size, bool Signed >
|
||||
struct extra_operations< Base, Size, Signed, false > :
|
||||
public emulated_extra_operations< Base, Size, Signed >
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace atomics
|
||||
} // namespace boost
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_EXTRA_OPS_EMULATED_HPP_INCLUDED_
|
1111
boost/atomic/detail/extra_ops_gcc_arm.hpp
Normal file
1111
boost/atomic/detail/extra_ops_gcc_arm.hpp
Normal file
File diff suppressed because it is too large
Load Diff
840
boost/atomic/detail/extra_ops_gcc_ppc.hpp
Normal file
840
boost/atomic/detail/extra_ops_gcc_ppc.hpp
Normal file
@ -0,0 +1,840 @@
|
||||
/*
|
||||
* 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) 2017 - 2018 Andrey Semashev
|
||||
*/
|
||||
/*!
|
||||
* \file atomic/detail/extra_ops_gcc_ppc.hpp
|
||||
*
|
||||
* This header contains implementation of the extra atomic operations for PowerPC.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ATOMIC_DETAIL_EXTRA_OPS_GCC_PPC_HPP_INCLUDED_
|
||||
#define BOOST_ATOMIC_DETAIL_EXTRA_OPS_GCC_PPC_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/extra_operations_fwd.hpp>
|
||||
#include <boost/atomic/detail/extra_ops_generic.hpp>
|
||||
#include <boost/atomic/detail/ops_gcc_ppc_common.hpp>
|
||||
#include <boost/atomic/capabilities.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
template< typename Base >
|
||||
struct gcc_ppc_extra_operations_common :
|
||||
public Base
|
||||
{
|
||||
typedef Base base_type;
|
||||
typedef typename base_type::storage_type storage_type;
|
||||
|
||||
static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
base_type::fetch_negate(storage, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
base_type::fetch_complement(storage, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool negate_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return !!base_type::negate(storage, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool add_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return !!base_type::add(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool sub_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return !!base_type::sub(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool and_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return !!base_type::bitwise_and(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool or_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return !!base_type::bitwise_or(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool xor_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return !!base_type::bitwise_xor(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool complement_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return !!base_type::bitwise_complement(storage, order);
|
||||
}
|
||||
};
|
||||
|
||||
template< typename Base, std::size_t Size, bool Signed >
|
||||
struct gcc_ppc_extra_operations;
|
||||
|
||||
#if defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LBARX_STBCX)
|
||||
|
||||
template< typename Base, bool Signed >
|
||||
struct gcc_ppc_extra_operations< Base, 1u, Signed > :
|
||||
public generic_extra_operations< Base, 1u, Signed >
|
||||
{
|
||||
typedef generic_extra_operations< Base, 1u, Signed > base_type;
|
||||
typedef typename base_type::storage_type storage_type;
|
||||
|
||||
static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
gcc_ppc_operations_base::fence_before(order);
|
||||
storage_type original, result;
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"1:\n\t"
|
||||
"lbarx %0,%y2\n\t"
|
||||
"neg %1,%0\n\t"
|
||||
"stbcx. %1,%y2\n\t"
|
||||
"bne- 1b\n\t"
|
||||
: "=&b" (original), "=&b" (result), "+Z" (storage)
|
||||
:
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return original;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
gcc_ppc_operations_base::fence_before(order);
|
||||
storage_type original, result;
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"1:\n\t"
|
||||
"lbarx %0,%y2\n\t"
|
||||
"neg %1,%0\n\t"
|
||||
"stbcx. %1,%y2\n\t"
|
||||
"bne- 1b\n\t"
|
||||
: "=&b" (original), "=&b" (result), "+Z" (storage)
|
||||
:
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type original, result;
|
||||
gcc_ppc_operations_base::fence_before(order);
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"1:\n\t"
|
||||
"lbarx %0,%y2\n\t"
|
||||
"add %1,%0,%3\n\t"
|
||||
"stbcx. %1,%y2\n\t"
|
||||
"bne- 1b\n\t"
|
||||
: "=&b" (original), "=&b" (result), "+Z" (storage)
|
||||
: "b" (v)
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type original, result;
|
||||
gcc_ppc_operations_base::fence_before(order);
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"1:\n\t"
|
||||
"lbarx %0,%y2\n\t"
|
||||
"sub %1,%0,%3\n\t"
|
||||
"stbcx. %1,%y2\n\t"
|
||||
"bne- 1b\n\t"
|
||||
: "=&b" (original), "=&b" (result), "+Z" (storage)
|
||||
: "b" (v)
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type original, result;
|
||||
gcc_ppc_operations_base::fence_before(order);
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"1:\n\t"
|
||||
"lbarx %0,%y2\n\t"
|
||||
"and %1,%0,%3\n\t"
|
||||
"stbcx. %1,%y2\n\t"
|
||||
"bne- 1b\n\t"
|
||||
: "=&b" (original), "=&b" (result), "+Z" (storage)
|
||||
: "b" (v)
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type original, result;
|
||||
gcc_ppc_operations_base::fence_before(order);
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"1:\n\t"
|
||||
"lbarx %0,%y2\n\t"
|
||||
"or %1,%0,%3\n\t"
|
||||
"stbcx. %1,%y2\n\t"
|
||||
"bne- 1b\n\t"
|
||||
: "=&b" (original), "=&b" (result), "+Z" (storage)
|
||||
: "b" (v)
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type original, result;
|
||||
gcc_ppc_operations_base::fence_before(order);
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"1:\n\t"
|
||||
"lbarx %0,%y2\n\t"
|
||||
"xor %1,%0,%3\n\t"
|
||||
"stbcx. %1,%y2\n\t"
|
||||
"bne- 1b\n\t"
|
||||
: "=&b" (original), "=&b" (result), "+Z" (storage)
|
||||
: "b" (v)
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
gcc_ppc_operations_base::fence_before(order);
|
||||
storage_type original, result;
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"1:\n\t"
|
||||
"lbarx %0,%y2\n\t"
|
||||
"nor %1,%0,%0\n\t"
|
||||
"stbcx. %1,%y2\n\t"
|
||||
"bne- 1b\n\t"
|
||||
: "=&b" (original), "=&b" (result), "+Z" (storage)
|
||||
:
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return original;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
gcc_ppc_operations_base::fence_before(order);
|
||||
storage_type original, result;
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"1:\n\t"
|
||||
"lbarx %0,%y2\n\t"
|
||||
"nor %1,%0,%0\n\t"
|
||||
"stbcx. %1,%y2\n\t"
|
||||
"bne- 1b\n\t"
|
||||
: "=&b" (original), "=&b" (result), "+Z" (storage)
|
||||
:
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template< typename Base, bool Signed >
|
||||
struct extra_operations< Base, 1u, Signed, true > :
|
||||
public gcc_ppc_extra_operations_common< gcc_ppc_extra_operations< Base, 1u, Signed > >
|
||||
{
|
||||
};
|
||||
|
||||
#endif // defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LBARX_STBCX)
|
||||
|
||||
#if defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LHARX_STHCX)
|
||||
|
||||
template< typename Base, bool Signed >
|
||||
struct gcc_ppc_extra_operations< Base, 2u, Signed > :
|
||||
public generic_extra_operations< Base, 2u, Signed >
|
||||
{
|
||||
typedef generic_extra_operations< Base, 2u, Signed > base_type;
|
||||
typedef typename base_type::storage_type storage_type;
|
||||
|
||||
static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
gcc_ppc_operations_base::fence_before(order);
|
||||
storage_type original, result;
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"1:\n\t"
|
||||
"lharx %0,%y2\n\t"
|
||||
"neg %1,%0\n\t"
|
||||
"sthcx. %1,%y2\n\t"
|
||||
"bne- 1b\n\t"
|
||||
: "=&b" (original), "=&b" (result), "+Z" (storage)
|
||||
:
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return original;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
gcc_ppc_operations_base::fence_before(order);
|
||||
storage_type original, result;
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"1:\n\t"
|
||||
"lharx %0,%y2\n\t"
|
||||
"neg %1,%0\n\t"
|
||||
"sthcx. %1,%y2\n\t"
|
||||
"bne- 1b\n\t"
|
||||
: "=&b" (original), "=&b" (result), "+Z" (storage)
|
||||
:
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type original, result;
|
||||
gcc_ppc_operations_base::fence_before(order);
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"1:\n\t"
|
||||
"lharx %0,%y2\n\t"
|
||||
"add %1,%0,%3\n\t"
|
||||
"sthcx. %1,%y2\n\t"
|
||||
"bne- 1b\n\t"
|
||||
: "=&b" (original), "=&b" (result), "+Z" (storage)
|
||||
: "b" (v)
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type original, result;
|
||||
gcc_ppc_operations_base::fence_before(order);
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"1:\n\t"
|
||||
"lharx %0,%y2\n\t"
|
||||
"sub %1,%0,%3\n\t"
|
||||
"sthcx. %1,%y2\n\t"
|
||||
"bne- 1b\n\t"
|
||||
: "=&b" (original), "=&b" (result), "+Z" (storage)
|
||||
: "b" (v)
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type original, result;
|
||||
gcc_ppc_operations_base::fence_before(order);
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"1:\n\t"
|
||||
"lharx %0,%y2\n\t"
|
||||
"and %1,%0,%3\n\t"
|
||||
"sthcx. %1,%y2\n\t"
|
||||
"bne- 1b\n\t"
|
||||
: "=&b" (original), "=&b" (result), "+Z" (storage)
|
||||
: "b" (v)
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type original, result;
|
||||
gcc_ppc_operations_base::fence_before(order);
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"1:\n\t"
|
||||
"lharx %0,%y2\n\t"
|
||||
"or %1,%0,%3\n\t"
|
||||
"sthcx. %1,%y2\n\t"
|
||||
"bne- 1b\n\t"
|
||||
: "=&b" (original), "=&b" (result), "+Z" (storage)
|
||||
: "b" (v)
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type original, result;
|
||||
gcc_ppc_operations_base::fence_before(order);
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"1:\n\t"
|
||||
"lharx %0,%y2\n\t"
|
||||
"xor %1,%0,%3\n\t"
|
||||
"sthcx. %1,%y2\n\t"
|
||||
"bne- 1b\n\t"
|
||||
: "=&b" (original), "=&b" (result), "+Z" (storage)
|
||||
: "b" (v)
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
gcc_ppc_operations_base::fence_before(order);
|
||||
storage_type original, result;
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"1:\n\t"
|
||||
"lharx %0,%y2\n\t"
|
||||
"nor %1,%0,%0\n\t"
|
||||
"sthcx. %1,%y2\n\t"
|
||||
"bne- 1b\n\t"
|
||||
: "=&b" (original), "=&b" (result), "+Z" (storage)
|
||||
:
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return original;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
gcc_ppc_operations_base::fence_before(order);
|
||||
storage_type original, result;
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"1:\n\t"
|
||||
"lharx %0,%y2\n\t"
|
||||
"nor %1,%0,%0\n\t"
|
||||
"sthcx. %1,%y2\n\t"
|
||||
"bne- 1b\n\t"
|
||||
: "=&b" (original), "=&b" (result), "+Z" (storage)
|
||||
:
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LHARX_STHCX)
|
||||
|
||||
template< typename Base, bool Signed >
|
||||
struct gcc_ppc_extra_operations< Base, 4u, Signed > :
|
||||
public generic_extra_operations< Base, 4u, Signed >
|
||||
{
|
||||
typedef generic_extra_operations< Base, 4u, Signed > base_type;
|
||||
typedef typename base_type::storage_type storage_type;
|
||||
|
||||
static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
gcc_ppc_operations_base::fence_before(order);
|
||||
storage_type original, result;
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"1:\n\t"
|
||||
"lwarx %0,%y2\n\t"
|
||||
"neg %1,%0\n\t"
|
||||
"stwcx. %1,%y2\n\t"
|
||||
"bne- 1b\n\t"
|
||||
: "=&b" (original), "=&b" (result), "+Z" (storage)
|
||||
:
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return original;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
gcc_ppc_operations_base::fence_before(order);
|
||||
storage_type original, result;
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"1:\n\t"
|
||||
"lwarx %0,%y2\n\t"
|
||||
"neg %1,%0\n\t"
|
||||
"stwcx. %1,%y2\n\t"
|
||||
"bne- 1b\n\t"
|
||||
: "=&b" (original), "=&b" (result), "+Z" (storage)
|
||||
:
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type original, result;
|
||||
gcc_ppc_operations_base::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" (result), "+Z" (storage)
|
||||
: "b" (v)
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type original, result;
|
||||
gcc_ppc_operations_base::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" (result), "+Z" (storage)
|
||||
: "b" (v)
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type original, result;
|
||||
gcc_ppc_operations_base::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" (result), "+Z" (storage)
|
||||
: "b" (v)
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type original, result;
|
||||
gcc_ppc_operations_base::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" (result), "+Z" (storage)
|
||||
: "b" (v)
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type original, result;
|
||||
gcc_ppc_operations_base::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" (result), "+Z" (storage)
|
||||
: "b" (v)
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
gcc_ppc_operations_base::fence_before(order);
|
||||
storage_type original, result;
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"1:\n\t"
|
||||
"lwarx %0,%y2\n\t"
|
||||
"nor %1,%0,%0\n\t"
|
||||
"stwcx. %1,%y2\n\t"
|
||||
"bne- 1b\n\t"
|
||||
: "=&b" (original), "=&b" (result), "+Z" (storage)
|
||||
:
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return original;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
gcc_ppc_operations_base::fence_before(order);
|
||||
storage_type original, result;
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"1:\n\t"
|
||||
"lwarx %0,%y2\n\t"
|
||||
"nor %1,%0,%0\n\t"
|
||||
"stwcx. %1,%y2\n\t"
|
||||
"bne- 1b\n\t"
|
||||
: "=&b" (original), "=&b" (result), "+Z" (storage)
|
||||
:
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template< typename Base, bool Signed >
|
||||
struct extra_operations< Base, 4u, Signed, true > :
|
||||
public gcc_ppc_extra_operations_common< gcc_ppc_extra_operations< Base, 4u, Signed > >
|
||||
{
|
||||
};
|
||||
|
||||
#if defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LDARX_STDCX)
|
||||
|
||||
template< typename Base, bool Signed >
|
||||
struct gcc_ppc_extra_operations< Base, 8u, Signed > :
|
||||
public generic_extra_operations< Base, 8u, Signed >
|
||||
{
|
||||
typedef generic_extra_operations< Base, 8u, Signed > base_type;
|
||||
typedef typename base_type::storage_type storage_type;
|
||||
|
||||
static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
gcc_ppc_operations_base::fence_before(order);
|
||||
storage_type original, result;
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"1:\n\t"
|
||||
"ldarx %0,%y2\n\t"
|
||||
"neg %1,%0\n\t"
|
||||
"stdcx. %1,%y2\n\t"
|
||||
"bne- 1b\n\t"
|
||||
: "=&b" (original), "=&b" (result), "+Z" (storage)
|
||||
:
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return original;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
gcc_ppc_operations_base::fence_before(order);
|
||||
storage_type original, result;
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"1:\n\t"
|
||||
"ldarx %0,%y2\n\t"
|
||||
"neg %1,%0\n\t"
|
||||
"stdcx. %1,%y2\n\t"
|
||||
"bne- 1b\n\t"
|
||||
: "=&b" (original), "=&b" (result), "+Z" (storage)
|
||||
:
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type original, result;
|
||||
gcc_ppc_operations_base::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" (result), "+Z" (storage)
|
||||
: "b" (v)
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type original, result;
|
||||
gcc_ppc_operations_base::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" (result), "+Z" (storage)
|
||||
: "b" (v)
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type original, result;
|
||||
gcc_ppc_operations_base::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" (result), "+Z" (storage)
|
||||
: "b" (v)
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type original, result;
|
||||
gcc_ppc_operations_base::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" (result), "+Z" (storage)
|
||||
: "b" (v)
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type original, result;
|
||||
gcc_ppc_operations_base::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" (result), "+Z" (storage)
|
||||
: "b" (v)
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
gcc_ppc_operations_base::fence_before(order);
|
||||
storage_type original, result;
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"1:\n\t"
|
||||
"ldarx %0,%y2\n\t"
|
||||
"nor %1,%0,%0\n\t"
|
||||
"stdcx. %1,%y2\n\t"
|
||||
"bne- 1b\n\t"
|
||||
: "=&b" (original), "=&b" (result), "+Z" (storage)
|
||||
:
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return original;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
gcc_ppc_operations_base::fence_before(order);
|
||||
storage_type original, result;
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"1:\n\t"
|
||||
"ldarx %0,%y2\n\t"
|
||||
"nor %1,%0,%0\n\t"
|
||||
"stdcx. %1,%y2\n\t"
|
||||
"bne- 1b\n\t"
|
||||
: "=&b" (original), "=&b" (result), "+Z" (storage)
|
||||
:
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
|
||||
);
|
||||
gcc_ppc_operations_base::fence_after(order);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template< typename Base, bool Signed >
|
||||
struct extra_operations< Base, 8u, Signed, true > :
|
||||
public gcc_ppc_extra_operations_common< gcc_ppc_extra_operations< Base, 8u, Signed > >
|
||||
{
|
||||
};
|
||||
|
||||
#endif // defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LDARX_STDCX)
|
||||
|
||||
} // namespace detail
|
||||
} // namespace atomics
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_EXTRA_OPS_GCC_ARM_PPC_INCLUDED_
|
1656
boost/atomic/detail/extra_ops_gcc_x86.hpp
Normal file
1656
boost/atomic/detail/extra_ops_gcc_x86.hpp
Normal file
File diff suppressed because it is too large
Load Diff
402
boost/atomic/detail/extra_ops_generic.hpp
Normal file
402
boost/atomic/detail/extra_ops_generic.hpp
Normal file
@ -0,0 +1,402 @@
|
||||
/*
|
||||
* 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) 2015 Andrey Semashev
|
||||
*/
|
||||
/*!
|
||||
* \file atomic/detail/extra_ops_generic.hpp
|
||||
*
|
||||
* This header contains generic implementation of the extra atomic operations.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ATOMIC_DETAIL_EXTRA_OPS_GENERIC_HPP_INCLUDED_
|
||||
#define BOOST_ATOMIC_DETAIL_EXTRA_OPS_GENERIC_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/integral_extend.hpp>
|
||||
#include <boost/atomic/detail/extra_operations_fwd.hpp>
|
||||
#include <boost/atomic/capabilities.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(push)
|
||||
// unary minus operator applied to unsigned type, result still unsigned
|
||||
#pragma warning(disable: 4146)
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
//! Generic implementation of extra operations
|
||||
template< typename Base, std::size_t Size, bool Signed, bool = Base::full_cas_based >
|
||||
struct generic_extra_operations :
|
||||
public Base
|
||||
{
|
||||
typedef Base base_type;
|
||||
typedef typename base_type::storage_type storage_type;
|
||||
typedef typename make_storage_type< Size >::type emulated_storage_type;
|
||||
|
||||
static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type old_val;
|
||||
atomics::detail::non_atomic_load(storage, old_val);
|
||||
while (!base_type::compare_exchange_weak(storage, old_val, atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(-old_val)), order, memory_order_relaxed)) {}
|
||||
return old_val;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type old_val, new_val;
|
||||
atomics::detail::non_atomic_load(storage, old_val);
|
||||
do
|
||||
{
|
||||
new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(-old_val));
|
||||
}
|
||||
while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed));
|
||||
return new_val;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return base_type::fetch_add(storage, v, order) + v;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return base_type::fetch_sub(storage, v, order) - v;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return base_type::fetch_and(storage, v, order) & v;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return base_type::fetch_or(storage, v, order) | v;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return base_type::fetch_xor(storage, v, order) ^ v;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return base_type::fetch_xor(storage, atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(~static_cast< emulated_storage_type >(0u))), order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(~static_cast< emulated_storage_type >(0u)));
|
||||
return base_type::fetch_xor(storage, mask, order) ^ mask;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE void opaque_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
base_type::fetch_add(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE void opaque_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
base_type::fetch_sub(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
fetch_negate(storage, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE void opaque_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
base_type::fetch_and(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE void opaque_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
base_type::fetch_or(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE void opaque_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
base_type::fetch_xor(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
fetch_complement(storage, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool add_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return !!static_cast< emulated_storage_type >(add(storage, v, order));
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool sub_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return !!static_cast< emulated_storage_type >(sub(storage, v, order));
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool negate_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return !!negate(storage, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool and_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return !!bitwise_and(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool or_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return !!bitwise_or(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool xor_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return !!bitwise_xor(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool complement_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return !!static_cast< emulated_storage_type >(bitwise_complement(storage, order));
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(static_cast< emulated_storage_type >(1u) << bit_number));
|
||||
storage_type old_val = base_type::fetch_or(storage, mask, order);
|
||||
return !!(old_val & mask);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(static_cast< emulated_storage_type >(1u) << bit_number));
|
||||
storage_type old_val = base_type::fetch_and(storage, ~mask, order);
|
||||
return !!(old_val & mask);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool bit_test_and_complement(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(static_cast< emulated_storage_type >(1u) << bit_number));
|
||||
storage_type old_val = base_type::fetch_xor(storage, mask, order);
|
||||
return !!(old_val & mask);
|
||||
}
|
||||
};
|
||||
|
||||
//! Specialization for cases when the platform only natively supports CAS
|
||||
template< typename Base, std::size_t Size, bool Signed >
|
||||
struct generic_extra_operations< Base, Size, Signed, true > :
|
||||
public Base
|
||||
{
|
||||
typedef Base base_type;
|
||||
typedef typename base_type::storage_type storage_type;
|
||||
typedef typename make_storage_type< Size >::type emulated_storage_type;
|
||||
|
||||
static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type old_val;
|
||||
atomics::detail::non_atomic_load(storage, old_val);
|
||||
while (!base_type::compare_exchange_weak(storage, old_val, atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(-old_val)), order, memory_order_relaxed)) {}
|
||||
return old_val;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type old_val, new_val;
|
||||
atomics::detail::non_atomic_load(storage, old_val);
|
||||
do
|
||||
{
|
||||
new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(-old_val));
|
||||
}
|
||||
while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed));
|
||||
return new_val;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type old_val, new_val;
|
||||
atomics::detail::non_atomic_load(storage, old_val);
|
||||
do
|
||||
{
|
||||
new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(old_val + v));
|
||||
}
|
||||
while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed));
|
||||
return new_val;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type old_val, new_val;
|
||||
atomics::detail::non_atomic_load(storage, old_val);
|
||||
do
|
||||
{
|
||||
new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(old_val - v));
|
||||
}
|
||||
while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed));
|
||||
return new_val;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type old_val, new_val;
|
||||
atomics::detail::non_atomic_load(storage, old_val);
|
||||
do
|
||||
{
|
||||
new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(old_val & v));
|
||||
}
|
||||
while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed));
|
||||
return new_val;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type old_val, new_val;
|
||||
atomics::detail::non_atomic_load(storage, old_val);
|
||||
do
|
||||
{
|
||||
new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(old_val | v));
|
||||
}
|
||||
while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed));
|
||||
return new_val;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type old_val, new_val;
|
||||
atomics::detail::non_atomic_load(storage, old_val);
|
||||
do
|
||||
{
|
||||
new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(old_val ^ v));
|
||||
}
|
||||
while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed));
|
||||
return new_val;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return base_type::fetch_xor(storage, atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(~static_cast< emulated_storage_type >(0u))), order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return bitwise_xor(storage, atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(~static_cast< emulated_storage_type >(0u))), order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE void opaque_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
base_type::fetch_add(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE void opaque_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
base_type::fetch_sub(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
fetch_negate(storage, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE void opaque_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
base_type::fetch_and(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE void opaque_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
base_type::fetch_or(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE void opaque_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
base_type::fetch_xor(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
fetch_complement(storage, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool add_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return !!static_cast< emulated_storage_type >(add(storage, v, order));
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool sub_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return !!static_cast< emulated_storage_type >(sub(storage, v, order));
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool negate_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return !!negate(storage, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool and_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return !!bitwise_and(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool or_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return !!bitwise_or(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool xor_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return !!bitwise_xor(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool complement_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return !!static_cast< emulated_storage_type >(bitwise_complement(storage, order));
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(static_cast< emulated_storage_type >(1u) << bit_number));
|
||||
storage_type old_val = base_type::fetch_or(storage, mask, order);
|
||||
return !!(old_val & mask);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(static_cast< emulated_storage_type >(1u) << bit_number));
|
||||
storage_type old_val = base_type::fetch_and(storage, ~mask, order);
|
||||
return !!(old_val & mask);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool bit_test_and_complement(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(static_cast< emulated_storage_type >(1u) << bit_number));
|
||||
storage_type old_val = base_type::fetch_xor(storage, mask, order);
|
||||
return !!(old_val & mask);
|
||||
}
|
||||
};
|
||||
|
||||
// Default extra_operations template definition will be used unless specialized for a specific platform
|
||||
template< typename Base, std::size_t Size, bool Signed >
|
||||
struct extra_operations< Base, Size, Signed, true > :
|
||||
public generic_extra_operations< Base, Size, Signed >
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace atomics
|
||||
} // namespace boost
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_EXTRA_OPS_GENERIC_HPP_INCLUDED_
|
106
boost/atomic/detail/extra_ops_msvc_arm.hpp
Normal file
106
boost/atomic/detail/extra_ops_msvc_arm.hpp
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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) 2017 Andrey Semashev
|
||||
*/
|
||||
/*!
|
||||
* \file atomic/detail/extra_ops_msvc_arm.hpp
|
||||
*
|
||||
* This header contains implementation of the extra atomic operations for ARM.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ATOMIC_DETAIL_EXTRA_OPS_MSVC_ARM_HPP_INCLUDED_
|
||||
#define BOOST_ATOMIC_DETAIL_EXTRA_OPS_MSVC_ARM_HPP_INCLUDED_
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/memory_order.hpp>
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
#include <boost/atomic/detail/interlocked.hpp>
|
||||
#include <boost/atomic/detail/storage_type.hpp>
|
||||
#include <boost/atomic/detail/extra_operations_fwd.hpp>
|
||||
#include <boost/atomic/detail/extra_ops_generic.hpp>
|
||||
#include <boost/atomic/capabilities.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
#if defined(BOOST_ATOMIC_INTERLOCKED_BTS) && defined(BOOST_ATOMIC_INTERLOCKED_BTR)
|
||||
|
||||
template< typename Base, std::size_t Size, bool Signed >
|
||||
struct extra_operations< Base, 4u, Signed, true > :
|
||||
public generic_extra_operations< Base, 4u, Signed >
|
||||
{
|
||||
typedef generic_extra_operations< Base, 4u, Signed > base_type;
|
||||
typedef typename base_type::storage_type storage_type;
|
||||
|
||||
static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
#if defined(BOOST_ATOMIC_INTERLOCKED_BTS_RELAXED) && defined(BOOST_ATOMIC_INTERLOCKED_BTS_ACQUIRE) && defined(BOOST_ATOMIC_INTERLOCKED_BTS_RELEASE)
|
||||
bool result;
|
||||
switch (order)
|
||||
{
|
||||
case memory_order_relaxed:
|
||||
result = !!BOOST_ATOMIC_INTERLOCKED_BTS_RELAXED(&storage, bit_number);
|
||||
break;
|
||||
case memory_order_consume:
|
||||
case memory_order_acquire:
|
||||
result = !!BOOST_ATOMIC_INTERLOCKED_BTS_ACQUIRE(&storage, bit_number);
|
||||
break;
|
||||
case memory_order_release:
|
||||
result = !!BOOST_ATOMIC_INTERLOCKED_BTS_RELEASE(&storage, bit_number);
|
||||
break;
|
||||
case memory_order_acq_rel:
|
||||
case memory_order_seq_cst:
|
||||
default:
|
||||
result = !!BOOST_ATOMIC_INTERLOCKED_BTS(&storage, bit_number);
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
#else
|
||||
return !!BOOST_ATOMIC_INTERLOCKED_BTS(&storage, bit_number);
|
||||
#endif
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
#if defined(BOOST_ATOMIC_INTERLOCKED_BTR_RELAXED) && defined(BOOST_ATOMIC_INTERLOCKED_BTR_ACQUIRE) && defined(BOOST_ATOMIC_INTERLOCKED_BTR_RELEASE)
|
||||
bool result;
|
||||
switch (order)
|
||||
{
|
||||
case memory_order_relaxed:
|
||||
result = !!BOOST_ATOMIC_INTERLOCKED_BTR_RELAXED(&storage, bit_number);
|
||||
break;
|
||||
case memory_order_consume:
|
||||
case memory_order_acquire:
|
||||
result = !!BOOST_ATOMIC_INTERLOCKED_BTR_ACQUIRE(&storage, bit_number);
|
||||
break;
|
||||
case memory_order_release:
|
||||
result = !!BOOST_ATOMIC_INTERLOCKED_BTR_RELEASE(&storage, bit_number);
|
||||
break;
|
||||
case memory_order_acq_rel:
|
||||
case memory_order_seq_cst:
|
||||
default:
|
||||
result = !!BOOST_ATOMIC_INTERLOCKED_BTR(&storage, bit_number);
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
#else
|
||||
return !!BOOST_ATOMIC_INTERLOCKED_BTR(&storage, bit_number);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
#endif // defined(BOOST_ATOMIC_INTERLOCKED_BTS) && defined(BOOST_ATOMIC_INTERLOCKED_BTR)
|
||||
|
||||
} // namespace detail
|
||||
} // namespace atomics
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_EXTRA_OPS_MSVC_ARM_HPP_INCLUDED_
|
1301
boost/atomic/detail/extra_ops_msvc_x86.hpp
Normal file
1301
boost/atomic/detail/extra_ops_msvc_x86.hpp
Normal file
File diff suppressed because it is too large
Load Diff
142
boost/atomic/detail/float_sizes.hpp
Normal file
142
boost/atomic/detail/float_sizes.hpp
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* 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) 2018 Andrey Semashev
|
||||
*/
|
||||
/*!
|
||||
* \file atomic/detail/float_sizes.hpp
|
||||
*
|
||||
* This header defines macros for testing buitin floating point type sizes
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ATOMIC_DETAIL_FLOAT_SIZES_HPP_INCLUDED_
|
||||
#define BOOST_ATOMIC_DETAIL_FLOAT_SIZES_HPP_INCLUDED_
|
||||
|
||||
#include <float.h>
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
// Detect value sizes of the different floating point types. The value sizes may be less than the corresponding type sizes
|
||||
// if the type contains padding bits. This is typical e.g. with 80-bit extended float types, which are often represented as 128-bit types.
|
||||
// See: https://en.wikipedia.org/wiki/IEEE_754
|
||||
// For Intel x87 extended double see: https://en.wikipedia.org/wiki/Extended_precision#x86_Architecture_Extended_Precision_Format
|
||||
// For IBM extended double (a.k.a. double-double) see: https://en.wikipedia.org/wiki/Long_double#Implementations, https://gcc.gnu.org/wiki/Ieee128PowerPC
|
||||
#if (FLT_RADIX+0) == 2
|
||||
|
||||
#if ((FLT_MANT_DIG+0) == 11) && ((FLT_MAX_EXP+0) == 16) // IEEE 754 binary16
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT_VALUE 2
|
||||
#elif ((FLT_MANT_DIG+0) == 24) && ((FLT_MAX_EXP+0) == 128) // IEEE 754 binary32
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT_VALUE 4
|
||||
#elif ((FLT_MANT_DIG+0) == 53) && ((FLT_MAX_EXP+0) == 1024) // IEEE 754 binary64
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT_VALUE 8
|
||||
#elif ((FLT_MANT_DIG+0) == 64) && ((FLT_MAX_EXP+0) == 16384) // x87 extended double
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT_VALUE 10
|
||||
#elif ((FLT_MANT_DIG+0) == 106) && ((FLT_MAX_EXP+0) == 1024) // IBM extended double
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT_VALUE 16
|
||||
#elif ((FLT_MANT_DIG+0) == 113) && ((FLT_MAX_EXP+0) == 16384) // IEEE 754 binary128
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT_VALUE 16
|
||||
#elif ((FLT_MANT_DIG+0) == 237) && ((FLT_MAX_EXP+0) == 262144) // IEEE 754 binary256
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT_VALUE 32
|
||||
#endif
|
||||
|
||||
#if ((DBL_MANT_DIG+0) == 11) && ((DBL_MAX_EXP+0) == 16) // IEEE 754 binary16
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE_VALUE 2
|
||||
#elif ((DBL_MANT_DIG+0) == 24) && ((DBL_MAX_EXP+0) == 128) // IEEE 754 binary32
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE_VALUE 4
|
||||
#elif ((DBL_MANT_DIG+0) == 53) && ((DBL_MAX_EXP+0) == 1024) // IEEE 754 binary64
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE_VALUE 8
|
||||
#elif ((DBL_MANT_DIG+0) == 64) && ((DBL_MAX_EXP+0) == 16384) // x87 extended double
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE_VALUE 10
|
||||
#elif ((DBL_MANT_DIG+0) == 106) && ((DBL_MAX_EXP+0) == 1024) // IBM extended double
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE_VALUE 16
|
||||
#elif ((DBL_MANT_DIG+0) == 113) && ((DBL_MAX_EXP+0) == 16384) // IEEE 754 binary128
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE_VALUE 16
|
||||
#elif ((DBL_MANT_DIG+0) == 237) && ((DBL_MAX_EXP+0) == 262144) // IEEE 754 binary256
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE_VALUE 32
|
||||
#endif
|
||||
|
||||
#if ((LDBL_MANT_DIG+0) == 11) && ((LDBL_MAX_EXP+0) == 16) // IEEE 754 binary16
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE_VALUE 2
|
||||
#elif ((LDBL_MANT_DIG+0) == 24) && ((LDBL_MAX_EXP+0) == 128) // IEEE 754 binary32
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE_VALUE 4
|
||||
#elif ((LDBL_MANT_DIG+0) == 53) && ((LDBL_MAX_EXP+0) == 1024) // IEEE 754 binary64
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE_VALUE 8
|
||||
#elif ((LDBL_MANT_DIG+0) == 64) && ((LDBL_MAX_EXP+0) == 16384) // x87 extended double
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE_VALUE 10
|
||||
#elif ((LDBL_MANT_DIG+0) == 106) && ((LDBL_MAX_EXP+0) == 1024) // IBM extended double
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE_VALUE 16
|
||||
#elif ((LDBL_MANT_DIG+0) == 113) && ((LDBL_MAX_EXP+0) == 16384) // IEEE 754 binary128
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE_VALUE 16
|
||||
#elif ((LDBL_MANT_DIG+0) == 237) && ((LDBL_MAX_EXP+0) == 262144) // IEEE 754 binary256
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE_VALUE 32
|
||||
#endif
|
||||
|
||||
#elif (FLT_RADIX+0) == 10
|
||||
|
||||
#if ((FLT_MANT_DIG+0) == 7) && ((FLT_MAX_EXP+0) == 97) // IEEE 754 decimal32
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT_VALUE 4
|
||||
#elif ((FLT_MANT_DIG+0) == 16) && ((FLT_MAX_EXP+0) == 385) // IEEE 754 decimal64
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT_VALUE 8
|
||||
#elif ((FLT_MANT_DIG+0) == 34) && ((FLT_MAX_EXP+0) == 6145) // IEEE 754 decimal128
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT_VALUE 16
|
||||
#endif
|
||||
|
||||
#if ((DBL_MANT_DIG+0) == 7) && ((DBL_MAX_EXP+0) == 97) // IEEE 754 decimal32
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE_VALUE 4
|
||||
#elif ((DBL_MANT_DIG+0) == 16) && ((DBL_MAX_EXP+0) == 385) // IEEE 754 decimal64
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE_VALUE 8
|
||||
#elif ((DBL_MANT_DIG+0) == 34) && ((DBL_MAX_EXP+0) == 6145) // IEEE 754 decimal128
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE_VALUE 16
|
||||
#endif
|
||||
|
||||
#if ((LDBL_MANT_DIG+0) == 7) && ((LDBL_MAX_EXP+0) == 97) // IEEE 754 decimal32
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE_VALUE 4
|
||||
#elif ((LDBL_MANT_DIG+0) == 16) && ((LDBL_MAX_EXP+0) == 385) // IEEE 754 decimal64
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE_VALUE 8
|
||||
#elif ((LDBL_MANT_DIG+0) == 34) && ((LDBL_MAX_EXP+0) == 6145) // IEEE 754 decimal128
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE_VALUE 16
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// GCC and compatible compilers define internal macros with builtin type traits
|
||||
#if defined(__SIZEOF_FLOAT__)
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT __SIZEOF_FLOAT__
|
||||
#endif
|
||||
#if defined(__SIZEOF_DOUBLE__)
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE __SIZEOF_DOUBLE__
|
||||
#endif
|
||||
#if defined(__SIZEOF_LONG_DOUBLE__)
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE __SIZEOF_LONG_DOUBLE__
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT) || !defined(BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE) || !defined(BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE)
|
||||
|
||||
#define BOOST_ATOMIC_DETAIL_ALIGN_SIZE_TO_POWER_OF_2(x)\
|
||||
((x) == 1u ? 1u : ((x) == 2u ? 2u : ((x) <= 4u ? 4u : ((x) <= 8u ? 8u : ((x) <= 16u ? 16u : ((x) <= 32u ? 32u : (x)))))))
|
||||
|
||||
// Make our best guess. These sizes may not be accurate, but they are good enough to estimate the size of the storage required to hold these types.
|
||||
#if !defined(BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT) && defined(BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT_VALUE)
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT BOOST_ATOMIC_DETAIL_ALIGN_SIZE_TO_POWER_OF_2(BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT_VALUE)
|
||||
#endif
|
||||
#if !defined(BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE) && defined(BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE_VALUE)
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE BOOST_ATOMIC_DETAIL_ALIGN_SIZE_TO_POWER_OF_2(BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE_VALUE)
|
||||
#endif
|
||||
#if !defined(BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE) && defined(BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE_VALUE)
|
||||
#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE BOOST_ATOMIC_DETAIL_ALIGN_SIZE_TO_POWER_OF_2(BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE_VALUE)
|
||||
#endif
|
||||
|
||||
#endif // !defined(BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT) || !defined(BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE) || !defined(BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE)
|
||||
|
||||
#if !defined(BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT_VALUE) || !defined(BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT) ||\
|
||||
!defined(BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE_VALUE) || !defined(BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE) ||\
|
||||
!defined(BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE_VALUE) || !defined(BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE)
|
||||
#error Boost.Atomic: Failed to determine builtin floating point type sizes, the target platform is not supported. Please, report to the developers (patches are welcome).
|
||||
#endif
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_FLOAT_SIZES_HPP_INCLUDED_
|
28
boost/atomic/detail/fp_operations.hpp
Normal file
28
boost/atomic/detail/fp_operations.hpp
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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) 2018 Andrey Semashev
|
||||
*/
|
||||
/*!
|
||||
* \file atomic/detail/fp_operations.hpp
|
||||
*
|
||||
* This header defines floating point atomic operations, including the generic version.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ATOMIC_DETAIL_FP_OPERATIONS_HPP_INCLUDED_
|
||||
#define BOOST_ATOMIC_DETAIL_FP_OPERATIONS_HPP_INCLUDED_
|
||||
|
||||
#include <boost/atomic/detail/fp_ops_generic.hpp>
|
||||
#include <boost/atomic/detail/fp_ops_emulated.hpp>
|
||||
|
||||
#if !defined(BOOST_ATOMIC_DETAIL_FP_BACKEND_GENERIC)
|
||||
#include BOOST_ATOMIC_DETAIL_FP_BACKEND_HEADER(boost/atomic/detail/fp_ops_)
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_FP_OPERATIONS_HPP_INCLUDED_
|
35
boost/atomic/detail/fp_operations_fwd.hpp
Normal file
35
boost/atomic/detail/fp_operations_fwd.hpp
Normal 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) 2018 Andrey Semashev
|
||||
*/
|
||||
/*!
|
||||
* \file atomic/detail/fp_operations_fwd.hpp
|
||||
*
|
||||
* This header contains forward declaration of the \c fp_operations template.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ATOMIC_DETAIL_FP_OPERATIONS_FWD_HPP_INCLUDED_
|
||||
#define BOOST_ATOMIC_DETAIL_FP_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< typename Base, typename Value, std::size_t Size, bool = Base::is_always_lock_free >
|
||||
struct fp_operations;
|
||||
|
||||
} // namespace detail
|
||||
} // namespace atomics
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_FP_OPERATIONS_FWD_HPP_INCLUDED_
|
72
boost/atomic/detail/fp_ops_emulated.hpp
Normal file
72
boost/atomic/detail/fp_ops_emulated.hpp
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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) 2018 Andrey Semashev
|
||||
*/
|
||||
/*!
|
||||
* \file atomic/detail/fp_ops_emulated.hpp
|
||||
*
|
||||
* This header contains emulated (lock-based) implementation of the floating point atomic operations.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ATOMIC_DETAIL_FP_OPS_EMULATED_HPP_INCLUDED_
|
||||
#define BOOST_ATOMIC_DETAIL_FP_OPS_EMULATED_HPP_INCLUDED_
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/memory_order.hpp>
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
#include <boost/atomic/detail/bitwise_fp_cast.hpp>
|
||||
#include <boost/atomic/detail/fp_operations_fwd.hpp>
|
||||
#include <boost/atomic/detail/lockpool.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
//! Generic implementation of floating point operations
|
||||
template< typename Base, typename Value, std::size_t Size >
|
||||
struct emulated_fp_operations :
|
||||
public Base
|
||||
{
|
||||
typedef Base base_type;
|
||||
typedef typename base_type::storage_type storage_type;
|
||||
typedef Value value_type;
|
||||
|
||||
static BOOST_FORCEINLINE value_type fetch_add(storage_type volatile& storage, value_type v, memory_order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type& s = const_cast< storage_type& >(storage);
|
||||
lockpool::scoped_lock lock(&storage);
|
||||
value_type old_val = atomics::detail::bitwise_fp_cast< value_type >(s);
|
||||
value_type new_val = old_val + v;
|
||||
s = atomics::detail::bitwise_fp_cast< storage_type >(new_val);
|
||||
return old_val;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE value_type fetch_sub(storage_type volatile& storage, value_type v, memory_order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type& s = const_cast< storage_type& >(storage);
|
||||
lockpool::scoped_lock lock(&storage);
|
||||
value_type old_val = atomics::detail::bitwise_fp_cast< value_type >(s);
|
||||
value_type new_val = old_val - v;
|
||||
s = atomics::detail::bitwise_fp_cast< storage_type >(new_val);
|
||||
return old_val;
|
||||
}
|
||||
};
|
||||
|
||||
template< typename Base, typename Value, std::size_t Size >
|
||||
struct fp_operations< Base, Value, Size, false > :
|
||||
public emulated_fp_operations< Base, Value, Size >
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace atomics
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_FP_OPS_EMULATED_HPP_INCLUDED_
|
83
boost/atomic/detail/fp_ops_generic.hpp
Normal file
83
boost/atomic/detail/fp_ops_generic.hpp
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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) 2018 Andrey Semashev
|
||||
*/
|
||||
/*!
|
||||
* \file atomic/detail/fp_ops_generic.hpp
|
||||
*
|
||||
* This header contains generic implementation of the floating point atomic operations.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ATOMIC_DETAIL_FP_OPS_GENERIC_HPP_INCLUDED_
|
||||
#define BOOST_ATOMIC_DETAIL_FP_OPS_GENERIC_HPP_INCLUDED_
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/memory_order.hpp>
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
#include <boost/atomic/detail/bitwise_fp_cast.hpp>
|
||||
#include <boost/atomic/detail/storage_type.hpp>
|
||||
#include <boost/atomic/detail/fp_operations_fwd.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
//! Generic implementation of floating point operations
|
||||
template< typename Base, typename Value, std::size_t Size >
|
||||
struct generic_fp_operations :
|
||||
public Base
|
||||
{
|
||||
typedef Base base_type;
|
||||
typedef typename base_type::storage_type storage_type;
|
||||
typedef Value value_type;
|
||||
|
||||
static BOOST_FORCEINLINE value_type fetch_add(storage_type volatile& storage, value_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type old_storage, new_storage;
|
||||
value_type old_val, new_val;
|
||||
atomics::detail::non_atomic_load(storage, old_storage);
|
||||
do
|
||||
{
|
||||
old_val = atomics::detail::bitwise_fp_cast< value_type >(old_storage);
|
||||
new_val = old_val + v;
|
||||
new_storage = atomics::detail::bitwise_fp_cast< storage_type >(new_val);
|
||||
}
|
||||
while (!base_type::compare_exchange_weak(storage, old_storage, new_storage, order, memory_order_relaxed));
|
||||
return old_val;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE value_type fetch_sub(storage_type volatile& storage, value_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type old_storage, new_storage;
|
||||
value_type old_val, new_val;
|
||||
atomics::detail::non_atomic_load(storage, old_storage);
|
||||
do
|
||||
{
|
||||
old_val = atomics::detail::bitwise_fp_cast< value_type >(old_storage);
|
||||
new_val = old_val - v;
|
||||
new_storage = atomics::detail::bitwise_fp_cast< storage_type >(new_val);
|
||||
}
|
||||
while (!base_type::compare_exchange_weak(storage, old_storage, new_storage, order, memory_order_relaxed));
|
||||
return old_val;
|
||||
}
|
||||
};
|
||||
|
||||
// Default fp_operations template definition will be used unless specialized for a specific platform
|
||||
template< typename Base, typename Value, std::size_t Size >
|
||||
struct fp_operations< Base, Value, Size, true > :
|
||||
public generic_fp_operations< Base, Value, Size >
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace atomics
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_FP_OPS_GENERIC_HPP_INCLUDED_
|
67
boost/atomic/detail/hwcaps_gcc_arm.hpp
Normal file
67
boost/atomic/detail/hwcaps_gcc_arm.hpp
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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) 2017 Andrey Semashev
|
||||
*/
|
||||
/*!
|
||||
* \file atomic/detail/hwcaps_gcc_arm.hpp
|
||||
*
|
||||
* This header defines hardware capabilities macros for ARM
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ATOMIC_DETAIL_HWCAPS_GCC_ARM_HPP_INCLUDED_
|
||||
#define BOOST_ATOMIC_DETAIL_HWCAPS_GCC_ARM_HPP_INCLUDED_
|
||||
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
#include <boost/atomic/detail/platform.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && defined(__arm__) && (BOOST_ATOMIC_DETAIL_ARM_ARCH+0) >= 6
|
||||
|
||||
#if BOOST_ATOMIC_DETAIL_ARM_ARCH > 6
|
||||
// ARMv7 and later have dmb instruction
|
||||
#define BOOST_ATOMIC_DETAIL_ARM_HAS_DMB 1
|
||||
#endif
|
||||
|
||||
#if defined(__ARM_FEATURE_LDREX)
|
||||
|
||||
#if (__ARM_FEATURE_LDREX & 1)
|
||||
#define BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXB_STREXB 1
|
||||
#endif
|
||||
#if (__ARM_FEATURE_LDREX & 2)
|
||||
#define BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXH_STREXH 1
|
||||
#endif
|
||||
#if (__ARM_FEATURE_LDREX & 8)
|
||||
#define BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXD_STREXD 1
|
||||
#endif
|
||||
|
||||
#else // defined(__ARM_FEATURE_LDREX)
|
||||
|
||||
#if !(defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6Z__))
|
||||
|
||||
// ARMv6k and ARMv7 have 8 and 16-bit ldrex/strex variants, but at least GCC 4.7 fails to compile them. GCC 4.9 is known to work.
|
||||
#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 409
|
||||
#define BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXB_STREXB 1
|
||||
#define BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXH_STREXH 1
|
||||
#endif
|
||||
|
||||
#if !(((defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6ZK__)) && defined(__thumb__)) || defined(__ARM_ARCH_7__) || 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 // !(defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6Z__))
|
||||
|
||||
#endif // defined(__ARM_FEATURE_LDREX)
|
||||
|
||||
#endif // defined(__GNUC__) && defined(__arm__) && (BOOST_ATOMIC_DETAIL_ARM_ARCH+0) >= 6
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_HWCAPS_GCC_ARM_HPP_INCLUDED_
|
42
boost/atomic/detail/hwcaps_gcc_ppc.hpp
Normal file
42
boost/atomic/detail/hwcaps_gcc_ppc.hpp
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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) 2017 Andrey Semashev
|
||||
*/
|
||||
/*!
|
||||
* \file atomic/detail/hwcaps_gcc_ppc.hpp
|
||||
*
|
||||
* This header defines hardware capabilities macros for PowerPC
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ATOMIC_DETAIL_HWCAPS_GCC_PPC_HPP_INCLUDED_
|
||||
#define BOOST_ATOMIC_DETAIL_HWCAPS_GCC_PPC_HPP_INCLUDED_
|
||||
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#if defined(__POWERPC__) || defined(__PPC__)
|
||||
|
||||
#if defined(_ARCH_PWR8)
|
||||
// Power8 and later architectures have 8 and 16-bit instructions
|
||||
#define BOOST_ATOMIC_DETAIL_PPC_HAS_LBARX_STBCX
|
||||
#define BOOST_ATOMIC_DETAIL_PPC_HAS_LHARX_STHCX
|
||||
#endif
|
||||
|
||||
#if defined(__powerpc64__) || defined(__PPC64__)
|
||||
// Power7 and later architectures in 64-bit mode have 64-bit instructions
|
||||
#define BOOST_ATOMIC_DETAIL_PPC_HAS_LDARX_STDCX
|
||||
#if defined(_ARCH_PWR8)
|
||||
// Power8 also has 128-bit instructions
|
||||
#define BOOST_ATOMIC_DETAIL_PPC_HAS_LQARX_STQCX
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // defined(__POWERPC__) || defined(__PPC__)
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_HWCAPS_GCC_PPC_HPP_INCLUDED_
|
58
boost/atomic/detail/hwcaps_gcc_x86.hpp
Normal file
58
boost/atomic/detail/hwcaps_gcc_x86.hpp
Normal 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) 2017 Andrey Semashev
|
||||
*/
|
||||
/*!
|
||||
* \file atomic/detail/hwcaps_gcc_x86.hpp
|
||||
*
|
||||
* This header defines hardware capabilities macros for x86
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ATOMIC_DETAIL_HWCAPS_GCC_X86_HPP_INCLUDED_
|
||||
#define BOOST_ATOMIC_DETAIL_HWCAPS_GCC_X86_HPP_INCLUDED_
|
||||
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
|
||||
#if defined(__i386__) &&\
|
||||
(\
|
||||
defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) ||\
|
||||
defined(__i586__) || defined(__i686__) || defined(__SSE__)\
|
||||
)
|
||||
#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(__x86_64__) || defined(__SSE2__)
|
||||
// Use mfence only if SSE2 is available
|
||||
#define BOOST_ATOMIC_DETAIL_X86_HAS_MFENCE 1
|
||||
#endif
|
||||
|
||||
#else // defined(__GNUC__)
|
||||
|
||||
#if defined(__i386__) && !defined(BOOST_ATOMIC_NO_CMPXCHG8B)
|
||||
#define BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B 1
|
||||
#endif
|
||||
|
||||
#if defined(__x86_64__) && !defined(BOOST_ATOMIC_NO_CMPXCHG16B)
|
||||
#define BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B 1
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_ATOMIC_NO_MFENCE)
|
||||
#define BOOST_ATOMIC_DETAIL_X86_HAS_MFENCE 1
|
||||
#endif
|
||||
|
||||
#endif // defined(__GNUC__)
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_HWCAPS_GCC_X86_HPP_INCLUDED_
|
140
boost/atomic/detail/int_sizes.hpp
Normal file
140
boost/atomic/detail/int_sizes.hpp
Normal 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_ARM64) || 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 (patches are welcome).
|
||||
#endif
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_INT_SIZES_HPP_INCLUDED_
|
105
boost/atomic/detail/integral_extend.hpp
Normal file
105
boost/atomic/detail/integral_extend.hpp
Normal 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) 2018 Andrey Semashev
|
||||
*/
|
||||
/*!
|
||||
* \file atomic/detail/integral_extend.hpp
|
||||
*
|
||||
* This header defines sign/zero extension utilities for Boost.Atomic. The tools assume two's complement signed integer representation.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ATOMIC_DETAIL_INTEGRAL_EXTEND_HPP_INCLUDED_
|
||||
#define BOOST_ATOMIC_DETAIL_INTEGRAL_EXTEND_HPP_INCLUDED_
|
||||
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
#include <boost/atomic/detail/bitwise_cast.hpp>
|
||||
#include <boost/atomic/detail/type_traits/integral_constant.hpp>
|
||||
#include <boost/atomic/detail/type_traits/is_signed.hpp>
|
||||
#include <boost/atomic/detail/type_traits/make_signed.hpp>
|
||||
#include <boost/atomic/detail/type_traits/make_unsigned.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
template< typename Output, typename Input >
|
||||
BOOST_FORCEINLINE Output zero_extend_impl(Input input, atomics::detail::true_type) BOOST_NOEXCEPT
|
||||
{
|
||||
// Note: If we are casting with truncation or to the same-sized output, don't cause signed integer overflow by this chain of conversions
|
||||
return atomics::detail::bitwise_cast< Output >(static_cast< typename atomics::detail::make_unsigned< Output >::type >(
|
||||
static_cast< typename atomics::detail::make_unsigned< Input >::type >(input)));
|
||||
}
|
||||
|
||||
template< typename Output, typename Input >
|
||||
BOOST_FORCEINLINE Output zero_extend_impl(Input input, atomics::detail::false_type) BOOST_NOEXCEPT
|
||||
{
|
||||
return static_cast< Output >(static_cast< typename atomics::detail::make_unsigned< Input >::type >(input));
|
||||
}
|
||||
|
||||
//! Zero-extends or truncates (wraps) input operand to fit in the output type
|
||||
template< typename Output, typename Input >
|
||||
BOOST_FORCEINLINE Output zero_extend(Input input) BOOST_NOEXCEPT
|
||||
{
|
||||
return atomics::detail::zero_extend_impl< Output >(input, atomics::detail::integral_constant< bool, atomics::detail::is_signed< Output >::value >());
|
||||
}
|
||||
|
||||
//! Truncates (wraps) input operand to fit in the output type
|
||||
template< typename Output, typename Input >
|
||||
BOOST_FORCEINLINE Output integral_truncate(Input input) BOOST_NOEXCEPT
|
||||
{
|
||||
// zero_extend does the truncation
|
||||
return atomics::detail::zero_extend< Output >(input);
|
||||
}
|
||||
|
||||
template< typename Output, typename Input >
|
||||
BOOST_FORCEINLINE Output sign_extend_impl(Input input, atomics::detail::true_type) BOOST_NOEXCEPT
|
||||
{
|
||||
return atomics::detail::integral_truncate< Output >(input);
|
||||
}
|
||||
|
||||
template< typename Output, typename Input >
|
||||
BOOST_FORCEINLINE Output sign_extend_impl(Input input, atomics::detail::false_type) BOOST_NOEXCEPT
|
||||
{
|
||||
return static_cast< Output >(atomics::detail::bitwise_cast< typename atomics::detail::make_signed< Input >::type >(input));
|
||||
}
|
||||
|
||||
//! Sign-extends or truncates (wraps) input operand to fit in the output type
|
||||
template< typename Output, typename Input >
|
||||
BOOST_FORCEINLINE Output sign_extend(Input input) BOOST_NOEXCEPT
|
||||
{
|
||||
return atomics::detail::sign_extend_impl< Output >(input, atomics::detail::integral_constant< bool, sizeof(Output) <= sizeof(Input) >());
|
||||
}
|
||||
|
||||
//! Sign-extends or truncates (wraps) input operand to fit in the output type
|
||||
template< typename Output, typename Input >
|
||||
BOOST_FORCEINLINE Output integral_extend(Input input, atomics::detail::true_type) BOOST_NOEXCEPT
|
||||
{
|
||||
return atomics::detail::sign_extend< Output >(input);
|
||||
}
|
||||
|
||||
//! Zero-extends or truncates (wraps) input operand to fit in the output type
|
||||
template< typename Output, typename Input >
|
||||
BOOST_FORCEINLINE Output integral_extend(Input input, atomics::detail::false_type) BOOST_NOEXCEPT
|
||||
{
|
||||
return atomics::detail::zero_extend< Output >(input);
|
||||
}
|
||||
|
||||
//! Sign- or zero-extends or truncates (wraps) input operand to fit in the output type
|
||||
template< bool Signed, typename Output, typename Input >
|
||||
BOOST_FORCEINLINE Output integral_extend(Input input) BOOST_NOEXCEPT
|
||||
{
|
||||
return atomics::detail::integral_extend< Output >(input, atomics::detail::integral_constant< bool, Signed >());
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace atomics
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_INTEGRAL_EXTEND_HPP_INCLUDED_
|
522
boost/atomic/detail/interlocked.hpp
Normal file
522
boost/atomic/detail/interlocked.hpp
Normal file
@ -0,0 +1,522 @@
|
||||
#ifndef BOOST_ATOMIC_DETAIL_INTERLOCKED_HPP
|
||||
#define BOOST_ATOMIC_DETAIL_INTERLOCKED_HPP
|
||||
|
||||
// Copyright (c) 2009 Helge Bahmann
|
||||
// Copyright (c) 2012 - 2014, 2017 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)
|
||||
#pragma intrinsic(_interlockedbittestandset)
|
||||
#pragma intrinsic(_interlockedbittestandreset)
|
||||
#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))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_BTS(dest, arg) _interlockedbittestandset((long*)(dest), (long)(arg))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_BTR(dest, arg) _interlockedbittestandreset((long*)(dest), (long)(arg))
|
||||
|
||||
#if defined(_M_AMD64)
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma intrinsic(_interlockedbittestandset64)
|
||||
#pragma intrinsic(_interlockedbittestandreset64)
|
||||
#endif
|
||||
|
||||
#define BOOST_ATOMIC_INTERLOCKED_BTS64(dest, arg) _interlockedbittestandset64((__int64*)(dest), (__int64)(arg))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_BTR64(dest, arg) _interlockedbittestandreset64((__int64*)(dest), (__int64)(arg))
|
||||
#endif // defined(_M_AMD64)
|
||||
|
||||
#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) || defined(_M_ARM64))
|
||||
|
||||
#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))
|
||||
|
||||
#if defined(_M_ARM64)
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64((__int64*)(dest), byte_offset))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER_RELAXED(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64_RELAXED((__int64*)(dest), byte_offset))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER_ACQUIRE(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64_ACQUIRE((__int64*)(dest), byte_offset))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER_RELEASE(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64_RELEASE((__int64*)(dest), byte_offset))
|
||||
#else
|
||||
#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))
|
||||
#endif
|
||||
|
||||
#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))
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma intrinsic(_interlockedbittestandset_nf)
|
||||
#pragma intrinsic(_interlockedbittestandset_acq)
|
||||
#pragma intrinsic(_interlockedbittestandset_rel)
|
||||
#endif
|
||||
|
||||
#define BOOST_ATOMIC_INTERLOCKED_BTS_RELAXED(dest, arg) _interlockedbittestandset_nf((long*)(dest), (long)(arg))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_BTS_ACQUIRE(dest, arg) _interlockedbittestandset_acq((long*)(dest), (long)(arg))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_BTS_RELEASE(dest, arg) _interlockedbittestandset_rel((long*)(dest), (long)(arg))
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma intrinsic(_interlockedbittestandreset_nf)
|
||||
#pragma intrinsic(_interlockedbittestandreset_acq)
|
||||
#pragma intrinsic(_interlockedbittestandreset_rel)
|
||||
#endif
|
||||
|
||||
#define BOOST_ATOMIC_INTERLOCKED_BTR_RELAXED(dest, arg) _interlockedbittestandreset_nf((long*)(dest), (long)(arg))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_BTR_ACQUIRE(dest, arg) _interlockedbittestandreset_acq((long*)(dest), (long)(arg))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_BTR_RELEASE(dest, arg) _interlockedbittestandreset_rel((long*)(dest), (long)(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
|
58
boost/atomic/detail/link.hpp
Normal file
58
boost/atomic/detail/link.hpp
Normal 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
|
51
boost/atomic/detail/lockpool.hpp
Normal file
51
boost/atomic/detail/lockpool.hpp
Normal 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_
|
24
boost/atomic/detail/operations.hpp
Normal file
24
boost/atomic/detail/operations.hpp
Normal 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_
|
35
boost/atomic/detail/operations_fwd.hpp
Normal file
35
boost/atomic/detail/operations_fwd.hpp
Normal 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_
|
30
boost/atomic/detail/operations_lockfree.hpp
Normal file
30
boost/atomic/detail/operations_lockfree.hpp
Normal 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_BACKEND_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_
|
107
boost/atomic/detail/ops_cas_based.hpp
Normal file
107
boost/atomic/detail/ops_cas_based.hpp
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 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_CONSTEXPR_OR_CONST bool full_cas_based = true;
|
||||
|
||||
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_
|
162
boost/atomic/detail/ops_emulated.hpp
Normal file
162
boost/atomic/detail/ops_emulated.hpp
Normal file
@ -0,0 +1,162 @@
|
||||
/*
|
||||
* 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< std::size_t Size, bool Signed >
|
||||
struct emulated_operations
|
||||
{
|
||||
typedef typename make_storage_type< Size >::type storage_type;
|
||||
typedef typename make_storage_type< Size >::aligned aligned_storage_type;
|
||||
|
||||
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = Size;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = false;
|
||||
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = false;
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
template< std::size_t Size, bool Signed >
|
||||
struct operations :
|
||||
public emulated_operations< Size, Signed >
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace atomics
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_OPS_EMULATED_HPP_INCLUDED_
|
69
boost/atomic/detail/ops_extending_cas_based.hpp
Normal file
69
boost/atomic/detail/ops_extending_cas_based.hpp
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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>
|
||||
#include <boost/atomic/detail/integral_extend.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 >::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);
|
||||
storage_type new_val;
|
||||
do
|
||||
{
|
||||
new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(old_val + v));
|
||||
}
|
||||
while (!Base::compare_exchange_weak(storage, old_val, 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);
|
||||
storage_type new_val;
|
||||
do
|
||||
{
|
||||
new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(old_val - v));
|
||||
}
|
||||
while (!Base::compare_exchange_weak(storage, old_val, 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_
|
876
boost/atomic/detail/ops_gcc_alpha.hpp
Normal file
876
boost/atomic/detail/ops_gcc_alpha.hpp
Normal 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 <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/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_CONSTEXPR_OR_CONST bool full_cas_based = false;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
|
||||
|
||||
static BOOST_FORCEINLINE void fence_before(memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
if ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u)
|
||||
__asm__ __volatile__ ("mb" ::: "memory");
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE void fence_after(memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u)
|
||||
__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 >::type storage_type;
|
||||
typedef typename make_storage_type< 4u >::aligned aligned_storage_type;
|
||||
|
||||
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 4u;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
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 >::type storage_type;
|
||||
typedef typename make_storage_type< 8u >::aligned aligned_storage_type;
|
||||
|
||||
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 8u;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
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_
|
1397
boost/atomic/detail/ops_gcc_arm.hpp
Normal file
1397
boost/atomic/detail/ops_gcc_arm.hpp
Normal file
File diff suppressed because it is too large
Load Diff
134
boost/atomic/detail/ops_gcc_arm_common.hpp
Normal file
134
boost/atomic/detail/ops_gcc_arm_common.hpp
Normal 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) 2009 Helge Bahmann
|
||||
* Copyright (c) 2013 Tim Blechmann
|
||||
* Copyright (c) 2014 Andrey Semashev
|
||||
*/
|
||||
/*!
|
||||
* \file atomic/detail/ops_gcc_arm_common.hpp
|
||||
*
|
||||
* This header contains basic utilities for gcc ARM backend.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ATOMIC_DETAIL_OPS_GCC_ARM_COMMON_HPP_INCLUDED_
|
||||
#define BOOST_ATOMIC_DETAIL_OPS_GCC_ARM_COMMON_HPP_INCLUDED_
|
||||
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/memory_order.hpp>
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
// 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_CONSTEXPR_OR_CONST bool full_cas_based = false;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
|
||||
|
||||
static BOOST_FORCEINLINE void fence_before(memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
if ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u)
|
||||
hardware_full_fence();
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE void fence_after(memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u)
|
||||
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
|
||||
uint32_t 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
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace atomics
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_OPS_GCC_ARM_COMMON_HPP_INCLUDED_
|
392
boost/atomic/detail/ops_gcc_atomic.hpp
Normal file
392
boost/atomic/detail/ops_gcc_atomic.hpp
Normal file
@ -0,0 +1,392 @@
|
||||
/*
|
||||
* 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 <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/capabilities.hpp>
|
||||
#if (defined(__clang__) || (defined(BOOST_GCC) && (BOOST_GCC+0) >= 70000)) && (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. Unfortunately, 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
|
||||
* propagate constants even when functions are 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< std::size_t Size, bool Signed >
|
||||
struct gcc_atomic_operations
|
||||
{
|
||||
typedef typename make_storage_type< Size >::type storage_type;
|
||||
typedef typename make_storage_type< Size >::aligned aligned_storage_type;
|
||||
|
||||
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = Size;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = false;
|
||||
|
||||
// Note: In the current implementation, gcc_atomic_operations are used only when the particularly sized __atomic
|
||||
// intrinsics are always lock-free (i.e. the corresponding LOCK_FREE macro is 2). Therefore it is safe to
|
||||
// always set is_always_lock_free to true here.
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
|
||||
|
||||
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));
|
||||
}
|
||||
};
|
||||
|
||||
#if BOOST_ATOMIC_INT128_LOCK_FREE > 0
|
||||
#if (defined(__clang__) || (defined(BOOST_GCC) && (BOOST_GCC+0) >= 70000)) && 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
|
||||
// A similar problem exists with gcc 7 as well, as it requires to link with libatomic to use 16-byte intrinsics:
|
||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80878
|
||||
template< bool Signed >
|
||||
struct operations< 16u, Signed > :
|
||||
public cas_based_operations< gcc_dcas_x86_64< Signed > >
|
||||
{
|
||||
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 16u;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
template< bool Signed >
|
||||
struct operations< 16u, Signed > :
|
||||
public gcc_atomic_operations< 16u, Signed >
|
||||
{
|
||||
};
|
||||
|
||||
#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 > >
|
||||
{
|
||||
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 8u;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_signed = 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< 16u, Signed >, 8u, Signed >
|
||||
{
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
template< bool Signed >
|
||||
struct operations< 8u, Signed > :
|
||||
public gcc_atomic_operations< 8u, Signed >
|
||||
{
|
||||
};
|
||||
|
||||
#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< 8u, Signed >, 4u, Signed >
|
||||
{
|
||||
};
|
||||
|
||||
#else // !defined(BOOST_ATOMIC_DETAIL_INT64_EXTENDED)
|
||||
|
||||
template< bool Signed >
|
||||
struct operations< 4u, Signed > :
|
||||
public extending_cas_based_operations< gcc_atomic_operations< 16u, Signed >, 4u, Signed >
|
||||
{
|
||||
};
|
||||
|
||||
#endif // !defined(BOOST_ATOMIC_DETAIL_INT64_EXTENDED)
|
||||
|
||||
#else
|
||||
|
||||
template< bool Signed >
|
||||
struct operations< 4u, Signed > :
|
||||
public gcc_atomic_operations< 4u, Signed >
|
||||
{
|
||||
};
|
||||
|
||||
#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< 4u, Signed >, 2u, Signed >
|
||||
{
|
||||
};
|
||||
|
||||
#elif !defined(BOOST_ATOMIC_DETAIL_INT64_EXTENDED)
|
||||
|
||||
template< bool Signed >
|
||||
struct operations< 2u, Signed > :
|
||||
public extending_cas_based_operations< gcc_atomic_operations< 8u, Signed >, 2u, Signed >
|
||||
{
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
template< bool Signed >
|
||||
struct operations< 2u, Signed > :
|
||||
public extending_cas_based_operations< gcc_atomic_operations< 16u, Signed >, 2u, Signed >
|
||||
{
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
template< bool Signed >
|
||||
struct operations< 2u, Signed > :
|
||||
public gcc_atomic_operations< 2u, Signed >
|
||||
{
|
||||
};
|
||||
|
||||
#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< 2u, Signed >, 1u, Signed >
|
||||
{
|
||||
};
|
||||
|
||||
#elif !defined(BOOST_ATOMIC_DETAIL_INT32_EXTENDED)
|
||||
|
||||
template< bool Signed >
|
||||
struct operations< 1u, Signed > :
|
||||
public extending_cas_based_operations< gcc_atomic_operations< 4u, Signed >, 1u, Signed >
|
||||
{
|
||||
};
|
||||
|
||||
#elif !defined(BOOST_ATOMIC_DETAIL_INT64_EXTENDED)
|
||||
|
||||
template< bool Signed >
|
||||
struct operations< 1u, Signed > :
|
||||
public extending_cas_based_operations< gcc_atomic_operations< 8u, Signed >, 1u, Signed >
|
||||
{
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
template< bool Signed >
|
||||
struct operations< 1u, Signed > :
|
||||
public extending_cas_based_operations< gcc_atomic_operations< 16u, Signed >, 1u, Signed >
|
||||
{
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
template< bool Signed >
|
||||
struct operations< 1u, Signed > :
|
||||
public gcc_atomic_operations< 1u, Signed >
|
||||
{
|
||||
};
|
||||
|
||||
#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_
|
1232
boost/atomic/detail/ops_gcc_ppc.hpp
Normal file
1232
boost/atomic/detail/ops_gcc_ppc.hpp
Normal file
File diff suppressed because it is too large
Load Diff
70
boost/atomic/detail/ops_gcc_ppc_common.hpp
Normal file
70
boost/atomic/detail/ops_gcc_ppc_common.hpp
Normal 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) 2009 Helge Bahmann
|
||||
* Copyright (c) 2013 Tim Blechmann
|
||||
* Copyright (c) 2014 Andrey Semashev
|
||||
*/
|
||||
/*!
|
||||
* \file atomic/detail/ops_gcc_ppc_common.hpp
|
||||
*
|
||||
* This header contains basic utilities for gcc PowerPC backend.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ATOMIC_DETAIL_OPS_GCC_PPC_COMMON_HPP_INCLUDED_
|
||||
#define BOOST_ATOMIC_DETAIL_OPS_GCC_PPC_COMMON_HPP_INCLUDED_
|
||||
|
||||
#include <boost/memory_order.hpp>
|
||||
#include <boost/atomic/detail/config.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
|
||||
|
||||
// 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_CONSTEXPR_OR_CONST bool full_cas_based = false;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
|
||||
|
||||
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 ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u)
|
||||
__asm__ __volatile__ ("lwsync" ::: "memory");
|
||||
#else
|
||||
if ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u)
|
||||
__asm__ __volatile__ ("sync" ::: "memory");
|
||||
#endif
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE void fence_after(memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u)
|
||||
__asm__ __volatile__ ("isync" ::: "memory");
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace atomics
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_OPS_GCC_PPC_COMMON_HPP_INCLUDED_
|
240
boost/atomic/detail/ops_gcc_sparc.hpp
Normal file
240
boost/atomic/detail/ops_gcc_sparc.hpp
Normal 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 <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/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_CONSTEXPR_OR_CONST bool full_cas_based = true;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
|
||||
|
||||
static BOOST_FORCEINLINE void fence_before(memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
if (order == memory_order_seq_cst)
|
||||
__asm__ __volatile__ ("membar #Sync" ::: "memory");
|
||||
else if ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u)
|
||||
__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 ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u)
|
||||
__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 >::type storage_type;
|
||||
typedef typename make_storage_type< 4u >::aligned aligned_storage_type;
|
||||
|
||||
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 4u;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
|
||||
|
||||
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 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
|
||||
{
|
||||
fence_before(order);
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"swap [%1], %0"
|
||||
: "+r" (v)
|
||||
: "r" (&storage)
|
||||
: "memory"
|
||||
);
|
||||
fence_after(order);
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
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 >::type storage_type;
|
||||
typedef typename make_storage_type< 8u >::aligned aligned_storage_type;
|
||||
|
||||
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 8u;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
|
||||
|
||||
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 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);
|
||||
}
|
||||
};
|
||||
|
||||
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_
|
240
boost/atomic/detail/ops_gcc_sync.hpp
Normal file
240
boost/atomic/detail/ops_gcc_sync.hpp
Normal 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) 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 <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/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_CONSTEXPR_OR_CONST bool full_cas_based = false;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
|
||||
|
||||
static BOOST_FORCEINLINE void fence_before_store(memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
if ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u)
|
||||
__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 ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_acquire) | static_cast< unsigned int >(memory_order_consume))) != 0u)
|
||||
__sync_synchronize();
|
||||
}
|
||||
};
|
||||
|
||||
template< std::size_t Size, bool Signed >
|
||||
struct gcc_sync_operations :
|
||||
public gcc_sync_operations_base
|
||||
{
|
||||
typedef typename make_storage_type< Size >::type storage_type;
|
||||
typedef typename make_storage_type< Size >::aligned aligned_storage_type;
|
||||
|
||||
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = Size;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
|
||||
|
||||
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 ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u)
|
||||
__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 ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u)
|
||||
__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();
|
||||
}
|
||||
};
|
||||
|
||||
#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< 1u, Signed >
|
||||
#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2)
|
||||
public extending_cas_based_operations< gcc_sync_operations< 2u, Signed >, 1u, Signed >
|
||||
#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
|
||||
public extending_cas_based_operations< gcc_sync_operations< 4u, Signed >, 1u, Signed >
|
||||
#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
|
||||
public extending_cas_based_operations< gcc_sync_operations< 8u, Signed >, 1u, Signed >
|
||||
#else
|
||||
public extending_cas_based_operations< gcc_sync_operations< 16u, Signed >, 1u, Signed >
|
||||
#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< 2u, Signed >
|
||||
#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
|
||||
public extending_cas_based_operations< gcc_sync_operations< 4u, Signed >, 2u, Signed >
|
||||
#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
|
||||
public extending_cas_based_operations< gcc_sync_operations< 8u, Signed >, 2u, Signed >
|
||||
#else
|
||||
public extending_cas_based_operations< gcc_sync_operations< 16u, Signed >, 2u, Signed >
|
||||
#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< 4u, Signed >
|
||||
#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
|
||||
public extending_cas_based_operations< gcc_sync_operations< 8u, Signed >, 4u, Signed >
|
||||
#else
|
||||
public extending_cas_based_operations< gcc_sync_operations< 16u, Signed >, 4u, Signed >
|
||||
#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< 8u, Signed >
|
||||
#else
|
||||
public extending_cas_based_operations< gcc_sync_operations< 16u, Signed >, 8u, Signed >
|
||||
#endif
|
||||
{
|
||||
};
|
||||
#endif
|
||||
|
||||
#if BOOST_ATOMIC_INT128_LOCK_FREE > 0
|
||||
template< bool Signed >
|
||||
struct operations< 16u, Signed > :
|
||||
public gcc_sync_operations< 16u, Signed >
|
||||
{
|
||||
};
|
||||
#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_
|
563
boost/atomic/detail/ops_gcc_x86.hpp
Normal file
563
boost/atomic/detail/ops_gcc_x86.hpp
Normal file
@ -0,0 +1,563 @@
|
||||
/*
|
||||
* 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 <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/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
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
struct gcc_x86_operations_base
|
||||
{
|
||||
static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = false;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
|
||||
|
||||
static BOOST_FORCEINLINE void fence_before(memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
if ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u)
|
||||
__asm__ __volatile__ ("" ::: "memory");
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE void fence_after(memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u)
|
||||
__asm__ __volatile__ ("" ::: "memory");
|
||||
}
|
||||
};
|
||||
|
||||
template< std::size_t Size, bool Signed, typename Derived >
|
||||
struct gcc_x86_operations :
|
||||
public gcc_x86_operations_base
|
||||
{
|
||||
typedef typename make_storage_type< Size >::type 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);
|
||||
}
|
||||
};
|
||||
|
||||
template< bool Signed >
|
||||
struct operations< 1u, Signed > :
|
||||
public gcc_x86_operations< 1u, Signed, operations< 1u, Signed > >
|
||||
{
|
||||
typedef gcc_x86_operations< 1u, Signed, operations< 1u, Signed > > base_type;
|
||||
typedef typename base_type::storage_type storage_type;
|
||||
typedef typename make_storage_type< 1u >::aligned aligned_storage_type;
|
||||
typedef typename make_storage_type< 4u >::type temp_storage_type;
|
||||
|
||||
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 1u;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
|
||||
|
||||
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;
|
||||
#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"lock; cmpxchgb %3, %1"
|
||||
: "+a" (previous), "+m" (storage), "=@ccz" (success)
|
||||
: "q" (desired)
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
|
||||
);
|
||||
#else // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
|
||||
__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"
|
||||
);
|
||||
#endif // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
|
||||
expected = previous;
|
||||
return success;
|
||||
}
|
||||
|
||||
#define BOOST_ATOMIC_DETAIL_CAS_LOOP(op, argument, result)\
|
||||
temp_storage_type new_val;\
|
||||
__asm__ __volatile__\
|
||||
(\
|
||||
".align 16\n\t"\
|
||||
"1: mov %[arg], %2\n\t"\
|
||||
op " %%al, %b2\n\t"\
|
||||
"lock; cmpxchgb %b2, %[storage]\n\t"\
|
||||
"jne 1b"\
|
||||
: [res] "+a" (result), [storage] "+m" (storage), "=&q" (new_val)\
|
||||
: [arg] "ir" ((temp_storage_type)argument)\
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "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< 2u, Signed, operations< 2u, Signed > >
|
||||
{
|
||||
typedef gcc_x86_operations< 2u, Signed, operations< 2u, Signed > > base_type;
|
||||
typedef typename base_type::storage_type storage_type;
|
||||
typedef typename make_storage_type< 2u >::aligned aligned_storage_type;
|
||||
typedef typename make_storage_type< 4u >::type temp_storage_type;
|
||||
|
||||
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 2u;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
|
||||
|
||||
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;
|
||||
#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"lock; cmpxchgw %3, %1"
|
||||
: "+a" (previous), "+m" (storage), "=@ccz" (success)
|
||||
: "q" (desired)
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
|
||||
);
|
||||
#else // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
|
||||
__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"
|
||||
);
|
||||
#endif // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
|
||||
expected = previous;
|
||||
return success;
|
||||
}
|
||||
|
||||
#define BOOST_ATOMIC_DETAIL_CAS_LOOP(op, argument, result)\
|
||||
temp_storage_type new_val;\
|
||||
__asm__ __volatile__\
|
||||
(\
|
||||
".align 16\n\t"\
|
||||
"1: mov %[arg], %2\n\t"\
|
||||
op " %%ax, %w2\n\t"\
|
||||
"lock; cmpxchgw %w2, %[storage]\n\t"\
|
||||
"jne 1b"\
|
||||
: [res] "+a" (result), [storage] "+m" (storage), "=&q" (new_val)\
|
||||
: [arg] "ir" ((temp_storage_type)argument)\
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "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< 4u, Signed, operations< 4u, Signed > >
|
||||
{
|
||||
typedef gcc_x86_operations< 4u, Signed, operations< 4u, Signed > > base_type;
|
||||
typedef typename base_type::storage_type storage_type;
|
||||
typedef typename make_storage_type< 4u >::aligned aligned_storage_type;
|
||||
|
||||
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 4u;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
|
||||
|
||||
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;
|
||||
#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"lock; cmpxchgl %3, %1"
|
||||
: "+a" (previous), "+m" (storage), "=@ccz" (success)
|
||||
: "r" (desired)
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
|
||||
);
|
||||
#else // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
|
||||
__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"
|
||||
);
|
||||
#endif // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
|
||||
expected = previous;
|
||||
return success;
|
||||
}
|
||||
|
||||
#define BOOST_ATOMIC_DETAIL_CAS_LOOP(op, argument, result)\
|
||||
storage_type new_val;\
|
||||
__asm__ __volatile__\
|
||||
(\
|
||||
".align 16\n\t"\
|
||||
"1: mov %[arg], %[new_val]\n\t"\
|
||||
op " %%eax, %[new_val]\n\t"\
|
||||
"lock; cmpxchgl %[new_val], %[storage]\n\t"\
|
||||
"jne 1b"\
|
||||
: [res] "+a" (result), [storage] "+m" (storage), [new_val] "=&r" (new_val)\
|
||||
: [arg] "ir" (argument)\
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "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 > >
|
||||
{
|
||||
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 8u;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
|
||||
};
|
||||
|
||||
#elif defined(__x86_64__)
|
||||
|
||||
template< bool Signed >
|
||||
struct operations< 8u, Signed > :
|
||||
public gcc_x86_operations< 8u, Signed, operations< 8u, Signed > >
|
||||
{
|
||||
typedef gcc_x86_operations< 8u, Signed, operations< 8u, Signed > > base_type;
|
||||
typedef typename base_type::storage_type storage_type;
|
||||
typedef typename make_storage_type< 8u >::aligned aligned_storage_type;
|
||||
|
||||
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 8u;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
|
||||
|
||||
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;
|
||||
#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"lock; cmpxchgq %3, %1"
|
||||
: "+a" (previous), "+m" (storage), "=@ccz" (success)
|
||||
: "r" (desired)
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
|
||||
);
|
||||
#else // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
|
||||
__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"
|
||||
);
|
||||
#endif // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
|
||||
expected = previous;
|
||||
return success;
|
||||
}
|
||||
|
||||
#define BOOST_ATOMIC_DETAIL_CAS_LOOP(op, argument, result)\
|
||||
storage_type new_val;\
|
||||
__asm__ __volatile__\
|
||||
(\
|
||||
".align 16\n\t"\
|
||||
"1: movq %[arg], %[new_val]\n\t"\
|
||||
op " %%rax, %[new_val]\n\t"\
|
||||
"lock; cmpxchgq %[new_val], %[storage]\n\t"\
|
||||
"jne 1b"\
|
||||
: [res] "+a" (result), [storage] "+m" (storage), [new_val] "=&r" (new_val)\
|
||||
: [arg] "r" (argument)\
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "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 > >
|
||||
{
|
||||
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 16u;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_signed = 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(BOOST_ATOMIC_DETAIL_X86_HAS_MFENCE)
|
||||
"mfence\n"
|
||||
#else
|
||||
"lock; addl $0, (%%esp)\n"
|
||||
#endif
|
||||
::: "memory"
|
||||
);
|
||||
}
|
||||
else if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_acquire) | static_cast< unsigned int >(memory_order_release))) != 0u)
|
||||
{
|
||||
__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
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_OPS_GCC_X86_HPP_INCLUDED_
|
555
boost/atomic/detail/ops_gcc_x86_dcas.hpp
Normal file
555
boost/atomic/detail/ops_gcc_x86_dcas.hpp
Normal file
@ -0,0 +1,555 @@
|
||||
/*
|
||||
* 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 - 2018 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/detail/string_ops.hpp>
|
||||
#include <boost/atomic/capabilities.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
// Note: In the 32-bit PIC code guarded with BOOST_ATOMIC_DETAIL_X86_ASM_PRESERVE_EBX below we have to avoid using memory
|
||||
// operand constraints because the compiler may choose to use ebx as the base register for that operand. At least, clang
|
||||
// is known to do that. For this reason we have to pre-compute a pointer to storage and pass it in edi. For the same reason
|
||||
// we cannot save ebx to the stack with a mov instruction, so we use esi as a scratch register and restore it afterwards.
|
||||
// Alternatively, we could push/pop the register to the stack, but exchanging the registers is faster.
|
||||
// The need to pass a pointer in edi is a bit wasteful because normally the memory operand would use a base pointer
|
||||
// with an offset (e.g. `this` + offset). But unfortunately, there seems to be no way around it.
|
||||
|
||||
#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B)
|
||||
|
||||
template< bool Signed >
|
||||
struct gcc_dcas_x86
|
||||
{
|
||||
typedef typename make_storage_type< 8u >::type storage_type;
|
||||
typedef typename make_storage_type< 8u >::aligned aligned_storage_type;
|
||||
typedef uint32_t BOOST_ATOMIC_DETAIL_MAY_ALIAS aliasing_uint32_t;
|
||||
|
||||
static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = true;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
|
||||
|
||||
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
|
||||
{
|
||||
if (BOOST_LIKELY((((uint32_t)&storage) & 0x00000007) == 0u))
|
||||
{
|
||||
#if defined(__SSE__)
|
||||
typedef float xmm_t __attribute__((__vector_size__(16)));
|
||||
xmm_t xmm_scratch;
|
||||
__asm__ __volatile__
|
||||
(
|
||||
#if defined(__AVX__)
|
||||
"vmovq %[value], %[xmm_scratch]\n\t"
|
||||
"vmovq %[xmm_scratch], %[storage]\n\t"
|
||||
#elif defined(__SSE2__)
|
||||
"movq %[value], %[xmm_scratch]\n\t"
|
||||
"movq %[xmm_scratch], %[storage]\n\t"
|
||||
#else
|
||||
"xorps %[xmm_scratch], %[xmm_scratch]\n\t"
|
||||
"movlps %[value], %[xmm_scratch]\n\t"
|
||||
"movlps %[xmm_scratch], %[storage]\n\t"
|
||||
#endif
|
||||
: [storage] "=m" (storage), [xmm_scratch] "=x" (xmm_scratch)
|
||||
: [value] "m" (v)
|
||||
: "memory"
|
||||
);
|
||||
#else
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"fildll %[value]\n\t"
|
||||
"fistpll %[storage]\n\t"
|
||||
: [storage] "=m" (storage)
|
||||
: [value] "m" (v)
|
||||
: "memory"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(BOOST_ATOMIC_DETAIL_X86_ASM_PRESERVE_EBX)
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"xchgl %%ebx, %%esi\n\t"
|
||||
"movl %%eax, %%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"
|
||||
"xchgl %%ebx, %%esi\n\t"
|
||||
:
|
||||
: "a" ((uint32_t)v), "c" ((uint32_t)(v >> 32)), [dest] "D" (&storage)
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "edx", "memory"
|
||||
);
|
||||
#else // defined(BOOST_ATOMIC_DETAIL_X86_ASM_PRESERVE_EBX)
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"movl %[dest_lo], %%eax\n\t"
|
||||
"movl %[dest_hi], %%edx\n\t"
|
||||
".align 16\n\t"
|
||||
"1: lock; cmpxchg8b %[dest_lo]\n\t"
|
||||
"jne 1b\n\t"
|
||||
: [dest_lo] "=m" (storage), [dest_hi] "=m" (reinterpret_cast< volatile aliasing_uint32_t* >(&storage)[1])
|
||||
: [value_lo] "b" ((uint32_t)v), "c" ((uint32_t)(v >> 32))
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "eax", "edx", "memory"
|
||||
);
|
||||
#endif // defined(BOOST_ATOMIC_DETAIL_X86_ASM_PRESERVE_EBX)
|
||||
}
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type value;
|
||||
|
||||
if (BOOST_LIKELY((((uint32_t)&storage) & 0x00000007) == 0u))
|
||||
{
|
||||
#if defined(__SSE__)
|
||||
typedef float xmm_t __attribute__((__vector_size__(16)));
|
||||
xmm_t xmm_scratch;
|
||||
__asm__ __volatile__
|
||||
(
|
||||
#if defined(__AVX__)
|
||||
"vmovq %[storage], %[xmm_scratch]\n\t"
|
||||
"vmovq %[xmm_scratch], %[value]\n\t"
|
||||
#elif defined(__SSE2__)
|
||||
"movq %[storage], %[xmm_scratch]\n\t"
|
||||
"movq %[xmm_scratch], %[value]\n\t"
|
||||
#else
|
||||
"xorps %[xmm_scratch], %[xmm_scratch]\n\t"
|
||||
"movlps %[storage], %[xmm_scratch]\n\t"
|
||||
"movlps %[xmm_scratch], %[value]\n\t"
|
||||
#endif
|
||||
: [value] "=m" (value), [xmm_scratch] "=x" (xmm_scratch)
|
||||
: [storage] "m" (storage)
|
||||
: "memory"
|
||||
);
|
||||
#else
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"fildll %[storage]\n\t"
|
||||
"fistpll %[value]\n\t"
|
||||
: [value] "=m" (value)
|
||||
: [storage] "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);
|
||||
#elif defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS)
|
||||
uint32_t value_bits[2];
|
||||
// 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_bits[0]), "=&d" (value_bits[1])
|
||||
: [storage] "m" (storage)
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
|
||||
);
|
||||
BOOST_ATOMIC_DETAIL_MEMCPY(&value, value_bits, sizeof(value));
|
||||
#else // defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS)
|
||||
// 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 // defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS)
|
||||
}
|
||||
|
||||
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(BOOST_ATOMIC_DETAIL_X86_ASM_PRESERVE_EBX)
|
||||
|
||||
bool success;
|
||||
|
||||
#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"xchgl %%ebx, %%esi\n\t"
|
||||
"lock; cmpxchg8b (%[dest])\n\t"
|
||||
"xchgl %%ebx, %%esi\n\t"
|
||||
: "+A" (expected), [success] "=@ccz" (success)
|
||||
: "S" ((uint32_t)desired), "c" ((uint32_t)(desired >> 32)), [dest] "D" (&storage)
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
|
||||
);
|
||||
#else // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"xchgl %%ebx, %%esi\n\t"
|
||||
"lock; cmpxchg8b (%[dest])\n\t"
|
||||
"xchgl %%ebx, %%esi\n\t"
|
||||
"sete %[success]\n\t"
|
||||
: "+A" (expected), [success] "=qm" (success)
|
||||
: "S" ((uint32_t)desired), "c" ((uint32_t)(desired >> 32)), [dest] "D" (&storage)
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
|
||||
);
|
||||
#endif // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
|
||||
|
||||
return success;
|
||||
|
||||
#else // defined(BOOST_ATOMIC_DETAIL_X86_ASM_PRESERVE_EBX)
|
||||
|
||||
bool success;
|
||||
|
||||
#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"lock; cmpxchg8b %[dest]\n\t"
|
||||
: "+A" (expected), [dest] "+m" (storage), [success] "=@ccz" (success)
|
||||
: "b" ((uint32_t)desired), "c" ((uint32_t)(desired >> 32))
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
|
||||
);
|
||||
#else // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"lock; cmpxchg8b %[dest]\n\t"
|
||||
"sete %[success]\n\t"
|
||||
: "+A" (expected), [dest] "+m" (storage), [success] "=qm" (success)
|
||||
: "b" ((uint32_t)desired), "c" ((uint32_t)(desired >> 32))
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
|
||||
);
|
||||
#endif // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
|
||||
|
||||
return success;
|
||||
|
||||
#endif // defined(BOOST_ATOMIC_DETAIL_X86_ASM_PRESERVE_EBX)
|
||||
}
|
||||
|
||||
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(BOOST_ATOMIC_DETAIL_X86_ASM_PRESERVE_EBX)
|
||||
#if defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS)
|
||||
|
||||
uint32_t old_bits[2];
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"xchgl %%ebx, %%esi\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"
|
||||
"xchgl %%ebx, %%esi\n\t"
|
||||
: "=a" (old_bits[0]), "=d" (old_bits[1])
|
||||
: "S" ((uint32_t)v), "c" ((uint32_t)(v >> 32)), [dest] "D" (&storage)
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
|
||||
);
|
||||
|
||||
storage_type old_value;
|
||||
BOOST_ATOMIC_DETAIL_MEMCPY(&old_value, old_bits, sizeof(old_value));
|
||||
return old_value;
|
||||
|
||||
#else // defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS)
|
||||
|
||||
storage_type old_value;
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"xchgl %%ebx, %%esi\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"
|
||||
"xchgl %%ebx, %%esi\n\t"
|
||||
: "=A" (old_value)
|
||||
: "S" ((uint32_t)v), "c" ((uint32_t)(v >> 32)), [dest] "D" (&storage)
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
|
||||
);
|
||||
return old_value;
|
||||
|
||||
#endif // defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS)
|
||||
#else // defined(BOOST_ATOMIC_DETAIL_X86_ASM_PRESERVE_EBX)
|
||||
#if defined(__MINGW32__) && ((__GNUC__+0) * 100 + (__GNUC_MINOR__+0)) < 407
|
||||
|
||||
// MinGW gcc up to 4.6 has problems with allocating registers in the asm blocks below
|
||||
uint32_t old_bits[2];
|
||||
__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" (old_bits[0]), "=&d" (old_bits[1])
|
||||
: "b" ((uint32_t)v), "c" ((uint32_t)(v >> 32)), [dest] "DS" (&storage)
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
|
||||
);
|
||||
|
||||
storage_type old_value;
|
||||
BOOST_ATOMIC_DETAIL_MEMCPY(&old_value, old_bits, sizeof(old_value));
|
||||
return old_value;
|
||||
|
||||
#elif defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS)
|
||||
|
||||
uint32_t old_bits[2];
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"movl %[dest_lo], %%eax\n\t"
|
||||
"movl %[dest_hi], %%edx\n\t"
|
||||
".align 16\n\t"
|
||||
"1: lock; cmpxchg8b %[dest_lo]\n\t"
|
||||
"jne 1b\n\t"
|
||||
: "=&a" (old_bits[0]), "=&d" (old_bits[1]), [dest_lo] "+m" (storage), [dest_hi] "+m" (reinterpret_cast< volatile aliasing_uint32_t* >(&storage)[1])
|
||||
: "b" ((uint32_t)v), "c" ((uint32_t)(v >> 32))
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
|
||||
);
|
||||
|
||||
storage_type old_value;
|
||||
BOOST_ATOMIC_DETAIL_MEMCPY(&old_value, old_bits, sizeof(old_value));
|
||||
return old_value;
|
||||
|
||||
#else // defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS)
|
||||
|
||||
storage_type old_value;
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"movl %[dest_lo], %%eax\n\t"
|
||||
"movl %[dest_hi], %%edx\n\t"
|
||||
".align 16\n\t"
|
||||
"1: lock; cmpxchg8b %[dest_lo]\n\t"
|
||||
"jne 1b\n\t"
|
||||
: "=&A" (old_value), [dest_lo] "+m" (storage), [dest_hi] "+m" (reinterpret_cast< volatile aliasing_uint32_t* >(&storage)[1])
|
||||
: "b" ((uint32_t)v), "c" ((uint32_t)(v >> 32))
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
|
||||
);
|
||||
return old_value;
|
||||
|
||||
#endif // defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS)
|
||||
#endif // defined(BOOST_ATOMIC_DETAIL_X86_ASM_PRESERVE_EBX)
|
||||
}
|
||||
};
|
||||
|
||||
#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 >::type storage_type;
|
||||
typedef typename make_storage_type< 16u >::aligned aligned_storage_type;
|
||||
typedef uint64_t BOOST_ATOMIC_DETAIL_MAY_ALIAS aliasing_uint64_t;
|
||||
|
||||
static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = true;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
|
||||
|
||||
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
|
||||
{
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"movq %[dest_lo], %%rax\n\t"
|
||||
"movq %[dest_hi], %%rdx\n\t"
|
||||
".align 16\n\t"
|
||||
"1: lock; cmpxchg16b %[dest_lo]\n\t"
|
||||
"jne 1b\n\t"
|
||||
: [dest_lo] "=m" (storage), [dest_hi] "=m" (reinterpret_cast< volatile aliasing_uint64_t* >(&storage)[1])
|
||||
: "b" (reinterpret_cast< const aliasing_uint64_t* >(&v)[0]), "c" (reinterpret_cast< const aliasing_uint64_t* >(&v)[1])
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "rax", "rdx", "memory"
|
||||
);
|
||||
}
|
||||
|
||||
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_X86_NO_ASM_AX_DX_PAIRS)
|
||||
|
||||
// Some compilers can't allocate rax:rdx register pair either and also don't support 128-bit __sync_val_compare_and_swap
|
||||
uint64_t value_bits[2];
|
||||
|
||||
// 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_bits[0]), "=&d" (value_bits[1])
|
||||
: [storage] "m" (storage)
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
|
||||
);
|
||||
|
||||
storage_type value;
|
||||
BOOST_ATOMIC_DETAIL_MEMCPY(&value, value_bits, sizeof(value));
|
||||
return value;
|
||||
|
||||
#else // defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_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 // defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS)
|
||||
}
|
||||
|
||||
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_X86_NO_ASM_AX_DX_PAIRS)
|
||||
|
||||
// Some compilers can't allocate rax:rdx register pair either but also don't support 128-bit __sync_val_compare_and_swap
|
||||
bool success;
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"lock; cmpxchg16b %[dest]\n\t"
|
||||
"sete %[success]\n\t"
|
||||
: [dest] "+m" (storage), "+a" (reinterpret_cast< aliasing_uint64_t* >(&expected)[0]), "+d" (reinterpret_cast< aliasing_uint64_t* >(&expected)[1]), [success] "=q" (success)
|
||||
: "b" (reinterpret_cast< const aliasing_uint64_t* >(&desired)[0]), "c" (reinterpret_cast< const aliasing_uint64_t* >(&desired)[1])
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
|
||||
);
|
||||
|
||||
return success;
|
||||
|
||||
#else // defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS)
|
||||
|
||||
bool success;
|
||||
|
||||
#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"lock; cmpxchg16b %[dest]\n\t"
|
||||
: "+A" (expected), [dest] "+m" (storage), "=@ccz" (success)
|
||||
: "b" (reinterpret_cast< const aliasing_uint64_t* >(&desired)[0]), "c" (reinterpret_cast< const aliasing_uint64_t* >(&desired)[1])
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
|
||||
);
|
||||
#else // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"lock; cmpxchg16b %[dest]\n\t"
|
||||
"sete %[success]\n\t"
|
||||
: "+A" (expected), [dest] "+m" (storage), [success] "=qm" (success)
|
||||
: "b" (reinterpret_cast< const aliasing_uint64_t* >(&desired)[0]), "c" (reinterpret_cast< const aliasing_uint64_t* >(&desired)[1])
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
|
||||
);
|
||||
#endif // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
|
||||
|
||||
return success;
|
||||
|
||||
#endif // defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS)
|
||||
}
|
||||
|
||||
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(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS)
|
||||
uint64_t old_bits[2];
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"movq %[dest_lo], %%rax\n\t"
|
||||
"movq %[dest_hi], %%rdx\n\t"
|
||||
".align 16\n\t"
|
||||
"1: lock; cmpxchg16b %[dest_lo]\n\t"
|
||||
"jne 1b\n\t"
|
||||
: [dest_lo] "+m" (storage), [dest_hi] "+m" (reinterpret_cast< volatile aliasing_uint64_t* >(&storage)[1]), "=&a" (old_bits[0]), "=&d" (old_bits[1])
|
||||
: "b" (reinterpret_cast< const aliasing_uint64_t* >(&v)[0]), "c" (reinterpret_cast< const aliasing_uint64_t* >(&v)[1])
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
|
||||
);
|
||||
|
||||
storage_type old_value;
|
||||
BOOST_ATOMIC_DETAIL_MEMCPY(&old_value, old_bits, sizeof(old_value));
|
||||
return old_value;
|
||||
#else // defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS)
|
||||
storage_type old_value;
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"movq %[dest_lo], %%rax\n\t"
|
||||
"movq %[dest_hi], %%rdx\n\t"
|
||||
".align 16\n\t"
|
||||
"1: lock; cmpxchg16b %[dest_lo]\n\t"
|
||||
"jne 1b\n\t"
|
||||
: "=&A" (old_value), [dest_lo] "+m" (storage), [dest_hi] "+m" (reinterpret_cast< volatile aliasing_uint64_t* >(&storage)[1])
|
||||
: "b" (reinterpret_cast< const aliasing_uint64_t* >(&v)[0]), "c" (reinterpret_cast< const aliasing_uint64_t* >(&v)[1])
|
||||
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
|
||||
);
|
||||
|
||||
return old_value;
|
||||
#endif // defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS)
|
||||
}
|
||||
};
|
||||
|
||||
#endif // defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B)
|
||||
|
||||
} // namespace detail
|
||||
} // namespace atomics
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_OPS_GCC_X86_DCAS_HPP_INCLUDED_
|
180
boost/atomic/detail/ops_linux_arm.hpp
Normal file
180
boost/atomic/detail/ops_linux_arm.hpp
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* 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 <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/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_CONSTEXPR_OR_CONST bool full_cas_based = true;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
|
||||
|
||||
static BOOST_FORCEINLINE void fence_before_store(memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
if ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u)
|
||||
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 ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u)
|
||||
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 >::type storage_type;
|
||||
typedef typename make_storage_type< 4u >::aligned aligned_storage_type;
|
||||
|
||||
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 4u;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
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_
|
824
boost/atomic/detail/ops_msvc_arm.hpp
Normal file
824
boost/atomic/detail/ops_msvc_arm.hpp
Normal 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 <cstddef>
|
||||
#include <boost/memory_order.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/detail/type_traits/make_signed.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_CONSTEXPR_OR_CONST bool full_cas_based = false;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
|
||||
|
||||
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 ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u)
|
||||
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 ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u)
|
||||
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 >(((static_cast< unsigned int >(failure_order) | static_cast< unsigned int >(success_order)) & ~static_cast< unsigned int >(memory_order_consume))
|
||||
| (((static_cast< unsigned int >(failure_order) | static_cast< unsigned int >(success_order)) & static_cast< unsigned int >(memory_order_consume)) << 1u));
|
||||
}
|
||||
};
|
||||
|
||||
template< std::size_t Size, bool Signed, typename Derived >
|
||||
struct msvc_arm_operations :
|
||||
public msvc_arm_operations_base
|
||||
{
|
||||
typedef typename make_storage_type< Size >::type storage_type;
|
||||
typedef typename make_storage_type< Size >::aligned aligned_storage_type;
|
||||
|
||||
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = Size;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
|
||||
|
||||
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
typedef typename boost::atomics::detail::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);
|
||||
}
|
||||
};
|
||||
|
||||
template< bool Signed >
|
||||
struct operations< 1u, Signed > :
|
||||
public msvc_arm_operations< 1u, Signed, operations< 1u, Signed > >
|
||||
{
|
||||
typedef msvc_arm_operations< 1u, Signed, operations< 1u, Signed > > base_type;
|
||||
typedef typename base_type::storage_type 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< 2u, Signed, operations< 2u, Signed > >
|
||||
{
|
||||
typedef msvc_arm_operations< 2u, Signed, operations< 2u, Signed > > base_type;
|
||||
typedef typename base_type::storage_type 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< 4u, Signed, operations< 4u, Signed > >
|
||||
{
|
||||
typedef msvc_arm_operations< 4u, Signed, operations< 4u, Signed > > base_type;
|
||||
typedef typename base_type::storage_type 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< 8u, Signed, operations< 8u, Signed > >
|
||||
{
|
||||
typedef msvc_arm_operations< 8u, Signed, operations< 8u, Signed > > base_type;
|
||||
typedef typename base_type::storage_type 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_
|
38
boost/atomic/detail/ops_msvc_common.hpp
Normal file
38
boost/atomic/detail/ops_msvc_common.hpp
Normal 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_
|
908
boost/atomic/detail/ops_msvc_x86.hpp
Normal file
908
boost/atomic/detail/ops_msvc_x86.hpp
Normal file
@ -0,0 +1,908 @@
|
||||
/*
|
||||
* 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 <cstddef>
|
||||
#include <boost/memory_order.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/detail/type_traits/make_signed.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(BOOST_ATOMIC_DETAIL_X86_HAS_MFENCE)
|
||||
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_CONSTEXPR_OR_CONST bool full_cas_based = false;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
|
||||
|
||||
static BOOST_FORCEINLINE void hardware_full_fence() BOOST_NOEXCEPT
|
||||
{
|
||||
#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_MFENCE)
|
||||
_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< std::size_t Size, bool Signed, typename Derived >
|
||||
struct msvc_x86_operations :
|
||||
public msvc_x86_operations_base
|
||||
{
|
||||
typedef typename make_storage_type< Size >::type storage_type;
|
||||
typedef typename make_storage_type< Size >::aligned aligned_storage_type;
|
||||
|
||||
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = Size;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
|
||||
|
||||
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 boost::atomics::detail::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);
|
||||
}
|
||||
};
|
||||
|
||||
template< bool Signed >
|
||||
struct operations< 4u, Signed > :
|
||||
public msvc_x86_operations< 4u, Signed, operations< 4u, Signed > >
|
||||
{
|
||||
typedef msvc_x86_operations< 4u, Signed, operations< 4u, Signed > > base_type;
|
||||
typedef typename base_type::storage_type 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< 1u, Signed, operations< 1u, Signed > >
|
||||
{
|
||||
typedef msvc_x86_operations< 1u, Signed, operations< 1u, Signed > > base_type;
|
||||
typedef typename base_type::storage_type 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< 1u, Signed, operations< 1u, Signed > >
|
||||
{
|
||||
typedef msvc_x86_operations< 1u, Signed, operations< 1u, Signed > > base_type;
|
||||
typedef typename 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
|
||||
{
|
||||
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);
|
||||
__asm
|
||||
{
|
||||
mov edi, storage
|
||||
movzx ecx, v
|
||||
xor edx, edx
|
||||
movzx eax, byte ptr [edi]
|
||||
align 16
|
||||
again:
|
||||
mov dl, al
|
||||
and dl, cl
|
||||
lock cmpxchg byte ptr [edi], dl
|
||||
jne again
|
||||
mov v, al
|
||||
};
|
||||
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);
|
||||
__asm
|
||||
{
|
||||
mov edi, storage
|
||||
movzx ecx, v
|
||||
xor edx, edx
|
||||
movzx eax, byte ptr [edi]
|
||||
align 16
|
||||
again:
|
||||
mov dl, al
|
||||
or dl, cl
|
||||
lock cmpxchg byte ptr [edi], dl
|
||||
jne again
|
||||
mov v, al
|
||||
};
|
||||
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);
|
||||
__asm
|
||||
{
|
||||
mov edi, storage
|
||||
movzx ecx, v
|
||||
xor edx, edx
|
||||
movzx eax, byte ptr [edi]
|
||||
align 16
|
||||
again:
|
||||
mov dl, al
|
||||
xor dl, cl
|
||||
lock cmpxchg byte ptr [edi], dl
|
||||
jne again
|
||||
mov v, al
|
||||
};
|
||||
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< 2u, Signed, operations< 2u, Signed > >
|
||||
{
|
||||
typedef msvc_x86_operations< 2u, Signed, operations< 2u, Signed > > base_type;
|
||||
typedef typename base_type::storage_type 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< 2u, Signed, operations< 2u, Signed > >
|
||||
{
|
||||
typedef msvc_x86_operations< 2u, Signed, operations< 2u, Signed > > base_type;
|
||||
typedef typename 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
|
||||
{
|
||||
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);
|
||||
__asm
|
||||
{
|
||||
mov edi, storage
|
||||
movzx ecx, v
|
||||
xor edx, edx
|
||||
movzx eax, word ptr [edi]
|
||||
align 16
|
||||
again:
|
||||
mov dx, ax
|
||||
and dx, cx
|
||||
lock cmpxchg word ptr [edi], dx
|
||||
jne again
|
||||
mov v, ax
|
||||
};
|
||||
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);
|
||||
__asm
|
||||
{
|
||||
mov edi, storage
|
||||
movzx ecx, v
|
||||
xor edx, edx
|
||||
movzx eax, word ptr [edi]
|
||||
align 16
|
||||
again:
|
||||
mov dx, ax
|
||||
or dx, cx
|
||||
lock cmpxchg word ptr [edi], dx
|
||||
jne again
|
||||
mov v, ax
|
||||
};
|
||||
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);
|
||||
__asm
|
||||
{
|
||||
mov edi, storage
|
||||
movzx ecx, v
|
||||
xor edx, edx
|
||||
movzx eax, word ptr [edi]
|
||||
align 16
|
||||
again:
|
||||
mov dx, ax
|
||||
xor dx, cx
|
||||
lock cmpxchg word ptr [edi], dx
|
||||
jne again
|
||||
mov v, ax
|
||||
};
|
||||
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 >::type storage_type;
|
||||
typedef typename make_storage_type< 8u >::aligned aligned_storage_type;
|
||||
|
||||
static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = true;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
|
||||
|
||||
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 8u;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
|
||||
|
||||
// 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
|
||||
{
|
||||
uint32_t 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;
|
||||
uint32_t 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) BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
|
||||
|
||||
storage_type volatile* p = &storage;
|
||||
uint32_t 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;
|
||||
}
|
||||
};
|
||||
|
||||
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< 8u, Signed, operations< 8u, Signed > >
|
||||
{
|
||||
typedef msvc_x86_operations< 8u, Signed, operations< 8u, Signed > > base_type;
|
||||
typedef typename base_type::storage_type 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 >::type storage_type;
|
||||
typedef typename make_storage_type< 16u >::aligned aligned_storage_type;
|
||||
|
||||
static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = true;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
|
||||
|
||||
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 16u;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
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_
|
218
boost/atomic/detail/ops_windows.hpp
Normal file
218
boost/atomic/detail/ops_windows.hpp
Normal file
@ -0,0 +1,218 @@
|
||||
/*
|
||||
* 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_windows.hpp
|
||||
*
|
||||
* This header contains implementation of the \c operations template.
|
||||
*
|
||||
* This implementation is the most basic version for Windows. It should
|
||||
* work for any non-MSVC-like compilers as long as there are Interlocked WinAPI
|
||||
* functions available. This version is also used for WinCE.
|
||||
*
|
||||
* Notably, this implementation is not as efficient as other
|
||||
* versions based on compiler intrinsics.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ATOMIC_DETAIL_OPS_WINDOWS_HPP_INCLUDED_
|
||||
#define BOOST_ATOMIC_DETAIL_OPS_WINDOWS_HPP_INCLUDED_
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/memory_order.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/detail/type_traits/make_signed.hpp>
|
||||
#include <boost/atomic/capabilities.hpp>
|
||||
#include <boost/atomic/detail/ops_msvc_common.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 windows_operations_base
|
||||
{
|
||||
static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = false;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
|
||||
|
||||
static BOOST_FORCEINLINE void hardware_full_fence() BOOST_NOEXCEPT
|
||||
{
|
||||
long tmp;
|
||||
BOOST_ATOMIC_INTERLOCKED_EXCHANGE(&tmp, 0);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
};
|
||||
|
||||
template< std::size_t Size, bool Signed, typename Derived >
|
||||
struct windows_operations :
|
||||
public windows_operations_base
|
||||
{
|
||||
typedef typename make_storage_type< Size >::type storage_type;
|
||||
typedef typename make_storage_type< Size >::aligned aligned_storage_type;
|
||||
|
||||
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = Size;
|
||||
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
|
||||
|
||||
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
Derived::exchange(storage, v, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
return Derived::fetch_add(const_cast< storage_type volatile& >(storage), (storage_type)0, order);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
typedef typename boost::atomics::detail::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);
|
||||
}
|
||||
};
|
||||
|
||||
template< bool Signed >
|
||||
struct operations< 4u, Signed > :
|
||||
public windows_operations< 4u, Signed, operations< 4u, Signed > >
|
||||
{
|
||||
typedef windows_operations< 4u, Signed, operations< 4u, Signed > > base_type;
|
||||
typedef typename 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
|
||||
{
|
||||
base_type::fence_before(order);
|
||||
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(&storage, v));
|
||||
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);
|
||||
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE(&storage, v));
|
||||
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 failure_order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type previous = expected;
|
||||
base_type::fence_before(success_order);
|
||||
storage_type old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(&storage, desired, previous));
|
||||
expected = old_val;
|
||||
// The success and failure fences are the same anyway
|
||||
base_type::fence_after(success_order);
|
||||
return (previous == old_val);
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
#if defined(BOOST_ATOMIC_INTERLOCKED_AND)
|
||||
base_type::fence_before(order);
|
||||
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND(&storage, v));
|
||||
base_type::fence_after(order);
|
||||
return v;
|
||||
#else
|
||||
storage_type res = storage;
|
||||
while (!compare_exchange_strong(storage, res, res & v, order, memory_order_relaxed)) {}
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
#if defined(BOOST_ATOMIC_INTERLOCKED_OR)
|
||||
base_type::fence_before(order);
|
||||
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR(&storage, v));
|
||||
base_type::fence_after(order);
|
||||
return v;
|
||||
#else
|
||||
storage_type res = storage;
|
||||
while (!compare_exchange_strong(storage, res, res | v, order, memory_order_relaxed)) {}
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
#if defined(BOOST_ATOMIC_INTERLOCKED_XOR)
|
||||
base_type::fence_before(order);
|
||||
v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR(&storage, v));
|
||||
base_type::fence_after(order);
|
||||
return v;
|
||||
#else
|
||||
storage_type res = storage;
|
||||
while (!compare_exchange_strong(storage, res, res ^ v, order, memory_order_relaxed)) {}
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
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 >
|
||||
{
|
||||
};
|
||||
|
||||
BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
|
||||
if (order == memory_order_seq_cst)
|
||||
windows_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
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_OPS_WINDOWS_HPP_INCLUDED_
|
43
boost/atomic/detail/pause.hpp
Normal file
43
boost/atomic/detail/pause.hpp
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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)
|
||||
*
|
||||
* (C) Copyright 2013 Tim Blechmann
|
||||
* (C) Copyright 2013 Andrey Semashev
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ATOMIC_DETAIL_PAUSE_HPP_INCLUDED_
|
||||
#define BOOST_ATOMIC_DETAIL_PAUSE_HPP_INCLUDED_
|
||||
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && (defined(_M_AMD64) || defined(_M_IX86))
|
||||
extern "C" void _mm_pause(void);
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma intrinsic(_mm_pause)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
BOOST_FORCEINLINE void pause() BOOST_NOEXCEPT
|
||||
{
|
||||
#if defined(_MSC_VER) && (defined(_M_AMD64) || defined(_M_IX86))
|
||||
_mm_pause();
|
||||
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
||||
__asm__ __volatile__("pause;");
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace atomics
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_PAUSE_HPP_INCLUDED_
|
163
boost/atomic/detail/platform.hpp
Normal file
163
boost/atomic/detail/platform.hpp
Normal file
@ -0,0 +1,163 @@
|
||||
/*
|
||||
* 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) 2014 Andrey Semashev
|
||||
*/
|
||||
/*!
|
||||
* \file atomic/detail/platform.hpp
|
||||
*
|
||||
* This header defines macros for the target platform detection
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ATOMIC_DETAIL_PLATFORM_HPP_INCLUDED_
|
||||
#define BOOST_ATOMIC_DETAIL_PLATFORM_HPP_INCLUDED_
|
||||
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && defined(__arm__)
|
||||
|
||||
// Newer gcc versions define __ARM_ARCH. Older ones don't, so we have to deduce ARM arch version from a bunch of version-specific macros.
|
||||
#if defined(__ARM_ARCH)
|
||||
#define BOOST_ATOMIC_DETAIL_ARM_ARCH __ARM_ARCH
|
||||
#elif defined(__ARM_ARCH_8A__)
|
||||
#define BOOST_ATOMIC_DETAIL_ARM_ARCH 8
|
||||
#elif defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) ||\
|
||||
defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) ||\
|
||||
defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7S__)
|
||||
#define BOOST_ATOMIC_DETAIL_ARM_ARCH 7
|
||||
#elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) ||\
|
||||
defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) ||\
|
||||
defined(__ARM_ARCH_6ZK__)
|
||||
#define BOOST_ATOMIC_DETAIL_ARM_ARCH 6
|
||||
#else
|
||||
// We are not interested in older versions - they don't support atomic ops
|
||||
#define BOOST_ATOMIC_DETAIL_ARM_ARCH 0
|
||||
#endif
|
||||
|
||||
#endif // defined(__GNUC__) && defined(__arm__)
|
||||
|
||||
#if !defined(BOOST_ATOMIC_FORCE_FALLBACK)
|
||||
|
||||
// Determine the target platform.
|
||||
// The target platform describes the compiler and target architecture. It can be used by more generic backends, such as the ones
|
||||
// based on compiler intrinsics, to implement specialized operations in a non-generic way.
|
||||
|
||||
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
||||
|
||||
#define BOOST_ATOMIC_DETAIL_PLATFORM gcc_x86
|
||||
#define BOOST_ATOMIC_DETAIL_EXTRA_BACKEND gcc_x86
|
||||
|
||||
#elif defined(__GNUC__) && (defined(__POWERPC__) || defined(__PPC__))
|
||||
|
||||
#define BOOST_ATOMIC_DETAIL_PLATFORM gcc_ppc
|
||||
#define BOOST_ATOMIC_DETAIL_EXTRA_BACKEND gcc_ppc
|
||||
|
||||
#elif defined(__GNUC__) && defined(__arm__) && (BOOST_ATOMIC_DETAIL_ARM_ARCH+0) >= 6
|
||||
|
||||
#define BOOST_ATOMIC_DETAIL_PLATFORM gcc_arm
|
||||
#define BOOST_ATOMIC_DETAIL_EXTRA_BACKEND gcc_arm
|
||||
|
||||
#elif (defined(__GNUC__) || defined(__SUNPRO_CC)) && (defined(__sparcv8plus) || defined(__sparc_v9__))
|
||||
|
||||
#define BOOST_ATOMIC_DETAIL_PLATFORM gcc_sparc
|
||||
|
||||
#elif defined(__GNUC__) && defined(__alpha__)
|
||||
|
||||
#define BOOST_ATOMIC_DETAIL_PLATFORM gcc_alpha
|
||||
|
||||
#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
|
||||
|
||||
#define BOOST_ATOMIC_DETAIL_PLATFORM msvc_x86
|
||||
|
||||
#elif defined(_MSC_VER) && _MSC_VER >= 1700 && (defined(_M_ARM) || defined(_M_ARM64))
|
||||
|
||||
#define BOOST_ATOMIC_DETAIL_PLATFORM msvc_arm
|
||||
|
||||
#endif
|
||||
|
||||
// Compiler-based backends
|
||||
|
||||
// IBM XL C++ Compiler has to be checked before GCC/Clang as it pretends to be one but does not support __atomic* intrinsics.
|
||||
// It does support GCC inline assembler though.
|
||||
#if !(defined(__ibmxl__) || defined(__IBMCPP__)) &&\
|
||||
((defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 407)) ||\
|
||||
(defined(BOOST_CLANG) && ((__clang_major__ * 100 + __clang_minor__) >= 302))) &&\
|
||||
(\
|
||||
(__GCC_ATOMIC_BOOL_LOCK_FREE + 0) == 2 ||\
|
||||
(__GCC_ATOMIC_CHAR_LOCK_FREE + 0) == 2 ||\
|
||||
(__GCC_ATOMIC_SHORT_LOCK_FREE + 0) == 2 ||\
|
||||
(__GCC_ATOMIC_INT_LOCK_FREE + 0) == 2 ||\
|
||||
(__GCC_ATOMIC_LONG_LOCK_FREE + 0) == 2 ||\
|
||||
(__GCC_ATOMIC_LLONG_LOCK_FREE + 0) == 2\
|
||||
)
|
||||
|
||||
#define BOOST_ATOMIC_DETAIL_BACKEND gcc_atomic
|
||||
|
||||
#elif defined(BOOST_ATOMIC_DETAIL_PLATFORM)
|
||||
|
||||
#define BOOST_ATOMIC_DETAIL_BACKEND BOOST_ATOMIC_DETAIL_PLATFORM
|
||||
|
||||
#elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 401) &&\
|
||||
(\
|
||||
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_DETAIL_BACKEND gcc_sync
|
||||
|
||||
#endif
|
||||
|
||||
// OS-based backends
|
||||
|
||||
#if !defined(BOOST_ATOMIC_DETAIL_BACKEND)
|
||||
|
||||
#if defined(__linux__) && defined(__arm__)
|
||||
|
||||
#define BOOST_ATOMIC_DETAIL_BACKEND linux_arm
|
||||
|
||||
#elif defined(BOOST_WINDOWS) || defined(_WIN32_CE)
|
||||
|
||||
#define BOOST_ATOMIC_DETAIL_BACKEND windows
|
||||
|
||||
#endif
|
||||
|
||||
#endif // !defined(BOOST_ATOMIC_DETAIL_BACKEND)
|
||||
|
||||
#endif // !defined(BOOST_ATOMIC_FORCE_FALLBACK)
|
||||
|
||||
#if !defined(BOOST_ATOMIC_DETAIL_BACKEND)
|
||||
#define BOOST_ATOMIC_DETAIL_BACKEND emulated
|
||||
#define BOOST_ATOMIC_EMULATED
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_ATOMIC_DETAIL_FP_BACKEND)
|
||||
#define BOOST_ATOMIC_DETAIL_FP_BACKEND generic
|
||||
#define BOOST_ATOMIC_DETAIL_FP_BACKEND_GENERIC
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_ATOMIC_DETAIL_EXTRA_BACKEND)
|
||||
#define BOOST_ATOMIC_DETAIL_EXTRA_BACKEND generic
|
||||
#define BOOST_ATOMIC_DETAIL_EXTRA_BACKEND_GENERIC
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_ATOMIC_DETAIL_EXTRA_FP_BACKEND)
|
||||
#define BOOST_ATOMIC_DETAIL_EXTRA_FP_BACKEND generic
|
||||
#define BOOST_ATOMIC_DETAIL_EXTRA_FP_BACKEND_GENERIC
|
||||
#endif
|
||||
|
||||
#define BOOST_ATOMIC_DETAIL_BACKEND_HEADER(prefix) <BOOST_JOIN(prefix, BOOST_ATOMIC_DETAIL_BACKEND).hpp>
|
||||
#define BOOST_ATOMIC_DETAIL_FP_BACKEND_HEADER(prefix) <BOOST_JOIN(prefix, BOOST_ATOMIC_DETAIL_FP_BACKEND).hpp>
|
||||
#define BOOST_ATOMIC_DETAIL_EXTRA_BACKEND_HEADER(prefix) <BOOST_JOIN(prefix, BOOST_ATOMIC_DETAIL_EXTRA_BACKEND).hpp>
|
||||
#define BOOST_ATOMIC_DETAIL_EXTRA_FP_BACKEND_HEADER(prefix) <BOOST_JOIN(prefix, BOOST_ATOMIC_DETAIL_EXTRA_FP_BACKEND).hpp>
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_PLATFORM_HPP_INCLUDED_
|
207
boost/atomic/detail/storage_type.hpp
Normal file
207
boost/atomic/detail/storage_type.hpp
Normal file
@ -0,0 +1,207 @@
|
||||
/*
|
||||
* 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/storage_type.hpp
|
||||
*
|
||||
* This header defines underlying types used as storage
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ATOMIC_DETAIL_STORAGE_TYPE_HPP_INCLUDED_
|
||||
#define BOOST_ATOMIC_DETAIL_STORAGE_TYPE_HPP_INCLUDED_
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
#include <boost/atomic/detail/string_ops.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
template< typename T >
|
||||
BOOST_FORCEINLINE void non_atomic_load(T const volatile& from, T& to) BOOST_NOEXCEPT
|
||||
{
|
||||
to = from;
|
||||
}
|
||||
|
||||
template< std::size_t Size >
|
||||
struct BOOST_ATOMIC_DETAIL_MAY_ALIAS buffer_storage
|
||||
{
|
||||
BOOST_ALIGNMENT(16) unsigned char data[Size];
|
||||
|
||||
BOOST_FORCEINLINE bool operator! () const BOOST_NOEXCEPT
|
||||
{
|
||||
return (data[0] == 0u && BOOST_ATOMIC_DETAIL_MEMCMP(data, data + 1, Size - 1) == 0);
|
||||
}
|
||||
|
||||
BOOST_FORCEINLINE bool operator== (buffer_storage const& that) const BOOST_NOEXCEPT
|
||||
{
|
||||
return BOOST_ATOMIC_DETAIL_MEMCMP(data, that.data, Size) == 0;
|
||||
}
|
||||
|
||||
BOOST_FORCEINLINE bool operator!= (buffer_storage const& that) const BOOST_NOEXCEPT
|
||||
{
|
||||
return BOOST_ATOMIC_DETAIL_MEMCMP(data, that.data, Size) != 0;
|
||||
}
|
||||
};
|
||||
|
||||
template< std::size_t Size >
|
||||
BOOST_FORCEINLINE void non_atomic_load(buffer_storage< Size > const volatile& from, buffer_storage< Size >& to) BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_ATOMIC_DETAIL_MEMCPY(to.data, const_cast< unsigned char const* >(from.data), Size);
|
||||
}
|
||||
|
||||
template< std::size_t Size >
|
||||
struct make_storage_type
|
||||
{
|
||||
typedef buffer_storage< Size > type;
|
||||
|
||||
struct BOOST_ATOMIC_DETAIL_MAY_ALIAS aligned
|
||||
{
|
||||
type value;
|
||||
|
||||
BOOST_DEFAULTED_FUNCTION(aligned(), {})
|
||||
BOOST_FORCEINLINE BOOST_CONSTEXPR explicit aligned(type const& v) BOOST_NOEXCEPT : value(v) {}
|
||||
};
|
||||
};
|
||||
|
||||
template< >
|
||||
struct make_storage_type< 1u >
|
||||
{
|
||||
typedef boost::uint8_t BOOST_ATOMIC_DETAIL_MAY_ALIAS type;
|
||||
|
||||
struct BOOST_ATOMIC_DETAIL_MAY_ALIAS aligned
|
||||
{
|
||||
type value;
|
||||
|
||||
BOOST_DEFAULTED_FUNCTION(aligned(), {})
|
||||
BOOST_FORCEINLINE BOOST_CONSTEXPR explicit aligned(type v) BOOST_NOEXCEPT : value(v) {}
|
||||
};
|
||||
};
|
||||
|
||||
template< >
|
||||
struct make_storage_type< 2u >
|
||||
{
|
||||
typedef boost::uint16_t BOOST_ATOMIC_DETAIL_MAY_ALIAS type;
|
||||
|
||||
struct BOOST_ATOMIC_DETAIL_MAY_ALIAS aligned
|
||||
{
|
||||
BOOST_ALIGNMENT(2) type value;
|
||||
|
||||
BOOST_DEFAULTED_FUNCTION(aligned(), {})
|
||||
BOOST_FORCEINLINE BOOST_CONSTEXPR explicit aligned(type v) BOOST_NOEXCEPT : value(v) {}
|
||||
};
|
||||
};
|
||||
|
||||
template< >
|
||||
struct make_storage_type< 4u >
|
||||
{
|
||||
typedef boost::uint32_t BOOST_ATOMIC_DETAIL_MAY_ALIAS type;
|
||||
|
||||
struct BOOST_ATOMIC_DETAIL_MAY_ALIAS aligned
|
||||
{
|
||||
BOOST_ALIGNMENT(4) type value;
|
||||
|
||||
BOOST_DEFAULTED_FUNCTION(aligned(), {})
|
||||
BOOST_FORCEINLINE BOOST_CONSTEXPR explicit aligned(type v) BOOST_NOEXCEPT : value(v) {}
|
||||
};
|
||||
};
|
||||
|
||||
template< >
|
||||
struct make_storage_type< 8u >
|
||||
{
|
||||
typedef boost::uint64_t BOOST_ATOMIC_DETAIL_MAY_ALIAS type;
|
||||
|
||||
struct BOOST_ATOMIC_DETAIL_MAY_ALIAS aligned
|
||||
{
|
||||
BOOST_ALIGNMENT(8) type value;
|
||||
|
||||
BOOST_DEFAULTED_FUNCTION(aligned(), {})
|
||||
BOOST_FORCEINLINE BOOST_CONSTEXPR explicit aligned(type v) BOOST_NOEXCEPT : value(v) {}
|
||||
};
|
||||
};
|
||||
|
||||
#if defined(BOOST_HAS_INT128)
|
||||
|
||||
template< >
|
||||
struct make_storage_type< 16u >
|
||||
{
|
||||
typedef boost::uint128_type BOOST_ATOMIC_DETAIL_MAY_ALIAS type;
|
||||
|
||||
struct BOOST_ATOMIC_DETAIL_MAY_ALIAS aligned
|
||||
{
|
||||
BOOST_ALIGNMENT(16) type value;
|
||||
|
||||
BOOST_DEFAULTED_FUNCTION(aligned(), {})
|
||||
BOOST_FORCEINLINE BOOST_CONSTEXPR explicit aligned(type v) BOOST_NOEXCEPT : value(v) {}
|
||||
};
|
||||
};
|
||||
|
||||
#elif !defined(BOOST_NO_ALIGNMENT)
|
||||
|
||||
struct BOOST_ATOMIC_DETAIL_MAY_ALIAS storage128_t
|
||||
{
|
||||
typedef boost::uint64_t BOOST_ATOMIC_DETAIL_MAY_ALIAS element_type;
|
||||
|
||||
element_type data[2];
|
||||
|
||||
BOOST_FORCEINLINE bool operator! () const BOOST_NOEXCEPT
|
||||
{
|
||||
return (data[0] | data[1]) == 0u;
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_FORCEINLINE bool operator== (storage128_t const& left, storage128_t const& right) BOOST_NOEXCEPT
|
||||
{
|
||||
return ((left.data[0] ^ right.data[0]) | (left.data[1] ^ right.data[1])) == 0u;
|
||||
}
|
||||
BOOST_FORCEINLINE bool operator!= (storage128_t const& left, storage128_t const& right) BOOST_NOEXCEPT
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
|
||||
BOOST_FORCEINLINE void non_atomic_load(storage128_t const volatile& from, storage128_t& to) BOOST_NOEXCEPT
|
||||
{
|
||||
to.data[0] = from.data[0];
|
||||
to.data[1] = from.data[1];
|
||||
}
|
||||
|
||||
template< >
|
||||
struct make_storage_type< 16u >
|
||||
{
|
||||
typedef storage128_t type;
|
||||
|
||||
struct BOOST_ATOMIC_DETAIL_MAY_ALIAS aligned
|
||||
{
|
||||
BOOST_ALIGNMENT(16) type value;
|
||||
|
||||
BOOST_DEFAULTED_FUNCTION(aligned(), {})
|
||||
BOOST_FORCEINLINE BOOST_CONSTEXPR explicit aligned(type const& v) BOOST_NOEXCEPT : value(v) {}
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
template< typename T >
|
||||
struct storage_size_of
|
||||
{
|
||||
static BOOST_CONSTEXPR_OR_CONST std::size_t size = sizeof(T);
|
||||
static BOOST_CONSTEXPR_OR_CONST std::size_t value = (size == 3u ? 4u : (size >= 5u && size <= 7u ? 8u : (size >= 9u && size <= 15u ? 16u : size)));
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace atomics
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_STORAGE_TYPE_HPP_INCLUDED_
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user