Commit fcb10459 by Abseil Team Committed by Ashley Hedberg

Creation of LTS branch "lts_2018_12_18"

  - 44b0fafc Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 926bfeb9 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 13327deb Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 3088e76c Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - f6ae8168 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - a06c4a1d Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 7b46e1d3 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 070f6e47 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 7990fd45 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - f9517906 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - cc8dcd30 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - a705aa78 Merge pull request #194 from Mizux/windows by Xiaoyi Zhang <zhangxy988@gmail.com>
  - a4c3ffff Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 01174578 Merge pull request #201 from ccawley2011/fix-byteswap by Matt Calabrese <38107210+mattcalabrese-google@users.noreply.github.com>
  - f86f9413 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 94c298e2 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 0884a6a0 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - c16d5557 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 45221ccc Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 2019e17a Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 5b70a891 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - a00bdd17 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - f340f773 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 445998d7 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - e821380d Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - f21d187b Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 5441bbe1 Fix code snippet in comment (#174) by Loo Rong Jie <loorongjie@gmail.com>
  - 5aae0cff Fix CMake build (#173) by Stephan Dollberg <stephan.dollberg@gmail.com>
  - 48cd2c3f Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - e291c279 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - e01d9552 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 8ff13740 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 02451914 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 921fd5cf Merge pull request #166 from rongjiecomputer/cmake-test by Gennadiy Civil <gennadiycivil@users.noreply.github.com>
  - fb462224 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - c075ad32 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 0f4bc966 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 6c7e5ffc Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - d6df7691 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 28080f5f Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 9c987f42 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 5e7d459e Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - bed5bd6e Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - fefc8363 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - d8cfe9f2 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - ad5c960b Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 86f0fe93 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - f0f15c27 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 29ff6d48 Removed "warning treated as error" flag from MSVC (#153) by vocaviking <vocaviking@users.noreply.github.com>
  - 083d04dd Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - bea85b52 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 8f96be6c Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 92e07e55 Merge pull request #152 from clnperez/fix-multi-defines-p... by Derek Mauro <761129+derekmauro@users.noreply.github.com>
  - 2125e644 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 9acad869 Merge pull request #150 from OlafvdSpek/patch-2 by Jonathan Cohen <cohenjon@google.com>
  - c2e00d34 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 9e060686 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 7aa411ce Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 2c5af55e Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 44aa2752 Merge pull request #143 from rongjiecomputer/kernel by Xiaoyi Zhang <zhangxy988@gmail.com>
  - 42f22a28 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - b973bc53 Merge pull request #139 from siepkes/smartos-support by ahedberg <ahedberg@google.com>
  - e0def747 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - f826f1d4 Merge pull request #138 from edbaunton/remove-deprecated-... by ahedberg <ahedberg@google.com>
  - 7b50a4a9 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - a5030ca5 Merge pull request #144 from rongjiecomputer/winsock2 by Xiaoyi Zhang <zhangxy988@gmail.com>
  - 02687955 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 8f612ebb Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 134496a3 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - ba8d6cf0 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - be1e84b9 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 16ac2ec2 Merge pull request #134 from rongjiecomputer/cmake by Alex Strelnikov <strel@google.com>
  - 7efd8dc0 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 87a4c078 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
  - 4491d606 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>

GitOrigin-RevId: 44b0fafc
Change-Id: I2c427b5b41b2d34101922048b00f3d9dafcb498d
parent 6c7de165
# Ignore all bazel-* symlinks.
/bazel-*
# Ignore Bazel verbose explanations
--verbose_explanations
# Ignore CMake usual build directory
build
# Ignore Vim files
*.swp
# Ignore QtCreator Project file
CMakeLists.txt.user
# Ignore VS Code files
.vscode/*
# Abseil-specific compiler flags. See absl/copts.bzl for description.
# DO NOT CHANGE THIS FILE WITHOUT THE CORRESPONDING CHANGE TO absl/copts.bzl
list(APPEND GCC_FLAGS
-Wall
-Wextra
-Wcast-qual
-Wconversion-null
-Wmissing-declarations
-Woverlength-strings
-Wpointer-arith
-Wunused-local-typedefs
-Wunused-result
-Wvarargs
-Wwrite-strings
-Wno-sign-compare
)
list(APPEND GCC_TEST_FLAGS
-Wno-conversion-null
-Wno-missing-declarations
-Wno-sign-compare
-Wno-unused-function
-Wno-unused-parameter
-Wno-unused-private-field
)
list(APPEND LLVM_FLAGS
-Wall
-Wextra
-Weverything
-Wno-c++98-compat-pedantic
-Wno-conversion
-Wno-covered-switch-default
-Wno-deprecated
-Wno-disabled-macro-expansion
-Wno-double-promotion
-Wno-comma
-Wno-extra-semi
-Wno-packed
-Wno-padded
-Wno-sign-compare
-Wno-float-conversion
-Wno-float-equal
-Wno-format-nonliteral
-Wno-gcc-compat
-Wno-global-constructors
-Wno-exit-time-destructors
-Wno-nested-anon-types
-Wno-non-modular-include-in-module
-Wno-old-style-cast
-Wno-range-loop-analysis
-Wno-reserved-id-macro
-Wno-shorten-64-to-32
-Wno-switch-enum
-Wno-thread-safety-negative
-Wno-undef
-Wno-unknown-warning-option
-Wno-unreachable-code
-Wno-unused-macros
-Wno-weak-vtables
-Wbitfield-enum-conversion
-Wbool-conversion
-Wconstant-conversion
-Wenum-conversion
-Wint-conversion
-Wliteral-conversion
-Wnon-literal-null-conversion
-Wnull-conversion
-Wobjc-literal-conversion
-Wno-sign-conversion
-Wstring-conversion
)
list(APPEND LLVM_TEST_FLAGS
-Wno-c99-extensions
-Wno-missing-noreturn
-Wno-missing-prototypes
-Wno-missing-variable-declarations
-Wno-null-conversion
-Wno-shadow
-Wno-shift-sign-overflow
-Wno-sign-compare
-Wno-unused-function
-Wno-unused-member-function
-Wno-unused-parameter
-Wno-unused-private-field
-Wno-unused-template
-Wno-used-but-marked-unused
-Wno-zero-as-null-pointer-constant
-Wno-gnu-zero-variadic-macro-arguments
)
list(APPEND MSVC_FLAGS
/W3
/wd4005
/wd4018
/wd4068
/wd4180
/wd4244
/wd4267
/wd4800
/DNOMINMAX
/DWIN32_LEAN_AND_MEAN
/D_CRT_SECURE_NO_WARNINGS
/D_SCL_SECURE_NO_WARNINGS
/D_ENABLE_EXTENDED_ALIGNED_STORAGE
)
list(APPEND MSVC_TEST_FLAGS
/wd4101
/wd4503
)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(ABSL_DEFAULT_COPTS "${GCC_FLAGS}")
set(ABSL_TEST_COPTS "${GCC_FLAGS};${GCC_TEST_FLAGS}")
set(ABSL_EXCEPTIONS_FLAG "-fexceptions")
elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
# MATCHES so we get both Clang and AppleClang
set(ABSL_DEFAULT_COPTS "${LLVM_FLAGS}")
set(ABSL_TEST_COPTS "${LLVM_FLAGS};${LLVM_TEST_FLAGS}")
set(ABSL_EXCEPTIONS_FLAG "-fexceptions")
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
set(ABSL_DEFAULT_COPTS "${MSVC_FLAGS}")
set(ABSL_TEST_COPTS "${MSVC_FLAGS};${MSVC_TEST_FLAGS}")
set(ABSL_EXCEPTIONS_FLAG "/U_HAS_EXCEPTIONS;/D_HAS_EXCEPTIONS=1;/EHsc")
else()
message(WARNING "Unknown compiler: ${CMAKE_CXX_COMPILER}. Building with no default flags")
set(ABSL_DEFAULT_COPTS "")
set(ABSL_TEST_COPTS "")
set(ABSL_EXCEPTIONS_FLAG "")
endif()
# This flag is used internally for Bazel builds and is kept here for consistency
set(ABSL_EXCEPTIONS_FLAG_LINKOPTS "")
if("${CMAKE_CXX_STANDARD}" EQUAL 98)
message(FATAL_ERROR "Abseil requires at least C++11")
elseif(NOT "${CMAKE_CXX_STANDARD}")
message(STATUS "No CMAKE_CXX_STANDARD set, assuming 11")
set(ABSL_CXX_STANDARD 11)
else()
set(ABSL_CXX_STANDARD "${CMAKE_CXX_STANDARD}")
endif()
......@@ -15,6 +15,7 @@
#
include(CMakeParseArguments)
include(AbseilConfigureCopts)
# The IDE folder for Abseil that will be used if Abseil is included in a CMake
# project that sets
......@@ -48,7 +49,11 @@ function(absl_library)
add_library(${_NAME} STATIC ${ABSL_LIB_SOURCES})
target_compile_options(${_NAME} PRIVATE ${ABSL_COMPILE_CXXFLAGS} ${ABSL_LIB_PRIVATE_COMPILE_FLAGS})
target_compile_options(${_NAME}
PRIVATE
${ABSL_LIB_PRIVATE_COMPILE_FLAGS}
${ABSL_DEFAULT_COPTS}
)
target_link_libraries(${_NAME} PUBLIC ${ABSL_LIB_PUBLIC_LIBRARIES})
target_include_directories(${_NAME}
PUBLIC ${ABSL_COMMON_INCLUDE_DIRS} ${ABSL_LIB_PUBLIC_INCLUDE_DIRS}
......@@ -57,12 +62,199 @@ function(absl_library)
# Add all Abseil targets to a a folder in the IDE for organization.
set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER})
set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${ABSL_CXX_STANDARD})
set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
if(ABSL_LIB_EXPORT_NAME)
add_library(absl::${ABSL_LIB_EXPORT_NAME} ALIAS ${_NAME})
endif()
endfunction()
# CMake function to imitate Bazel's cc_library rule.
#
# Parameters:
# NAME: name of target (see Note)
# HDRS: List of public header files for the library
# SRCS: List of source files for the library
# DEPS: List of other libraries to be linked in to the binary targets
# COPTS: List of private compile options
# DEFINES: List of public defines
# LINKOPTS: List of link options
# PUBLIC: Add this so that this library will be exported under absl:: (see Note).
# Also in IDE, target will appear in Abseil folder while non PUBLIC will be in Abseil/internal.
# TESTONLY: When added, this target will only be built if user passes -DABSL_RUN_TESTS=ON to CMake.
#
# Note:
# By default, absl_cc_library will always create a library named absl_internal_${NAME},
# and alias target absl::${NAME}.
# This is to reduce namespace pollution.
#
# absl_cc_library(
# NAME
# awesome
# HDRS
# "a.h"
# SRCS
# "a.cc"
# )
# absl_cc_library(
# NAME
# fantastic_lib
# SRCS
# "b.cc"
# DEPS
# absl_internal_awesome # not "awesome"!
# )
#
# If PUBLIC is set, absl_cc_library will instead create a target named
# absl_${NAME} and still an alias absl::${NAME}.
#
# absl_cc_library(
# NAME
# main_lib
# ...
# PUBLIC
# )
#
# User can then use the library as absl::main_lib (although absl_main_lib is defined too).
#
# TODO: Implement "ALWAYSLINK"
function(absl_cc_library)
cmake_parse_arguments(ABSL_CC_LIB
"DISABLE_INSTALL;PUBLIC;TESTONLY"
"NAME"
"HDRS;SRCS;COPTS;DEFINES;LINKOPTS;DEPS"
${ARGN}
)
if (NOT ABSL_CC_LIB_TESTONLY OR ABSL_RUN_TESTS)
if (ABSL_CC_LIB_PUBLIC)
set(_NAME "absl_${ABSL_CC_LIB_NAME}")
else()
set(_NAME "absl_internal_${ABSL_CC_LIB_NAME}")
endif()
# Check if this is a header-only library
if ("${ABSL_CC_LIB_SRCS}" STREQUAL "")
set(ABSL_CC_LIB_IS_INTERFACE 1)
else()
set(ABSL_CC_LIB_IS_INTERFACE 0)
endif()
if(NOT ABSL_CC_LIB_IS_INTERFACE)
add_library(${_NAME} STATIC "")
target_sources(${_NAME} PRIVATE ${ABSL_CC_LIB_SRCS} ${ABSL_CC_LIB_HDRS})
target_include_directories(${_NAME}
PUBLIC ${ABSL_COMMON_INCLUDE_DIRS})
target_compile_options(${_NAME}
PRIVATE ${ABSL_CC_LIB_COPTS})
target_link_libraries(${_NAME}
PUBLIC ${ABSL_CC_LIB_DEPS}
PRIVATE ${ABSL_CC_LIB_LINKOPTS}
)
target_compile_definitions(${_NAME} PUBLIC ${ABSL_CC_LIB_DEFINES})
# Add all Abseil targets to a a folder in the IDE for organization.
if(ABSL_CC_LIB_PUBLIC)
set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER})
elseif(ABSL_CC_LIB_TESTONLY)
set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/test)
else()
set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/internal)
endif()
# INTERFACE libraries can't have the CXX_STANDARD property set
set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${ABSL_CXX_STANDARD})
set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
else()
# Generating header-only library
add_library(${_NAME} INTERFACE)
target_include_directories(${_NAME}
INTERFACE ${ABSL_COMMON_INCLUDE_DIRS})
target_link_libraries(${_NAME}
INTERFACE ${ABSL_CC_LIB_DEPS} ${ABSL_CC_LIB_LINKOPTS}
)
target_compile_definitions(${_NAME} INTERFACE ${ABSL_CC_LIB_DEFINES})
endif()
add_library(absl::${ABSL_CC_LIB_NAME} ALIAS ${_NAME})
endif()
endfunction()
# absl_cc_test()
#
# CMake function to imitate Bazel's cc_test rule.
#
# Parameters:
# NAME: name of target (see Usage below)
# SRCS: List of source files for the binary
# DEPS: List of other libraries to be linked in to the binary targets
# COPTS: List of private compile options
# DEFINES: List of public defines
# LINKOPTS: List of link options
#
# Note:
# By default, absl_cc_test will always create a binary named absl_${NAME}.
# This will also add it to ctest list as absl_${NAME}.
#
# Usage:
# absl_cc_library(
# NAME
# awesome
# HDRS
# "a.h"
# SRCS
# "a.cc"
# PUBLIC
# )
#
# absl_cc_test(
# NAME
# awesome_test
# SRCS
# "awesome_test.cc"
# DEPS
# absl::awesome
# gmock
# gtest_main
# )
function(absl_cc_test)
if(NOT ABSL_RUN_TESTS)
return()
endif()
cmake_parse_arguments(ABSL_CC_TEST
""
"NAME"
"SRCS;COPTS;DEFINES;LINKOPTS;DEPS"
${ARGN}
)
set(_NAME "absl_${ABSL_CC_TEST_NAME}")
add_executable(${_NAME} "")
target_sources(${_NAME} PRIVATE ${ABSL_CC_TEST_SRCS})
target_include_directories(${_NAME}
PUBLIC ${ABSL_COMMON_INCLUDE_DIRS}
PRIVATE ${GMOCK_INCLUDE_DIRS} ${GTEST_INCLUDE_DIRS}
)
target_compile_definitions(${_NAME}
PUBLIC ${ABSL_CC_TEST_DEFINES}
)
target_compile_options(${_NAME}
PRIVATE ${ABSL_CC_TEST_COPTS}
)
target_link_libraries(${_NAME}
PUBLIC ${ABSL_CC_TEST_DEPS}
PRIVATE ${ABSL_CC_TEST_LINKOPTS}
)
# Add all Abseil targets to a a folder in the IDE for organization.
set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/test)
set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${ABSL_CXX_STANDARD})
set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
add_test(NAME ${_NAME} COMMAND ${_NAME})
endfunction()
#
# header only virtual target creation
......@@ -103,13 +295,15 @@ function(absl_header_library)
# Add all Abseil targets to a a folder in the IDE for organization.
set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER})
set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${ABSL_CXX_STANDARD})
set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
if(ABSL_HO_LIB_EXPORT_NAME)
add_library(absl::${ABSL_HO_LIB_EXPORT_NAME} ALIAS ${_NAME})
endif()
endfunction()
#
# create an abseil unit_test and add it to the executed test list
#
......@@ -123,7 +317,7 @@ endfunction()
#
# all tests will be register for execution with add_test()
#
# test compilation and execution is disable when BUILD_TESTING=OFF
# test compilation and execution is disable when ABSL_RUN_TESTS=OFF
#
function(absl_test)
......@@ -135,25 +329,32 @@ function(absl_test)
)
if(BUILD_TESTING)
if(ABSL_RUN_TESTS)
set(_NAME ${ABSL_TEST_TARGET})
set(_NAME "absl_${ABSL_TEST_TARGET}")
string(TOUPPER ${_NAME} _UPPER_NAME)
add_executable(${_NAME}_bin ${ABSL_TEST_SOURCES})
add_executable(${_NAME} ${ABSL_TEST_SOURCES})
target_compile_options(${_NAME}_bin PRIVATE ${ABSL_COMPILE_CXXFLAGS} ${ABSL_TEST_PRIVATE_COMPILE_FLAGS})
target_link_libraries(${_NAME}_bin PUBLIC ${ABSL_TEST_PUBLIC_LIBRARIES} ${ABSL_TEST_COMMON_LIBRARIES})
target_include_directories(${_NAME}_bin
target_compile_options(${_NAME}
PRIVATE
${ABSL_TEST_PRIVATE_COMPILE_FLAGS}
${ABSL_TEST_COPTS}
)
target_link_libraries(${_NAME} PUBLIC ${ABSL_TEST_PUBLIC_LIBRARIES} ${ABSL_TEST_COMMON_LIBRARIES})
target_include_directories(${_NAME}
PUBLIC ${ABSL_COMMON_INCLUDE_DIRS} ${ABSL_TEST_PUBLIC_INCLUDE_DIRS}
PRIVATE ${GMOCK_INCLUDE_DIRS} ${GTEST_INCLUDE_DIRS}
)
# Add all Abseil targets to a a folder in the IDE for organization.
set_property(TARGET ${_NAME}_bin PROPERTY FOLDER ${ABSL_IDE_FOLDER})
set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER})
set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${ABSL_CXX_STANDARD})
set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
add_test(${_NAME} ${_NAME}_bin)
endif(BUILD_TESTING)
add_test(NAME ${_NAME} COMMAND ${_NAME})
endif(ABSL_RUN_TESTS)
endfunction()
......
......@@ -4,7 +4,7 @@
# Download the latest googletest from Github master
configure_file(
${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt.in
googletest-download/CMakeLists.txt
${CMAKE_BINARY_DIR}/googletest-download/CMakeLists.txt
)
# Configure and build the downloaded googletest source
......
......@@ -17,9 +17,15 @@
# We require 3.0 for modern, target-based CMake. We require 3.1 for the use of
# CXX_STANDARD in our targets.
cmake_minimum_required(VERSION 3.1)
# Compiler id for Apple Clang is now AppleClang.
if (POLICY CMP0025)
cmake_policy(SET CMP0025 NEW)
endif()
project(absl)
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMake)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/CMake)
include(GNUInstallDirs)
include(AbseilHelpers)
......@@ -32,8 +38,16 @@ if (MSVC)
# /wd4244 conversion from 'type1' to 'type2'
# /wd4267 conversion from 'size_t' to 'type2'
# /wd4800 force value to bool 'true' or 'false' (performance warning)
add_compile_options(/W3 /WX /wd4005 /wd4068 /wd4244 /wd4267 /wd4800)
add_definitions(/DNOMINMAX /DWIN32_LEAN_AND_MEAN=1 /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS)
add_compile_options(/W3 /wd4005 /wd4068 /wd4244 /wd4267 /wd4800)
# /D_ENABLE_EXTENDED_ALIGNED_STORAGE Introduced in VS 2017 15.8, before the
# member type would non-conformingly have an alignment of only alignof(max_align_t).
add_definitions(
/DNOMINMAX
/DWIN32_LEAN_AND_MEAN=1
/D_CRT_SECURE_NO_WARNINGS
/D_SCL_SECURE_NO_WARNINGS
/D_ENABLE_EXTENDED_ALIGNED_STORAGE
)
else()
set(ABSL_STD_CXX_FLAG "-std=c++11" CACHE STRING "c++ std flag (default: c++11)")
endif()
......@@ -60,6 +74,12 @@ set(CMAKE_CXX_FLAGS "${ABSL_STD_CXX_FLAG} ${CMAKE_CXX_FLAGS}")
# -fexceptions
set(ABSL_EXCEPTIONS_FLAG "${CMAKE_CXX_EXCEPTIONS}")
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
set(ABSL_USING_CLANG ON)
else()
set(ABSL_USING_CLANG OFF)
endif()
# find dependencies
## pthread
find_package(Threads REQUIRED)
......
......@@ -18,6 +18,53 @@ You generally only need to submit a CLA once, so if you've already submitted one
(even if it was for a different project), you probably don't need to do it
again.
## Contribution Guidelines
Potential contributors sometimes ask us if the Abseil project is the appropriate
home for their utility library code or for specific functions implementing
missing portions of the standard. Often, the answer to this question is "no".
We’d like to articulate our thinking on this issue so that our choices can be
understood by everyone and so that contributors can have a better intuition
about whether Abseil might be interested in adopting a new library.
### Priorities
Although our mission is to augment the C++ standard library, our goal is not to
provide a full forward-compatible implementation of the latest standard. For us
to consider a library for inclusion in Abseil, it is not enough that a library
is useful. We generally choose to release a library when it meets at least one
of the following criteria:
* **Widespread usage** - Using our internal codebase to help gauge usage, most
of the libraries we've released have tens of thousands of users.
* **Anticipated widespread usage** - Pre-adoption of some standard-compliant
APIs may not have broad adoption initially but can be expected to pick up
usage when it replaces legacy APIs. `absl::from_chars`, for example,
replaces existing code that converts strings to numbers and will therefore
likely see usage growth.
* **High impact** - APIs that provide a key solution to a specific problem,
such as `absl::FixedArray`, have higher impact than usage numbers may signal
and are released because of their importance.
* **Direct support for a library that falls under one of the above** - When we
want access to a smaller library as an implementation detail for a
higher-priority library we plan to release, we may release it, as we did
with portions of `absl/meta/type_traits.h`. One consequence of this is that
the presence of a library in Abseil does not necessarily mean that other
similar libraries would be a high priority.
### API Freeze Consequences
Via the
[Abseil Compatibility Guidelines](https://abseil.io/about/compatibility), we
have promised a large degree of API stability. In particular, we will not make
backward-incompatible changes to released APIs without also shipping a tool or
process that can upgrade our users' code. We are not yet at the point of easily
releasing such tools. Therefore, at this time, shipping a library establishes an
API contract which is borderline unchangeable. (We can add new functionality,
but we cannot easily change existing behavior.) This constraint forces us to
very carefully review all APIs that we ship.
## Coding Style
To keep the source consistent, readable, diffable and easy to merge, we use a
......
......@@ -63,10 +63,14 @@ Abseil contains the following C++ library components:
<br /> The `algorithm` library contains additions to the C++ `<algorithm>`
library and container-based versions of such algorithms.
* [`container`](absl/container/)
<br /> The `container` library contains additional STL-style containers.
<br /> The `container` library contains additional STL-style containers,
including Abseil's unordered "Swiss table" containers.
* [`debugging`](absl/debugging/)
<br /> The `debugging` library contains code useful for enabling leak
checks. Future updates will add stacktrace and symbolization utilities.
checks, and stacktrace and symbolization utilities.
* [`hash`](absl/hash/)
<br /> The `hash` library contains the hashing framework and default hash
functor implementations for hashable types in Abseil.
* [`memory`](absl/memory/)
<br /> The `memory` library contains C++11-compatible versions of
`std::make_unique()` and related memory management facilities.
......@@ -90,6 +94,8 @@ Abseil contains the following C++ library components:
* [`types`](absl/types/)
<br /> The `types` library contains non-container utility types, like a
C++11-compatible version of the C++17 `std::optional` type.
* [`utility`](absl/utility/)
<br /> The `utility` library contains utility and helper code.
## License
......
workspace(name = "com_google_absl")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
# Bazel toolchains
http_archive(
name = "bazel_toolchains",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/287b64e0a211fb7c23b74695f8d5f5205b61f4eb.tar.gz",
"https://github.com/bazelbuild/bazel-toolchains/archive/287b64e0a211fb7c23b74695f8d5f5205b61f4eb.tar.gz",
"https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/bc09b995c137df042bb80a395b73d7ce6f26afbe.tar.gz",
"https://github.com/bazelbuild/bazel-toolchains/archive/bc09b995c137df042bb80a395b73d7ce6f26afbe.tar.gz",
],
strip_prefix = "bazel-toolchains-287b64e0a211fb7c23b74695f8d5f5205b61f4eb",
sha256 = "aca8ac6afd7745027ee4a43032b51a725a61a75a30f02cc58681ee87e4dcdf4b",
strip_prefix = "bazel-toolchains-bc09b995c137df042bb80a395b73d7ce6f26afbe",
sha256 = "4329663fe6c523425ad4d3c989a8ac026b04e1acedeceb56aa4b190fa7f3973c",
)
# GoogleTest/GoogleMock framework. Used by most unit-tests.
http_archive(
name = "com_google_googletest",
urls = ["https://github.com/google/googletest/archive/4e4df226fc197c0dda6e37f5c8c3845ca1e73a49.zip"],
strip_prefix = "googletest-4e4df226fc197c0dda6e37f5c8c3845ca1e73a49",
sha256 = "d4179caf54410968d1fff0b869e7d74803dd30209ee6645ccf1ca65ab6cf5e5a",
urls = ["https://github.com/google/googletest/archive/b4d4438df9479675a632b2f11125e57133822ece.zip"], # 2018-07-16
strip_prefix = "googletest-b4d4438df9479675a632b2f11125e57133822ece",
sha256 = "5aaa5d566517cae711e2a3505ea9a6438be1b37fcaae0ebcb96ccba9aa56f23a",
)
# Google benchmark.
......@@ -25,11 +27,3 @@ http_archive(
strip_prefix = "benchmark-16703ff83c1ae6d53e5155df3bb3ab0bc96083be",
sha256 = "59f918c8ccd4d74b6ac43484467b500f1d64b40cc1010daa055375b322a43ba3",
)
# RE2 regular-expression framework. Used by some unit-tests.
http_archive(
name = "com_googlesource_code_re2",
urls = ["https://github.com/google/re2/archive/6cf8ccd82dbaab2668e9b13596c68183c9ecd13f.zip"],
strip_prefix = "re2-6cf8ccd82dbaab2668e9b13596c68183c9ecd13f",
sha256 = "279a852219dbfc504501775596089d30e9c0b29664ce4128b0ac4c841471a16a",
)
......@@ -18,11 +18,10 @@ package(default_visibility = ["//visibility:public"])
licenses(["notice"]) # Apache 2.0
config_setting(
load(":compiler_config_setting.bzl", "create_llvm_config")
create_llvm_config(
name = "llvm_compiler",
values = {
"compiler": "llvm",
},
visibility = [":__subpackages__"],
)
......
......@@ -20,6 +20,7 @@ add_subdirectory(base)
add_subdirectory(algorithm)
add_subdirectory(container)
add_subdirectory(debugging)
add_subdirectory(hash)
add_subdirectory(memory)
add_subdirectory(meta)
add_subdirectory(numeric)
......
......@@ -14,50 +14,50 @@
# limitations under the License.
#
list(APPEND ALGORITHM_PUBLIC_HEADERS
absl_cc_library(
NAME
algorithm
HDRS
"algorithm.h"
"container.h"
COPTS
${ABSL_DEFAULT_COPTS}
PUBLIC
)
#
## TESTS
#
# test algorithm_test
list(APPEND ALGORITHM_TEST_SRC
absl_cc_test(
NAME
algorithm_test
SRCS
"algorithm_test.cc"
${ALGORITHM_PUBLIC_HEADERS}
${ALGORITHM_INTERNAL_HEADERS}
)
absl_header_library(
TARGET
absl_algorithm
EXPORT_NAME
algorithm
DEPS
absl::algorithm
gmock_main
)
absl_test(
TARGET
algorithm_test
SOURCES
${ALGORITHM_TEST_SRC}
PUBLIC_LIBRARIES
absl_cc_library(
NAME
algorithm_container
HDRS
"container.h"
COPTS
${ABSL_DEFAULT_COPTS}
DEPS
absl::algorithm
absl::core_headers
absl::meta
PUBLIC
)
# test container_test
set(CONTAINER_TEST_SRC "container_test.cc")
absl_test(
TARGET
absl_cc_test(
NAME
container_test
SOURCES
${CONTAINER_TEST_SRC}
PUBLIC_LIBRARIES
absl::algorithm
SRCS
"container_test.cc"
DEPS
absl::algorithm_container
absl::base
absl::core_headers
absl::memory
absl::span
gmock_main
)
......@@ -27,7 +27,7 @@
#include <type_traits>
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace algorithm_internal {
......@@ -146,7 +146,7 @@ ForwardIterator rotate(ForwardIterator first, ForwardIterator middle,
ForwardIterator>());
}
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
#endif // ABSL_ALGORITHM_ALGORITHM_H_
......@@ -46,6 +46,8 @@
#include <iterator>
#include <numeric>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
......@@ -54,8 +56,7 @@
#include "absl/meta/type_traits.h"
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace container_algorithm_internal {
// NOTE: it is important to defer to ADL lookup for building with C++ modules,
......@@ -102,6 +103,17 @@ ContainerIter<C> c_begin(C& c) { return begin(c); }
template <typename C>
ContainerIter<C> c_end(C& c) { return end(c); }
template <typename T>
struct IsUnorderedContainer : std::false_type {};
template <class Key, class T, class Hash, class KeyEqual, class Allocator>
struct IsUnorderedContainer<
std::unordered_map<Key, T, Hash, KeyEqual, Allocator>> : std::true_type {};
template <class Key, class Hash, class KeyEqual, class Allocator>
struct IsUnorderedContainer<std::unordered_set<Key, Hash, KeyEqual, Allocator>>
: std::true_type {};
} // namespace container_algorithm_internal
// PUBLIC API
......@@ -315,7 +327,7 @@ container_algorithm_internal::ContainerDifferenceType<const C> c_count_if(
// c_mismatch()
//
// Container-based version of the <algorithm> `std::mismatchf()` function to
// Container-based version of the <algorithm> `std::mismatch()` function to
// return the first element where two ordered containers differ.
template <typename C1, typename C2>
container_algorithm_internal::ContainerIterPairType<C1, C2>
......@@ -495,7 +507,7 @@ BidirectionalIterator c_copy_backward(const C& src,
// Container-based version of the <algorithm> `std::move()` function to move
// a container's elements into an iterator.
template <typename C, typename OutputIterator>
OutputIterator c_move(C& src, OutputIterator dest) {
OutputIterator c_move(C&& src, OutputIterator dest) {
return std::move(container_algorithm_internal::c_begin(src),
container_algorithm_internal::c_end(src), dest);
}
......@@ -635,7 +647,7 @@ container_algorithm_internal::ContainerIter<C> c_generate_n(C& c, Size n,
// Note: `c_xx()` <algorithm> container versions for `remove()`, `remove_if()`,
// and `unique()` are omitted, because it's not clear whether or not such
// functions should call erase their supplied sequences afterwards. Either
// functions should call erase on their supplied sequences afterwards. Either
// behavior would be surprising for a different set of users.
//
......@@ -1155,7 +1167,13 @@ bool c_includes(const C1& c1, const C2& c2, Compare&& comp) {
// Container-based version of the <algorithm> `std::set_union()` function
// to return an iterator containing the union of two containers; duplicate
// values are not copied into the output.
template <typename C1, typename C2, typename OutputIterator>
template <typename C1, typename C2, typename OutputIterator,
typename = typename std::enable_if<
!container_algorithm_internal::IsUnorderedContainer<C1>::value,
void>::type,
typename = typename std::enable_if<
!container_algorithm_internal::IsUnorderedContainer<C2>::value,
void>::type>
OutputIterator c_set_union(const C1& c1, const C2& c2, OutputIterator output) {
return std::set_union(container_algorithm_internal::c_begin(c1),
container_algorithm_internal::c_end(c1),
......@@ -1165,7 +1183,13 @@ OutputIterator c_set_union(const C1& c1, const C2& c2, OutputIterator output) {
// Overload of c_set_union() for performing a merge using a `comp` other than
// `operator<`.
template <typename C1, typename C2, typename OutputIterator, typename Compare>
template <typename C1, typename C2, typename OutputIterator, typename Compare,
typename = typename std::enable_if<
!container_algorithm_internal::IsUnorderedContainer<C1>::value,
void>::type,
typename = typename std::enable_if<
!container_algorithm_internal::IsUnorderedContainer<C2>::value,
void>::type>
OutputIterator c_set_union(const C1& c1, const C2& c2, OutputIterator output,
Compare&& comp) {
return std::set_union(container_algorithm_internal::c_begin(c1),
......@@ -1179,7 +1203,13 @@ OutputIterator c_set_union(const C1& c1, const C2& c2, OutputIterator output,
//
// Container-based version of the <algorithm> `std::set_intersection()` function
// to return an iterator containing the intersection of two containers.
template <typename C1, typename C2, typename OutputIterator>
template <typename C1, typename C2, typename OutputIterator,
typename = typename std::enable_if<
!container_algorithm_internal::IsUnorderedContainer<C1>::value,
void>::type,
typename = typename std::enable_if<
!container_algorithm_internal::IsUnorderedContainer<C2>::value,
void>::type>
OutputIterator c_set_intersection(const C1& c1, const C2& c2,
OutputIterator output) {
return std::set_intersection(container_algorithm_internal::c_begin(c1),
......@@ -1190,7 +1220,13 @@ OutputIterator c_set_intersection(const C1& c1, const C2& c2,
// Overload of c_set_intersection() for performing a merge using a `comp` other
// than `operator<`.
template <typename C1, typename C2, typename OutputIterator, typename Compare>
template <typename C1, typename C2, typename OutputIterator, typename Compare,
typename = typename std::enable_if<
!container_algorithm_internal::IsUnorderedContainer<C1>::value,
void>::type,
typename = typename std::enable_if<
!container_algorithm_internal::IsUnorderedContainer<C2>::value,
void>::type>
OutputIterator c_set_intersection(const C1& c1, const C2& c2,
OutputIterator output, Compare&& comp) {
return std::set_intersection(container_algorithm_internal::c_begin(c1),
......@@ -1205,7 +1241,13 @@ OutputIterator c_set_intersection(const C1& c1, const C2& c2,
// Container-based version of the <algorithm> `std::set_difference()` function
// to return an iterator containing elements present in the first container but
// not in the second.
template <typename C1, typename C2, typename OutputIterator>
template <typename C1, typename C2, typename OutputIterator,
typename = typename std::enable_if<
!container_algorithm_internal::IsUnorderedContainer<C1>::value,
void>::type,
typename = typename std::enable_if<
!container_algorithm_internal::IsUnorderedContainer<C2>::value,
void>::type>
OutputIterator c_set_difference(const C1& c1, const C2& c2,
OutputIterator output) {
return std::set_difference(container_algorithm_internal::c_begin(c1),
......@@ -1216,7 +1258,13 @@ OutputIterator c_set_difference(const C1& c1, const C2& c2,
// Overload of c_set_difference() for performing a merge using a `comp` other
// than `operator<`.
template <typename C1, typename C2, typename OutputIterator, typename Compare>
template <typename C1, typename C2, typename OutputIterator, typename Compare,
typename = typename std::enable_if<
!container_algorithm_internal::IsUnorderedContainer<C1>::value,
void>::type,
typename = typename std::enable_if<
!container_algorithm_internal::IsUnorderedContainer<C2>::value,
void>::type>
OutputIterator c_set_difference(const C1& c1, const C2& c2,
OutputIterator output, Compare&& comp) {
return std::set_difference(container_algorithm_internal::c_begin(c1),
......@@ -1231,7 +1279,13 @@ OutputIterator c_set_difference(const C1& c1, const C2& c2,
// Container-based version of the <algorithm> `std::set_symmetric_difference()`
// function to return an iterator containing elements present in either one
// container or the other, but not both.
template <typename C1, typename C2, typename OutputIterator>
template <typename C1, typename C2, typename OutputIterator,
typename = typename std::enable_if<
!container_algorithm_internal::IsUnorderedContainer<C1>::value,
void>::type,
typename = typename std::enable_if<
!container_algorithm_internal::IsUnorderedContainer<C2>::value,
void>::type>
OutputIterator c_set_symmetric_difference(const C1& c1, const C2& c2,
OutputIterator output) {
return std::set_symmetric_difference(
......@@ -1243,7 +1297,13 @@ OutputIterator c_set_symmetric_difference(const C1& c1, const C2& c2,
// Overload of c_set_symmetric_difference() for performing a merge using a
// `comp` other than `operator<`.
template <typename C1, typename C2, typename OutputIterator, typename Compare>
template <typename C1, typename C2, typename OutputIterator, typename Compare,
typename = typename std::enable_if<
!container_algorithm_internal::IsUnorderedContainer<C1>::value,
void>::type,
typename = typename std::enable_if<
!container_algorithm_internal::IsUnorderedContainer<C2>::value,
void>::type>
OutputIterator c_set_symmetric_difference(const C1& c1, const C2& c2,
OutputIterator output,
Compare&& comp) {
......@@ -1638,7 +1698,7 @@ OutputIt c_partial_sum(const InputSequence& input, OutputIt output_first,
output_first, std::forward<BinaryOp>(op));
}
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
#endif // ABSL_ALGORITHM_CONTAINER_H_
......@@ -636,6 +636,21 @@ TEST(MutatingTest, Move) {
Pointee(5)));
}
TEST(MutatingTest, MoveWithRvalue) {
auto MakeRValueSrc = [] {
std::vector<std::unique_ptr<int>> src;
src.emplace_back(absl::make_unique<int>(1));
src.emplace_back(absl::make_unique<int>(2));
src.emplace_back(absl::make_unique<int>(3));
return src;
};
std::vector<std::unique_ptr<int>> dest = MakeRValueSrc();
absl::c_move(MakeRValueSrc(), std::back_inserter(dest));
EXPECT_THAT(dest, ElementsAre(Pointee(1), Pointee(2), Pointee(3), Pointee(1),
Pointee(2), Pointee(3)));
}
TEST(MutatingTest, SwapRanges) {
std::vector<int> odds = {2, 4, 6};
std::vector<int> evens = {1, 3, 5};
......
......@@ -19,6 +19,7 @@ load(
"ABSL_DEFAULT_COPTS",
"ABSL_TEST_COPTS",
"ABSL_EXCEPTIONS_FLAG",
"ABSL_EXCEPTIONS_FLAG_LINKOPTS",
)
package(default_visibility = ["//visibility:public"])
......@@ -29,6 +30,7 @@ cc_library(
name = "spinlock_wait",
srcs = [
"internal/spinlock_akaros.inc",
"internal/spinlock_linux.inc",
"internal/spinlock_posix.inc",
"internal/spinlock_wait.cc",
"internal/spinlock_win32.inc",
......@@ -73,7 +75,6 @@ cc_library(
copts = ABSL_DEFAULT_COPTS,
deps = [
":config",
":dynamic_annotations",
],
)
......@@ -106,6 +107,7 @@ cc_library(
"internal/identity.h",
"internal/inline_variable.h",
"internal/invoke.h",
"internal/scheduling_mode.h",
],
copts = ABSL_DEFAULT_COPTS,
visibility = [
......@@ -179,13 +181,13 @@ cc_library(
srcs = ["internal/throw_delegate.cc"],
hdrs = ["internal/throw_delegate.h"],
copts = ABSL_DEFAULT_COPTS + ABSL_EXCEPTIONS_FLAG,
linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
visibility = [
"//absl:__subpackages__",
],
deps = [
":base",
":config",
":core_headers",
],
)
......@@ -193,6 +195,7 @@ cc_test(
name = "throw_delegate_test",
srcs = ["throw_delegate_test.cc"],
copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
deps = [
":throw_delegate",
"@com_google_googletest//:gtest_main",
......@@ -225,6 +228,7 @@ cc_library(
srcs = ["internal/exception_safety_testing.cc"],
hdrs = ["internal/exception_safety_testing.h"],
copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
deps = [
":base",
":config",
......@@ -232,7 +236,7 @@ cc_library(
"//absl/memory",
"//absl/meta:type_traits",
"//absl/strings",
"//absl/types:optional",
"//absl/utility",
"@com_google_googletest//:gtest",
],
)
......@@ -241,6 +245,7 @@ cc_test(
name = "exception_safety_testing_test",
srcs = ["exception_safety_testing_test.cc"],
copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
deps = [
":exception_safety_testing",
"//absl/memory",
......@@ -299,6 +304,7 @@ cc_test(
size = "medium",
srcs = ["spinlock_test_common.cc"],
copts = ABSL_TEST_COPTS,
tags = ["no_test_wasm"],
deps = [
":base",
":core_headers",
......@@ -309,6 +315,33 @@ cc_test(
)
cc_library(
name = "spinlock_benchmark_common",
testonly = 1,
srcs = ["internal/spinlock_benchmark.cc"],
copts = ABSL_DEFAULT_COPTS,
visibility = [
"//absl/base:__pkg__",
],
deps = [
":base",
":base_internal",
"//absl/synchronization",
"@com_github_google_benchmark//:benchmark_main",
],
alwayslink = 1,
)
cc_binary(
name = "spinlock_benchmark",
testonly = 1,
copts = ABSL_DEFAULT_COPTS,
visibility = ["//visibility:private"],
deps = [
":spinlock_benchmark_common",
],
)
cc_library(
name = "endian",
hdrs = [
"internal/endian.h",
......@@ -337,6 +370,9 @@ cc_test(
name = "config_test",
srcs = ["config_test.cc"],
copts = ABSL_TEST_COPTS,
tags = [
"no_test_wasm",
],
deps = [
":config",
"//absl/synchronization:thread_pool",
......@@ -348,6 +384,9 @@ cc_test(
name = "call_once_test",
srcs = ["call_once_test.cc"],
copts = ABSL_TEST_COPTS,
tags = [
"no_test_wasm",
],
deps = [
":base",
":core_headers",
......@@ -362,6 +401,7 @@ cc_test(
copts = ABSL_TEST_COPTS,
deps = [
":base",
"//absl/strings",
"@com_google_googletest//:gtest_main",
],
)
......@@ -387,6 +427,7 @@ cc_test(
"//absl:windows": [],
"//conditions:default": ["-pthread"],
}),
tags = ["no_test_ios_x86_64"],
deps = [":malloc_internal"],
)
......@@ -399,6 +440,9 @@ cc_test(
"//absl:windows": [],
"//conditions:default": ["-pthread"],
}),
tags = [
"no_test_wasm",
],
deps = [
":base",
":core_headers",
......@@ -419,3 +463,23 @@ cc_test(
"@com_github_google_benchmark//:benchmark_main",
],
)
cc_library(
name = "bits",
hdrs = ["internal/bits.h"],
visibility = [
"//absl:__subpackages__",
],
deps = [":core_headers"],
)
cc_test(
name = "bits_test",
size = "small",
srcs = ["internal/bits_test.cc"],
copts = ABSL_TEST_COPTS,
deps = [
":bits",
"@com_google_googletest//:gtest_main",
],
)
......@@ -100,7 +100,7 @@
// ABSL_PRINTF_ATTRIBUTE
// ABSL_SCANF_ATTRIBUTE
//
// Tells the compiler to perform `printf` format std::string checking if the
// Tells the compiler to perform `printf` format string checking if the
// compiler supports it; see the 'format' attribute in
// <http://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html>.
//
......@@ -155,7 +155,12 @@
// ABSL_ATTRIBUTE_WEAK
//
// Tags a function as weak for the purposes of compilation and linking.
#if ABSL_HAVE_ATTRIBUTE(weak) || (defined(__GNUC__) && !defined(__clang__))
// Weak attributes currently do not work properly in LLVM's Windows backend,
// so disable them there. See https://bugs.llvm.org/show_bug.cgi?id=37598
// for futher information.
#if (ABSL_HAVE_ATTRIBUTE(weak) || \
(defined(__GNUC__) && !defined(__clang__))) && \
!(defined(__llvm__) && defined(_WIN32))
#undef ABSL_ATTRIBUTE_WEAK
#define ABSL_ATTRIBUTE_WEAK __attribute__((weak))
#define ABSL_HAVE_ATTRIBUTE_WEAK 1
......@@ -296,13 +301,13 @@
// ABSL_HAVE_ATTRIBUTE_SECTION
//
// Indicates whether labeled sections are supported. Labeled sections are not
// supported on Darwin/iOS.
// Indicates whether labeled sections are supported. Weak symbol support is
// a prerequisite. Labeled sections are not supported on Darwin/iOS.
#ifdef ABSL_HAVE_ATTRIBUTE_SECTION
#error ABSL_HAVE_ATTRIBUTE_SECTION cannot be directly set
#elif (ABSL_HAVE_ATTRIBUTE(section) || \
(defined(__GNUC__) && !defined(__clang__))) && \
!defined(__APPLE__)
!defined(__APPLE__) && ABSL_HAVE_ATTRIBUTE_WEAK
#define ABSL_HAVE_ATTRIBUTE_SECTION 1
// ABSL_ATTRIBUTE_SECTION
......@@ -397,17 +402,28 @@
// ABSL_MUST_USE_RESULT
//
// Tells the compiler to warn about unused return values for functions declared
// with this macro. The macro must appear as the very first part of a function
// declaration or definition:
// Tells the compiler to warn about unused results.
//
// Example:
// When annotating a function, it must appear as the first part of the
// declaration or definition. The compiler will warn if the return value from
// such a function is unused:
//
// ABSL_MUST_USE_RESULT Sprocket* AllocateSprocket();
// AllocateSprocket(); // Triggers a warning.
//
// When annotating a class, it is equivalent to annotating every function which
// returns an instance.
//
// class ABSL_MUST_USE_RESULT Sprocket {};
// Sprocket(); // Triggers a warning.
//
// Sprocket MakeSprocket();
// MakeSprocket(); // Triggers a warning.
//
// Note that references and pointers are not instances:
//
// This placement has the broadest compatibility with GCC, Clang, and MSVC, with
// both defs and decls, and with GCC-style attributes, MSVC declspec, C++11
// and C++17 attributes.
// Sprocket* SprocketPointer();
// SprocketPointer(); // Does *not* trigger a warning.
//
// ABSL_MUST_USE_RESULT allows using cast-to-void to suppress the unused result
// warning. For that, warn_unused_result is used only for clang but not for gcc.
......@@ -494,14 +510,27 @@
#define ABSL_XRAY_LOG_ARGS(N)
#endif
// ABSL_ATTRIBUTE_REINITIALIZES
//
// Indicates that a member function reinitializes the entire object to a known
// state, independent of the previous state of the object.
//
// The clang-tidy check bugprone-use-after-move allows member functions marked
// with this attribute to be called on objects that have been moved from;
// without the attribute, this would result in a use-after-move warning.
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::reinitializes)
#define ABSL_ATTRIBUTE_REINITIALIZES [[clang::reinitializes]]
#else
#define ABSL_ATTRIBUTE_REINITIALIZES
#endif
// -----------------------------------------------------------------------------
// Variable Attributes
// -----------------------------------------------------------------------------
// ABSL_ATTRIBUTE_UNUSED
//
// Prevents the compiler from complaining about or optimizing away variables
// that appear unused.
// Prevents the compiler from complaining about variables that appear unused.
#if ABSL_HAVE_ATTRIBUTE(unused) || (defined(__GNUC__) && !defined(__clang__))
#undef ABSL_ATTRIBUTE_UNUSED
#define ABSL_ATTRIBUTE_UNUSED __attribute__((__unused__))
......
......@@ -22,7 +22,7 @@
#include "absl/base/macros.h"
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace {
template <int N>
......@@ -105,5 +105,5 @@ TEST(BitCast, Double) {
}
} // namespace
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
......@@ -39,7 +39,7 @@
#include "absl/base/port.h"
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
class once_flag;
......@@ -151,11 +151,7 @@ void CallOnceImpl(std::atomic<uint32_t>* control,
old_control != kOnceRunning &&
old_control != kOnceWaiter &&
old_control != kOnceDone) {
ABSL_RAW_LOG(
FATAL,
"Unexpected value for control word: %lx. Either the control word "
"has non-static storage duration (where GoogleOnceDynamic might "
"be appropriate), or there's been a memory corruption.",
ABSL_RAW_LOG(FATAL, "Unexpected value for control word: 0x%lx",
static_cast<unsigned long>(old_control)); // NOLINT
}
}
......@@ -212,7 +208,7 @@ void call_once(absl::once_flag& flag, Callable&& fn, Args&&... args) {
}
}
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
#endif // ABSL_BASE_CALL_ONCE_H_
......@@ -22,7 +22,7 @@
#include "absl/synchronization/mutex.h"
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace {
absl::once_flag once;
......@@ -100,5 +100,5 @@ TEST(CallOnceTest, ExecutionCount) {
}
} // namespace
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
......@@ -25,12 +25,36 @@
#define ABSL_BASE_CASTS_H_
#include <cstring>
#include <memory>
#include <type_traits>
#include "absl/base/internal/identity.h"
#include "absl/base/macros.h"
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace internal_casts {
// NOTE: Not a fully compliant implementation of `std::is_trivially_copyable`.
// TODO(calabrese) Branch on implementations that directly provide
// `std::is_trivially_copyable`, create a more rigorous workaround, and publicly
// expose in meta/type_traits.
template <class T>
struct is_trivially_copyable
: std::integral_constant<
bool, std::is_destructible<T>::value&& __has_trivial_destructor(T) &&
__has_trivial_copy(T) && __has_trivial_assign(T)> {};
template <class Dest, class Source>
struct is_bitcastable
: std::integral_constant<bool,
sizeof(Dest) == sizeof(Source) &&
is_trivially_copyable<Source>::value &&
is_trivially_copyable<Dest>::value &&
std::is_default_constructible<Dest>::value> {};
} // namespace internal_casts
// implicit_cast()
//
......@@ -82,7 +106,7 @@ inline namespace lts_2018_06_20 {
//
// Such implicit cast chaining may be useful within template logic.
template <typename To>
inline To implicit_cast(typename absl::internal::identity_t<To> to) {
constexpr To implicit_cast(typename absl::internal::identity_t<To> to) {
return to;
}
......@@ -126,7 +150,32 @@ inline To implicit_cast(typename absl::internal::identity_t<To> to) {
// and reading its bits back using a different type. A `bit_cast()` avoids this
// issue by implementing its casts using `memcpy()`, which avoids introducing
// this undefined behavior.
template <typename Dest, typename Source>
//
// NOTE: The requirements here are more strict than the bit_cast of standard
// proposal p0476 due to the need for workarounds and lack of intrinsics.
// Specifically, this implementation also requires `Dest` to be
// default-constructible.
template <
typename Dest, typename Source,
typename std::enable_if<internal_casts::is_bitcastable<Dest, Source>::value,
int>::type = 0>
inline Dest bit_cast(const Source& source) {
Dest dest;
memcpy(static_cast<void*>(std::addressof(dest)),
static_cast<const void*>(std::addressof(source)), sizeof(dest));
return dest;
}
// NOTE: This overload is only picked if the requirements of bit_cast are not
// met. It is therefore UB, but is provided temporarily as previous versions of
// this function template were unchecked. Do not use this in new code.
template <
typename Dest, typename Source,
typename std::enable_if<
!internal_casts::is_bitcastable<Dest, Source>::value, int>::type = 0>
ABSL_DEPRECATED(
"absl::bit_cast type requirements were violated. Update the types being "
"used such that they are the same size and are both TriviallyCopyable.")
inline Dest bit_cast(const Source& source) {
static_assert(sizeof(Dest) == sizeof(Source),
"Source and destination types should have equal sizes.");
......@@ -136,7 +185,7 @@ inline Dest bit_cast(const Source& source) {
return dest;
}
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
#endif // ABSL_BASE_CASTS_H_
......@@ -139,12 +139,18 @@
#ifdef ABSL_HAVE_THREAD_LOCAL
#error ABSL_HAVE_THREAD_LOCAL cannot be directly set
#elif defined(__APPLE__)
// Notes: Xcode's clang did not support `thread_local` until version
// 8, and even then not for all iOS < 9.0. Also, Xcode 9.3 started disallowing
// `thread_local` for 32-bit iOS simulator targeting iOS 9.x.
// `__has_feature` is only supported by Clang so it has be inside
// Notes:
// * Xcode's clang did not support `thread_local` until version 8, and
// even then not for all iOS < 9.0.
// * Xcode 9.3 started disallowing `thread_local` for 32-bit iOS simulator
// targeting iOS 9.x.
// * Xcode 10 moves the deployment target check for iOS < 9.0 to link time
// making __has_feature unreliable there.
//
// Otherwise, `__has_feature` is only supported by Clang so it has be inside
// `defined(__APPLE__)` check.
#if __has_feature(cxx_thread_local)
#if __has_feature(cxx_thread_local) && \
!(TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0)
#define ABSL_HAVE_THREAD_LOCAL 1
#endif
#else // !defined(__APPLE__)
......@@ -199,7 +205,7 @@
#define ABSL_HAVE_INTRINSIC_INT128 1
#elif defined(__CUDACC__)
// __CUDACC_VER__ is a full version number before CUDA 9, and is defined to a
// std::string explaining that it has been removed starting with CUDA 9. We use
// string explaining that it has been removed starting with CUDA 9. We use
// nested #ifs because there is no short-circuiting in the preprocessor.
// NOTE: `__CUDACC__` could be undefined while `__CUDACC_VER__` is defined.
#if __CUDACC_VER__ >= 70000
......@@ -268,7 +274,8 @@
#error ABSL_HAVE_MMAP cannot be directly set
#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
defined(__ros__) || defined(__native_client__) || defined(__asmjs__) || \
defined(__wasm__) || defined(__Fuchsia__)
defined(__wasm__) || defined(__Fuchsia__) || defined(__sun) || \
defined(__ASYLO__)
#define ABSL_HAVE_MMAP 1
#endif
......@@ -322,6 +329,8 @@
#define ABSL_HAVE_ALARM 1
#elif defined(_MSC_VER)
// feature tests for Microsoft's library
#elif defined(__EMSCRIPTEN__)
// emscripten doesn't support signals
#elif defined(__native_client__)
#else
// other standard libraries
......@@ -356,6 +365,18 @@
#error "absl endian detection needs to be set up for your compiler"
#endif
// MacOS 10.13 doesn't let you use <any>, <optional>, or <variant> even though
// the headers exist and are publicly noted to work. See
// https://github.com/abseil/abseil-cpp/issues/207 and
// https://developer.apple.com/documentation/xcode_release_notes/xcode_10_release_notes
#if defined(__APPLE__) && defined(_LIBCPP_VERSION) && \
defined(__MAC_OS_X_VERSION_MIN_REQUIRED__) && \
__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101400
#define ABSL_INTERNAL_MACOS_HAS_CXX_17_TYPES 1
#else
#define ABSL_INTERNAL_MACOS_HAS_CXX_17_TYPES 0
#endif
// ABSL_HAVE_STD_ANY
//
// Checks whether C++17 std::any is available by checking whether <any> exists.
......@@ -364,7 +385,8 @@
#endif
#ifdef __has_include
#if __has_include(<any>) && __cplusplus >= 201703L
#if __has_include(<any>) && __cplusplus >= 201703L && \
ABSL_INTERNAL_MACOS_HAS_CXX_17_TYPES
#define ABSL_HAVE_STD_ANY 1
#endif
#endif
......@@ -377,7 +399,8 @@
#endif
#ifdef __has_include
#if __has_include(<optional>) && __cplusplus >= 201703L
#if __has_include(<optional>) && __cplusplus >= 201703L && \
ABSL_INTERNAL_MACOS_HAS_CXX_17_TYPES
#define ABSL_HAVE_STD_OPTIONAL 1
#endif
#endif
......@@ -390,7 +413,8 @@
#endif
#ifdef __has_include
#if __has_include(<variant>) && __cplusplus >= 201703L
#if __has_include(<variant>) && __cplusplus >= 201703L && \
ABSL_INTERNAL_MACOS_HAS_CXX_17_TYPES
#define ABSL_HAVE_STD_VARIANT 1
#endif
#endif
......@@ -414,14 +438,21 @@
// <string_view>, <variant> is implemented) or higher. Also, `__cplusplus` is
// not correctly set by MSVC, so we use `_MSVC_LANG` to check the language
// version.
// TODO(zhangxy): fix tests before enabling aliasing for `std::any`,
// `std::string_view`.
// TODO(zhangxy): fix tests before enabling aliasing for `std::any`.
#if defined(_MSC_VER) && _MSC_VER >= 1910 && \
((defined(_MSVC_LANG) && _MSVC_LANG > 201402) || __cplusplus > 201402)
// #define ABSL_HAVE_STD_ANY 1
#define ABSL_HAVE_STD_OPTIONAL 1
#define ABSL_HAVE_STD_VARIANT 1
// #define ABSL_HAVE_STD_STRING_VIEW 1
#define ABSL_HAVE_STD_STRING_VIEW 1
#endif
// In debug mode, MSVC 2017's std::variant throws a EXCEPTION_ACCESS_VIOLATION
// SEH exception from emplace for variant<SomeStruct> when constructing the
// struct can throw. This defeats some of variant_test and
// variant_exception_safety_test.
#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_DEBUG)
#define ABSL_INTERNAL_MSVC_2017_DBG_MODE
#endif
#endif // ABSL_BASE_CONFIG_H_
......@@ -20,7 +20,7 @@
#include "gtest/gtest.h"
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace inline_variable_testing_internal {
namespace {
......@@ -60,5 +60,5 @@ TEST(InlineVariableTest, FunPtrType) {
} // namespace
} // namespace inline_variable_testing_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
......@@ -15,7 +15,7 @@
#include "absl/base/internal/inline_variable_testing.h"
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace inline_variable_testing_internal {
const Foo& get_foo_a() { return inline_variable_foo; }
......@@ -23,5 +23,5 @@ const Foo& get_foo_a() { return inline_variable_foo; }
const int& get_int_a() { return inline_variable_int; }
} // namespace inline_variable_testing_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
......@@ -15,7 +15,7 @@
#include "absl/base/internal/inline_variable_testing.h"
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace inline_variable_testing_internal {
const Foo& get_foo_b() { return inline_variable_foo; }
......@@ -23,5 +23,5 @@ const Foo& get_foo_b() { return inline_variable_foo; }
const int& get_int_b() { return inline_variable_int; }
} // namespace inline_variable_testing_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
......@@ -28,7 +28,7 @@
#endif
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace base_internal {
template <typename T>
......@@ -161,7 +161,7 @@ class AtomicHook<ReturnType (*)(Args...)> {
#undef ABSL_HAVE_WORKING_ATOMIC_POINTER
} // namespace base_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
#endif // ABSL_BASE_INTERNAL_ATOMIC_HOOK_H_
// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_BASE_INTERNAL_BITS_H_
#define ABSL_BASE_INTERNAL_BITS_H_
// This file contains bitwise ops which are implementation details of various
// absl libraries.
#include <cstdint>
// Clang on Windows has __builtin_clzll; otherwise we need to use the
// windows intrinsic functions.
#if defined(_MSC_VER)
#include <intrin.h>
#if defined(_M_X64)
#pragma intrinsic(_BitScanReverse64)
#pragma intrinsic(_BitScanForward64)
#endif
#pragma intrinsic(_BitScanReverse)
#pragma intrinsic(_BitScanForward)
#endif
#include "absl/base/attributes.h"
#if defined(_MSC_VER)
// We can achieve something similar to attribute((always_inline)) with MSVC by
// using the __forceinline keyword, however this is not perfect. MSVC is
// much less aggressive about inlining, and even with the __forceinline keyword.
#define ABSL_BASE_INTERNAL_FORCEINLINE __forceinline
#else
// Use default attribute inline.
#define ABSL_BASE_INTERNAL_FORCEINLINE inline ABSL_ATTRIBUTE_ALWAYS_INLINE
#endif
namespace absl {
inline namespace lts_2018_12_18 {
namespace base_internal {
ABSL_BASE_INTERNAL_FORCEINLINE int CountLeadingZeros64Slow(uint64_t n) {
int zeroes = 60;
if (n >> 32) zeroes -= 32, n >>= 32;
if (n >> 16) zeroes -= 16, n >>= 16;
if (n >> 8) zeroes -= 8, n >>= 8;
if (n >> 4) zeroes -= 4, n >>= 4;
return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[n] + zeroes;
}
ABSL_BASE_INTERNAL_FORCEINLINE int CountLeadingZeros64(uint64_t n) {
#if defined(_MSC_VER) && defined(_M_X64)
// MSVC does not have __buitin_clzll. Use _BitScanReverse64.
unsigned long result = 0; // NOLINT(runtime/int)
if (_BitScanReverse64(&result, n)) {
return 63 - result;
}
return 64;
#elif defined(_MSC_VER)
// MSVC does not have __buitin_clzll. Compose two calls to _BitScanReverse
unsigned long result = 0; // NOLINT(runtime/int)
if ((n >> 32) && _BitScanReverse(&result, n >> 32)) {
return 31 - result;
}
if (_BitScanReverse(&result, n)) {
return 63 - result;
}
return 64;
#elif defined(__GNUC__)
// Use __builtin_clzll, which uses the following instructions:
// x86: bsr
// ARM64: clz
// PPC: cntlzd
static_assert(sizeof(unsigned long long) == sizeof(n), // NOLINT(runtime/int)
"__builtin_clzll does not take 64-bit arg");
// Handle 0 as a special case because __builtin_clzll(0) is undefined.
if (n == 0) {
return 64;
}
return __builtin_clzll(n);
#else
return CountLeadingZeros64Slow(n);
#endif
}
ABSL_BASE_INTERNAL_FORCEINLINE int CountLeadingZeros32Slow(uint64_t n) {
int zeroes = 28;
if (n >> 16) zeroes -= 16, n >>= 16;
if (n >> 8) zeroes -= 8, n >>= 8;
if (n >> 4) zeroes -= 4, n >>= 4;
return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[n] + zeroes;
}
ABSL_BASE_INTERNAL_FORCEINLINE int CountLeadingZeros32(uint32_t n) {
#if defined(_MSC_VER)
unsigned long result = 0; // NOLINT(runtime/int)
if (_BitScanReverse(&result, n)) {
return 31 - result;
}
return 32;
#elif defined(__GNUC__)
// Use __builtin_clz, which uses the following instructions:
// x86: bsr
// ARM64: clz
// PPC: cntlzd
static_assert(sizeof(int) == sizeof(n),
"__builtin_clz does not take 32-bit arg");
// Handle 0 as a special case because __builtin_clz(0) is undefined.
if (n == 0) {
return 32;
}
return __builtin_clz(n);
#else
return CountLeadingZeros32Slow(n);
#endif
}
ABSL_BASE_INTERNAL_FORCEINLINE int CountTrailingZerosNonZero64Slow(uint64_t n) {
int c = 63;
n &= ~n + 1;
if (n & 0x00000000FFFFFFFF) c -= 32;
if (n & 0x0000FFFF0000FFFF) c -= 16;
if (n & 0x00FF00FF00FF00FF) c -= 8;
if (n & 0x0F0F0F0F0F0F0F0F) c -= 4;
if (n & 0x3333333333333333) c -= 2;
if (n & 0x5555555555555555) c -= 1;
return c;
}
ABSL_BASE_INTERNAL_FORCEINLINE int CountTrailingZerosNonZero64(uint64_t n) {
#if defined(_MSC_VER) && defined(_M_X64)
unsigned long result = 0; // NOLINT(runtime/int)
_BitScanForward64(&result, n);
return result;
#elif defined(_MSC_VER)
unsigned long result = 0; // NOLINT(runtime/int)
if (static_cast<uint32_t>(n) == 0) {
_BitScanForward(&result, n >> 32);
return result + 32;
}
_BitScanForward(&result, n);
return result;
#elif defined(__GNUC__)
static_assert(sizeof(unsigned long long) == sizeof(n), // NOLINT(runtime/int)
"__builtin_ctzll does not take 64-bit arg");
return __builtin_ctzll(n);
#else
return CountTrailingZerosNonZero64Slow(n);
#endif
}
ABSL_BASE_INTERNAL_FORCEINLINE int CountTrailingZerosNonZero32Slow(uint32_t n) {
int c = 31;
n &= ~n + 1;
if (n & 0x0000FFFF) c -= 16;
if (n & 0x00FF00FF) c -= 8;
if (n & 0x0F0F0F0F) c -= 4;
if (n & 0x33333333) c -= 2;
if (n & 0x55555555) c -= 1;
return c;
}
ABSL_BASE_INTERNAL_FORCEINLINE int CountTrailingZerosNonZero32(uint32_t n) {
#if defined(_MSC_VER)
unsigned long result = 0; // NOLINT(runtime/int)
_BitScanForward(&result, n);
return result;
#elif defined(__GNUC__)
static_assert(sizeof(int) == sizeof(n),
"__builtin_ctz does not take 32-bit arg");
return __builtin_ctz(n);
#else
return CountTrailingZerosNonZero32Slow(n);
#endif
}
#undef ABSL_BASE_INTERNAL_FORCEINLINE
} // namespace base_internal
} // inline namespace lts_2018_12_18
} // namespace absl
#endif // ABSL_BASE_INTERNAL_BITS_H_
// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "absl/base/internal/bits.h"
#include "gtest/gtest.h"
namespace {
int CLZ64(uint64_t n) {
int fast = absl::base_internal::CountLeadingZeros64(n);
int slow = absl::base_internal::CountLeadingZeros64Slow(n);
EXPECT_EQ(fast, slow) << n;
return fast;
}
TEST(BitsTest, CountLeadingZeros64) {
EXPECT_EQ(64, CLZ64(uint64_t{}));
EXPECT_EQ(0, CLZ64(~uint64_t{}));
for (int index = 0; index < 64; index++) {
uint64_t x = static_cast<uint64_t>(1) << index;
const auto cnt = 63 - index;
ASSERT_EQ(cnt, CLZ64(x)) << index;
ASSERT_EQ(cnt, CLZ64(x + x - 1)) << index;
}
}
int CLZ32(uint32_t n) {
int fast = absl::base_internal::CountLeadingZeros32(n);
int slow = absl::base_internal::CountLeadingZeros32Slow(n);
EXPECT_EQ(fast, slow) << n;
return fast;
}
TEST(BitsTest, CountLeadingZeros32) {
EXPECT_EQ(32, CLZ32(uint32_t{}));
EXPECT_EQ(0, CLZ32(~uint32_t{}));
for (int index = 0; index < 32; index++) {
uint32_t x = static_cast<uint32_t>(1) << index;
const auto cnt = 31 - index;
ASSERT_EQ(cnt, CLZ32(x)) << index;
ASSERT_EQ(cnt, CLZ32(x + x - 1)) << index;
ASSERT_EQ(CLZ64(x), CLZ32(x) + 32);
}
}
int CTZ64(uint64_t n) {
int fast = absl::base_internal::CountTrailingZerosNonZero64(n);
int slow = absl::base_internal::CountTrailingZerosNonZero64Slow(n);
EXPECT_EQ(fast, slow) << n;
return fast;
}
TEST(BitsTest, CountTrailingZerosNonZero64) {
EXPECT_EQ(0, CTZ64(~uint64_t{}));
for (int index = 0; index < 64; index++) {
uint64_t x = static_cast<uint64_t>(1) << index;
const auto cnt = index;
ASSERT_EQ(cnt, CTZ64(x)) << index;
ASSERT_EQ(cnt, CTZ64(~(x - 1))) << index;
}
}
int CTZ32(uint32_t n) {
int fast = absl::base_internal::CountTrailingZerosNonZero32(n);
int slow = absl::base_internal::CountTrailingZerosNonZero32Slow(n);
EXPECT_EQ(fast, slow) << n;
return fast;
}
TEST(BitsTest, CountTrailingZerosNonZero32) {
EXPECT_EQ(0, CTZ32(~uint32_t{}));
for (int index = 0; index < 32; index++) {
uint32_t x = static_cast<uint32_t>(1) << index;
const auto cnt = index;
ASSERT_EQ(cnt, CTZ32(x)) << index;
ASSERT_EQ(cnt, CTZ32(~(x - 1))) << index;
}
}
} // namespace
......@@ -27,7 +27,7 @@
#include "absl/base/internal/unscaledcycleclock.h"
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace base_internal {
#if ABSL_USE_UNSCALED_CYCLECLOCK
......@@ -79,5 +79,5 @@ double CycleClock::Frequency() {
#endif
} // namespace base_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
......@@ -46,7 +46,7 @@
#include <cstdint>
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace base_internal {
// -----------------------------------------------------------------------------
......@@ -73,7 +73,7 @@ class CycleClock {
};
} // namespace base_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
#endif // ABSL_BASE_INTERNAL_CYCLECLOCK_H_
......@@ -62,7 +62,7 @@ extern "C" void* __mmap2(void*, size_t, int, int, int, size_t);
#endif // __BIONIC__
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace base_internal {
// Platform specific logic extracted from
......@@ -76,7 +76,11 @@ inline void* DirectMmap(void* start, size_t length, int prot, int flags, int fd,
// On these architectures, implement mmap with mmap2.
static int pagesize = 0;
if (pagesize == 0) {
#if defined(__wasm__) || defined(__asmjs__)
pagesize = getpagesize();
#else
pagesize = sysconf(_SC_PAGESIZE);
#endif
}
if (offset < 0 || offset % pagesize != 0) {
errno = EINVAL;
......@@ -93,11 +97,13 @@ inline void* DirectMmap(void* start, size_t length, int prot, int flags, int fd,
#endif
#elif defined(__s390x__)
// On s390x, mmap() arguments are passed in memory.
uint32_t buf[6] = {
reinterpret_cast<uint32_t>(start), static_cast<uint32_t>(length),
static_cast<uint32_t>(prot), static_cast<uint32_t>(flags),
static_cast<uint32_t>(fd), static_cast<uint32_t>(offset)};
return reintrepret_cast<void*>(syscall(SYS_mmap, buf));
unsigned long buf[6] = {reinterpret_cast<unsigned long>(start), // NOLINT
static_cast<unsigned long>(length), // NOLINT
static_cast<unsigned long>(prot), // NOLINT
static_cast<unsigned long>(flags), // NOLINT
static_cast<unsigned long>(fd), // NOLINT
static_cast<unsigned long>(offset)}; // NOLINT
return reinterpret_cast<void*>(syscall(SYS_mmap, buf));
#elif defined(__x86_64__)
// The x32 ABI has 32 bit longs, but the syscall interface is 64 bit.
// We need to explicitly cast to an unsigned 64 bit type to avoid implicit
......@@ -123,7 +129,7 @@ inline int DirectMunmap(void* start, size_t length) {
}
} // namespace base_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
#else // !__linux__
......@@ -132,7 +138,7 @@ inline int DirectMunmap(void* start, size_t length) {
// actual mmap()/munmap() methods.
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace base_internal {
inline void* DirectMmap(void* start, size_t length, int prot, int flags, int fd,
......@@ -145,7 +151,7 @@ inline int DirectMunmap(void* start, size_t length) {
}
} // namespace base_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
#endif // __linux__
......
......@@ -34,7 +34,7 @@
#include "absl/base/port.h"
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
// Use compiler byte-swapping intrinsics if they are available. 32-bit
// and 64-bit versions are available in Clang and GCC as of GCC 4.3.0.
......@@ -83,14 +83,14 @@ inline uint64_t gbswap_64(uint64_t host_int) {
#elif defined(__GLIBC__)
return bswap_64(host_int);
#else
return (((x & uint64_t{(0xFF}) << 56) |
((x & uint64_t{(0xFF00}) << 40) |
((x & uint64_t{(0xFF0000}) << 24) |
((x & uint64_t{(0xFF000000}) << 8) |
((x & uint64_t{(0xFF00000000}) >> 8) |
((x & uint64_t{(0xFF0000000000}) >> 24) |
((x & uint64_t{(0xFF000000000000}) >> 40) |
((x & uint64_t{(0xFF00000000000000}) >> 56));
return (((host_int & uint64_t{0xFF}) << 56) |
((host_int & uint64_t{0xFF00}) << 40) |
((host_int & uint64_t{0xFF0000}) << 24) |
((host_int & uint64_t{0xFF000000}) << 8) |
((host_int & uint64_t{0xFF00000000}) >> 8) |
((host_int & uint64_t{0xFF0000000000}) >> 24) |
((host_int & uint64_t{0xFF000000000000}) >> 40) |
((host_int & uint64_t{0xFF00000000000000}) >> 56));
#endif // bswap_64
}
......@@ -98,8 +98,10 @@ inline uint32_t gbswap_32(uint32_t host_int) {
#if defined(__GLIBC__)
return bswap_32(host_int);
#else
return (((x & 0xFF) << 24) | ((x & 0xFF00) << 8) | ((x & 0xFF0000) >> 8) |
((x & 0xFF000000) >> 24));
return (((host_int & uint32_t{0xFF}) << 24) |
((host_int & uint32_t{0xFF00}) << 8) |
((host_int & uint32_t{0xFF0000}) >> 8) |
((host_int & uint32_t{0xFF000000}) >> 24));
#endif
}
......@@ -107,7 +109,8 @@ inline uint16_t gbswap_16(uint16_t host_int) {
#if defined(__GLIBC__)
return bswap_16(host_int);
#else
return uint16_t{((x & 0xFF) << 8) | ((x & 0xFF00) >> 8)};
return (((host_int & uint16_t{0xFF}) << 8) |
((host_int & uint16_t{0xFF00}) >> 8));
#endif
}
......@@ -265,7 +268,7 @@ inline void Store64(void *p, uint64_t v) {
} // namespace big_endian
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
#endif // ABSL_BASE_INTERNAL_ENDIAN_H_
......@@ -24,7 +24,7 @@
#include "absl/base/config.h"
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace {
const uint64_t kInitialNumber{0x0123456789abcdef};
......@@ -34,32 +34,16 @@ const uint16_t k16Value{0x0123};
const int kNumValuesToTest = 1000000;
const int kRandomSeed = 12345;
#ifdef ABSL_IS_BIG_ENDIAN
#if defined(ABSL_IS_BIG_ENDIAN)
const uint64_t kInitialInNetworkOrder{kInitialNumber};
const uint64_t k64ValueLE{0xefcdab8967452301};
const uint32_t k32ValueLE{0x67452301};
const uint16_t k16ValueLE{0x2301};
const uint8_t k8ValueLE{k8Value};
const uint64_t k64IValueLE{0xefcdab89674523a1};
const uint32_t k32IValueLE{0x67452391};
const uint16_t k16IValueLE{0x85ff};
const uint8_t k8IValueLE{0xff};
const uint64_t kDoubleValueLE{0x6e861bf0f9210940};
const uint32_t kFloatValueLE{0xd00f4940};
const uint8_t kBoolValueLE{0x1};
const uint64_t k64ValueBE{kInitialNumber};
const uint32_t k32ValueBE{k32Value};
const uint16_t k16ValueBE{k16Value};
const uint8_t k8ValueBE{k8Value};
const uint64_t k64IValueBE{0xa123456789abcdef};
const uint32_t k32IValueBE{0x91234567};
const uint16_t k16IValueBE{0xff85};
const uint8_t k8IValueBE{0xff};
const uint64_t kDoubleValueBE{0x400921f9f01b866e};
const uint32_t kFloatValueBE{0x40490fd0};
const uint8_t kBoolValueBE{0x1};
#elif defined ABSL_IS_LITTLE_ENDIAN
#elif defined(ABSL_IS_LITTLE_ENDIAN)
const uint64_t kInitialInNetworkOrder{0xefcdab8967452301};
const uint64_t k64ValueLE{kInitialNumber};
const uint32_t k32ValueLE{k32Value};
......@@ -277,5 +261,5 @@ TEST(EndianessTest, big_endian) {
}
} // namespace
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
......@@ -23,6 +23,10 @@ exceptions_internal::NoThrowTag nothrow_ctor;
exceptions_internal::StrongGuaranteeTagType strong_guarantee;
exceptions_internal::ExceptionSafetyTestBuilder<> MakeExceptionSafetyTester() {
return {};
}
namespace exceptions_internal {
int countdown = -1;
......
......@@ -35,7 +35,7 @@
EXPECT_DEATH(expr, ".*")
#else
#define ABSL_BASE_INTERNAL_EXPECT_FAIL(expr, exception_t, text) \
EXPECT_DEATH(expr, text)
EXPECT_DEATH_IF_SUPPORTED(expr, text)
#endif
......
......@@ -18,7 +18,7 @@
#include <cstdint>
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace base_internal {
// Arbitrary value with high bits set. Xor'ing with it is unlikely
......@@ -43,7 +43,7 @@ inline T* UnhidePtr(uintptr_t hidden) {
}
} // namespace base_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
#endif // ABSL_BASE_INTERNAL_HIDE_PTR_H_
......@@ -17,7 +17,7 @@
#define ABSL_BASE_INTERNAL_IDENTITY_H_
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace internal {
template <typename T>
......@@ -29,7 +29,7 @@ template <typename T>
using identity_t = typename identity<T>::type;
} // namespace internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
#endif // ABSL_BASE_INTERNAL_IDENTITY_H_
......@@ -18,7 +18,7 @@
#include "absl/base/internal/inline_variable.h"
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace inline_variable_testing_internal {
struct Foo {
......@@ -40,7 +40,7 @@ const int& get_int_a();
const int& get_int_b();
} // namespace inline_variable_testing_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
#endif // ABSL_BASE_INLINE_VARIABLE_TESTING_H_
......@@ -43,7 +43,7 @@
// top of this file for the API documentation.
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace base_internal {
// The five classes below each implement one of the clauses from the definition
......@@ -184,7 +184,7 @@ InvokeT<F, Args...> Invoke(F&& f, Args&&... args) {
std::forward<Args>(args)...);
}
} // namespace base_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
#endif // ABSL_BASE_INTERNAL_INVOKE_H_
......@@ -63,7 +63,7 @@
#endif // __APPLE__
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace base_internal {
// A first-fit allocator with amortized logarithmic free() time.
......@@ -209,7 +209,7 @@ struct LowLevelAlloc::Arena {
int32_t allocation_count GUARDED_BY(mu);
// flags passed to NewArena
const uint32_t flags;
// Result of getpagesize()
// Result of sysconf(_SC_PAGESIZE)
const size_t pagesize;
// Lowest power of two >= max(16, sizeof(AllocList))
const size_t roundup;
......@@ -325,8 +325,10 @@ size_t GetPageSize() {
SYSTEM_INFO system_info;
GetSystemInfo(&system_info);
return std::max(system_info.dwPageSize, system_info.dwAllocationGranularity);
#else
#elif defined(__wasm__) || defined(__asmjs__)
return getpagesize();
#else
return sysconf(_SC_PAGESIZE);
#endif
}
......@@ -402,16 +404,20 @@ bool LowLevelAlloc::DeleteArena(Arena *arena) {
ABSL_RAW_CHECK(munmap_result != 0,
"LowLevelAlloc::DeleteArena: VitualFree failed");
#else
#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING
if ((arena->flags & LowLevelAlloc::kAsyncSignalSafe) == 0) {
munmap_result = munmap(region, size);
} else {
munmap_result = base_internal::DirectMunmap(region, size);
}
#else
munmap_result = munmap(region, size);
#endif // ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING
if (munmap_result != 0) {
ABSL_RAW_LOG(FATAL, "LowLevelAlloc::DeleteArena: munmap failed: %d",
errno);
}
#endif
#endif // _WIN32
}
section.Leave();
arena->~Arena();
......@@ -546,6 +552,7 @@ static void *DoAllocWithArena(size_t request, LowLevelAlloc::Arena *arena) {
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
ABSL_RAW_CHECK(new_pages != nullptr, "VirtualAlloc failed");
#else
#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING
if ((arena->flags & LowLevelAlloc::kAsyncSignalSafe) != 0) {
new_pages = base_internal::DirectMmap(nullptr, new_pages_size,
PROT_WRITE|PROT_READ, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
......@@ -553,10 +560,15 @@ static void *DoAllocWithArena(size_t request, LowLevelAlloc::Arena *arena) {
new_pages = mmap(nullptr, new_pages_size, PROT_WRITE | PROT_READ,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
}
#else
new_pages = mmap(nullptr, new_pages_size, PROT_WRITE | PROT_READ,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
#endif // ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING
if (new_pages == MAP_FAILED) {
ABSL_RAW_LOG(FATAL, "mmap error: %d", errno);
}
#endif
#endif // _WIN32
arena->mu.Lock();
s = reinterpret_cast<AllocList *>(new_pages);
s->header.size = new_pages_size;
......@@ -600,7 +612,7 @@ void *LowLevelAlloc::AllocWithArena(size_t request, Arena *arena) {
}
} // namespace base_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
#endif // ABSL_LOW_LEVEL_ALLOC_MISSING
......@@ -39,10 +39,13 @@
#define ABSL_LOW_LEVEL_ALLOC_MISSING 1
#endif
// Using LowLevelAlloc with kAsyncSignalSafe isn't supported on Windows.
// Using LowLevelAlloc with kAsyncSignalSafe isn't supported on Windows or
// asm.js / WebAssembly.
// See https://kripken.github.io/emscripten-site/docs/porting/pthreads.html
// for more information.
#ifdef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING
#error ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING cannot be directly set
#elif defined(_WIN32)
#elif defined(_WIN32) || defined(__asmjs__) || defined(__wasm__)
#define ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING 1
#endif
......@@ -51,7 +54,7 @@
#include "absl/base/port.h"
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace base_internal {
class LowLevelAlloc {
......@@ -116,6 +119,6 @@ class LowLevelAlloc {
};
} // namespace base_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
#endif // ABSL_BASE_INTERNAL_LOW_LEVEL_ALLOC_H_
......@@ -22,7 +22,7 @@
#include <utility>
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace base_internal {
namespace {
......@@ -149,7 +149,7 @@ static struct BeforeMain {
} // namespace
} // namespace base_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
int main(int argc, char *argv[]) {
......
......@@ -28,7 +28,7 @@ extern "C" bool __google_disable_rescheduling(void);
extern "C" void __google_enable_rescheduling(bool disable_result);
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace base_internal {
class SchedulingHelper; // To allow use of SchedulingGuard.
......@@ -101,6 +101,6 @@ inline void SchedulingGuard::EnableRescheduling(bool /* disable_result */) {
} // namespace base_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
#endif // ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_
......@@ -139,7 +139,7 @@ void RawLogVA(absl::LogSeverity severity, const char* file, int line,
#endif
#ifdef ABSL_MIN_LOG_LEVEL
if (static_cast<int>(severity) < ABSL_MIN_LOG_LEVEL &&
if (severity < static_cast<absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) &&
severity < absl::LogSeverity::kFatal) {
enabled = false;
}
......@@ -181,7 +181,7 @@ void RawLogVA(absl::LogSeverity severity, const char* file, int line,
} // namespace
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace raw_logging_internal {
void SafeWriteToStderr(const char *s, size_t len) {
#if defined(ABSL_HAVE_SYSCALL_WRITE)
......@@ -207,6 +207,15 @@ void RawLog(absl::LogSeverity severity, const char* file, int line,
va_end(ap);
}
// Non-formatting version of RawLog().
//
// TODO(gfalcon): When string_view no longer depends on base, change this
// interface to take its message as a string_view instead.
static void DefaultInternalLog(absl::LogSeverity severity, const char* file,
int line, const std::string& message) {
RawLog(severity, file, line, "%s", message.c_str());
}
bool RawLoggingFullySupported() {
#ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED
return true;
......@@ -215,6 +224,13 @@ bool RawLoggingFullySupported() {
#endif // !ABSL_LOW_LEVEL_WRITE_SUPPORTED
}
ABSL_CONST_INIT absl::base_internal::AtomicHook<InternalLogFunction>
internal_log_function(DefaultInternalLog);
void RegisterInternalLogFunction(InternalLogFunction func) {
internal_log_function.Store(func);
}
} // namespace raw_logging_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
......@@ -19,7 +19,10 @@
#ifndef ABSL_BASE_INTERNAL_RAW_LOGGING_H_
#define ABSL_BASE_INTERNAL_RAW_LOGGING_H_
#include <string>
#include "absl/base/attributes.h"
#include "absl/base/internal/atomic_hook.h"
#include "absl/base/log_severity.h"
#include "absl/base/macros.h"
#include "absl/base/port.h"
......@@ -57,6 +60,34 @@
} \
} while (0)
// ABSL_INTERNAL_LOG and ABSL_INTERNAL_CHECK work like the RAW variants above,
// except that if the richer log library is linked into the binary, we dispatch
// to that instead. This is potentially useful for internal logging and
// assertions, where we are using RAW_LOG neither for its async-signal-safety
// nor for its non-allocating nature, but rather because raw logging has very
// few other dependencies.
//
// The API is a subset of the above: each macro only takes two arguments. Use
// StrCat if you need to build a richer message.
#define ABSL_INTERNAL_LOG(severity, message) \
do { \
constexpr const char* absl_raw_logging_internal_basename = \
::absl::raw_logging_internal::Basename(__FILE__, \
sizeof(__FILE__) - 1); \
::absl::raw_logging_internal::internal_log_function( \
ABSL_RAW_LOGGING_INTERNAL_##severity, \
absl_raw_logging_internal_basename, __LINE__, message); \
} while (0)
#define ABSL_INTERNAL_CHECK(condition, message) \
do { \
if (ABSL_PREDICT_FALSE(!(condition))) { \
std::string death_message = "Check " #condition " failed: "; \
death_message += std::string(message); \
ABSL_INTERNAL_LOG(FATAL, death_message); \
} \
} while (0)
#define ABSL_RAW_LOGGING_INTERNAL_INFO ::absl::LogSeverity::kInfo
#define ABSL_RAW_LOGGING_INTERNAL_WARNING ::absl::LogSeverity::kWarning
#define ABSL_RAW_LOGGING_INTERNAL_ERROR ::absl::LogSeverity::kError
......@@ -65,7 +96,7 @@
::absl::NormalizeLogSeverity(severity)
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace raw_logging_internal {
// Helper function to implement ABSL_RAW_LOG
......@@ -84,7 +115,7 @@ void SafeWriteToStderr(const char *s, size_t len);
// compile-time function to get the "base" filename, that is, the part of
// a filename after the last "/" or "\" path separator. The search starts at
// the end of the std::string; the second parameter is the length of the std::string.
// the end of the string; the second parameter is the length of the string.
constexpr const char* Basename(const char* fname, int offset) {
return offset == 0 || fname[offset - 1] == '/' || fname[offset - 1] == '\\'
? fname + offset
......@@ -132,8 +163,20 @@ using LogPrefixHook = bool (*)(absl::LogSeverity severity, const char* file,
using AbortHook = void (*)(const char* file, int line, const char* buf_start,
const char* prefix_end, const char* buf_end);
// Internal logging function for ABSL_INTERNAL_LOG to dispatch to.
//
// TODO(gfalcon): When string_view no longer depends on base, change this
// interface to take its message as a string_view instead.
using InternalLogFunction = void (*)(absl::LogSeverity severity,
const char* file, int line,
const std::string& message);
extern base_internal::AtomicHook<InternalLogFunction> internal_log_function;
void RegisterInternalLogFunction(InternalLogFunction func);
} // namespace raw_logging_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
#endif // ABSL_BASE_INTERNAL_RAW_LOGGING_H_
......@@ -19,7 +19,7 @@
#define ABSL_BASE_INTERNAL_SCHEDULING_MODE_H_
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace base_internal {
// Used to describe how a thread may be scheduled. Typically associated with
......@@ -50,7 +50,7 @@ enum SchedulingMode {
};
} // namespace base_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
#endif // ABSL_BASE_INTERNAL_SCHEDULING_MODE_H_
......@@ -54,7 +54,7 @@
// holder to acquire the lock. There may be outstanding waiter(s).
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace base_internal {
ABSL_CONST_INIT static base_internal::AtomicHook<void (*)(const void *lock,
......@@ -96,13 +96,9 @@ void SpinLock::InitLinkerInitializedAndCooperative() {
}
// Monitor the lock to see if its value changes within some time period
// (adaptive_spin_count loop iterations). A timestamp indicating
// when the thread initially started waiting for the lock is passed in via
// the initial_wait_timestamp value. The total wait time in cycles for the
// lock is returned in the wait_cycles parameter. The last value read
// from the lock is returned from the method.
uint32_t SpinLock::SpinLoop(int64_t initial_wait_timestamp,
uint32_t *wait_cycles) {
// (adaptive_spin_count loop iterations). The last value read from the lock
// is returned from the method.
uint32_t SpinLock::SpinLoop() {
// We are already in the slow path of SpinLock, initialize the
// adaptive_spin_count here.
ABSL_CONST_INIT static absl::once_flag init_adaptive_spin_count;
......@@ -116,22 +112,21 @@ uint32_t SpinLock::SpinLoop(int64_t initial_wait_timestamp,
do {
lock_value = lockword_.load(std::memory_order_relaxed);
} while ((lock_value & kSpinLockHeld) != 0 && --c > 0);
uint32_t spin_loop_wait_cycles =
EncodeWaitCycles(initial_wait_timestamp, CycleClock::Now());
*wait_cycles = spin_loop_wait_cycles;
return TryLockInternal(lock_value, spin_loop_wait_cycles);
return lock_value;
}
void SpinLock::SlowLock() {
uint32_t lock_value = SpinLoop();
lock_value = TryLockInternal(lock_value, 0);
if ((lock_value & kSpinLockHeld) == 0) {
return;
}
// The lock was not obtained initially, so this thread needs to wait for
// it. Record the current timestamp in the local variable wait_start_time
// so the total wait time can be stored in the lockword once this thread
// obtains the lock.
int64_t wait_start_time = CycleClock::Now();
uint32_t wait_cycles;
uint32_t lock_value = SpinLoop(wait_start_time, &wait_cycles);
uint32_t wait_cycles = 0;
int lock_wait_call_count = 0;
while ((lock_value & kSpinLockHeld) != 0) {
// If the lock is currently held, but not marked as having a sleeper, mark
......@@ -142,7 +137,7 @@ void SpinLock::SlowLock() {
// owner to think it experienced contention.
if (lockword_.compare_exchange_strong(
lock_value, lock_value | kSpinLockSleeper,
std::memory_order_acquire, std::memory_order_relaxed)) {
std::memory_order_relaxed, std::memory_order_relaxed)) {
// Successfully transitioned to kSpinLockSleeper. Pass
// kSpinLockSleeper to the SpinLockWait routine to properly indicate
// the last lock_value observed.
......@@ -171,7 +166,9 @@ void SpinLock::SlowLock() {
ABSL_TSAN_MUTEX_POST_DIVERT(this, 0);
// Spin again after returning from the wait routine to give this thread
// some chance of obtaining the lock.
lock_value = SpinLoop(wait_start_time, &wait_cycles);
lock_value = SpinLoop();
wait_cycles = EncodeWaitCycles(wait_start_time, CycleClock::Now());
lock_value = TryLockInternal(lock_value, wait_cycles);
}
}
......@@ -207,14 +204,20 @@ uint32_t SpinLock::EncodeWaitCycles(int64_t wait_start_time,
(wait_end_time - wait_start_time) >> PROFILE_TIMESTAMP_SHIFT;
// Return a representation of the time spent waiting that can be stored in
// the lock word's upper bits. bit_cast is required as Atomic32 is signed.
const uint32_t clamped = static_cast<uint32_t>(
// the lock word's upper bits.
uint32_t clamped = static_cast<uint32_t>(
std::min(scaled_wait_time, kMaxWaitTime) << LOCKWORD_RESERVED_SHIFT);
// bump up value if necessary to avoid returning kSpinLockSleeper.
const uint32_t after_spinlock_sleeper =
if (clamped == 0) {
return kSpinLockSleeper; // Just wake waiters, but don't record contention.
}
// Bump up value if necessary to avoid returning kSpinLockSleeper.
const uint32_t kMinWaitTime =
kSpinLockSleeper + (1 << LOCKWORD_RESERVED_SHIFT);
return clamped == kSpinLockSleeper ? after_spinlock_sleeper : clamped;
if (clamped == kSpinLockSleeper) {
return kMinWaitTime;
}
return clamped;
}
uint64_t SpinLock::DecodeWaitCycles(uint32_t lock_value) {
......@@ -226,5 +229,5 @@ uint64_t SpinLock::DecodeWaitCycles(uint32_t lock_value) {
}
} // namespace base_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
......@@ -45,7 +45,7 @@
#include "absl/base/thread_annotations.h"
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace base_internal {
class LOCKABLE SpinLock {
......@@ -102,7 +102,7 @@ class LOCKABLE SpinLock {
inline void Unlock() UNLOCK_FUNCTION() {
ABSL_TSAN_MUTEX_PRE_UNLOCK(this, 0);
uint32_t lock_value = lockword_.load(std::memory_order_relaxed);
lockword_.store(lock_value & kSpinLockCooperative,
lock_value = lockword_.exchange(lock_value & kSpinLockCooperative,
std::memory_order_release);
if ((lock_value & kSpinLockDisabledScheduling) != 0) {
......@@ -162,7 +162,7 @@ class LOCKABLE SpinLock {
void InitLinkerInitializedAndCooperative();
void SlowLock() ABSL_ATTRIBUTE_COLD;
void SlowUnlock(uint32_t lock_value) ABSL_ATTRIBUTE_COLD;
uint32_t SpinLoop(int64_t initial_wait_timestamp, uint32_t* wait_cycles);
uint32_t SpinLoop();
inline bool TryLockImpl() {
uint32_t lock_value = lockword_.load(std::memory_order_relaxed);
......@@ -235,7 +235,7 @@ inline uint32_t SpinLock::TryLockInternal(uint32_t lock_value,
}
} // namespace base_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
#endif // ABSL_BASE_INTERNAL_SPINLOCK_H_
// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// See also //absl/synchronization:mutex_benchmark for a comparison of SpinLock
// and Mutex performance under varying levels of contention.
#include "absl/base/internal/raw_logging.h"
#include "absl/base/internal/scheduling_mode.h"
#include "absl/base/internal/spinlock.h"
#include "absl/synchronization/internal/create_thread_identity.h"
#include "benchmark/benchmark.h"
namespace {
template <absl::base_internal::SchedulingMode scheduling_mode>
static void BM_SpinLock(benchmark::State& state) {
// Ensure a ThreadIdentity is installed.
ABSL_INTERNAL_CHECK(
absl::synchronization_internal::GetOrCreateCurrentThreadIdentity() !=
nullptr,
"GetOrCreateCurrentThreadIdentity() failed");
static auto* spinlock = new absl::base_internal::SpinLock(scheduling_mode);
for (auto _ : state) {
absl::base_internal::SpinLockHolder holder(spinlock);
}
}
BENCHMARK_TEMPLATE(BM_SpinLock,
absl::base_internal::SCHEDULE_KERNEL_ONLY)
->UseRealTime()
->Threads(1)
->ThreadPerCpu();
BENCHMARK_TEMPLATE(BM_SpinLock,
absl::base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL)
->UseRealTime()
->Threads(1)
->ThreadPerCpu();
} // namespace
// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// This file is a Linux-specific part of spinlock_wait.cc
#include <linux/futex.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <atomic>
#include <cerrno>
#include <climits>
#include <cstdint>
#include <ctime>
#include "absl/base/attributes.h"
// The SpinLock lockword is `std::atomic<uint32_t>`. Here we assert that
// `std::atomic<uint32_t>` is bitwise equivalent of the `int` expected
// by SYS_futex. We also assume that reads/writes done to the lockword
// by SYS_futex have rational semantics with regard to the
// std::atomic<> API. C++ provides no guarantees of these assumptions,
// but they are believed to hold in practice.
static_assert(sizeof(std::atomic<uint32_t>) == sizeof(int),
"SpinLock lockword has the wrong size for a futex");
// Some Android headers are missing these definitions even though they
// support these futex operations.
#ifdef __BIONIC__
#ifndef SYS_futex
#define SYS_futex __NR_futex
#endif
#ifndef FUTEX_PRIVATE_FLAG
#define FUTEX_PRIVATE_FLAG 128
#endif
#endif
extern "C" {
ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockDelay(
std::atomic<uint32_t> *w, uint32_t value, int loop,
absl::base_internal::SchedulingMode) {
if (loop != 0) {
int save_errno = errno;
struct timespec tm;
tm.tv_sec = 0;
// Increase the delay; we expect (but do not rely on) explicit wakeups.
// We don't rely on explicit wakeups because we intentionally allow for
// a race on the kSpinLockSleeper bit.
tm.tv_nsec = 16 * absl::base_internal::SpinLockSuggestedDelayNS(loop);
syscall(SYS_futex, w, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, value, &tm);
errno = save_errno;
}
}
ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockWake(std::atomic<uint32_t> *w,
bool all) {
syscall(SYS_futex, w, FUTEX_WAKE | FUTEX_PRIVATE_FLAG, all ? INT_MAX : 1, 0);
}
} // extern "C"
......@@ -13,7 +13,7 @@
// limitations under the License.
// The OS-specific header included below must provide two calls:
// base::subtle::SpinLockDelay() and base::subtle::SpinLockWake().
// AbslInternalSpinLockDelay() and AbslInternalSpinLockWake().
// See spinlock_wait.h for the specs.
#include <atomic>
......@@ -23,6 +23,8 @@
#if defined(_WIN32)
#include "absl/base/internal/spinlock_win32.inc"
#elif defined(__linux__)
#include "absl/base/internal/spinlock_linux.inc"
#elif defined(__akaros__)
#include "absl/base/internal/spinlock_akaros.inc"
#else
......@@ -30,20 +32,21 @@
#endif
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace base_internal {
// See spinlock_wait.h for spec.
uint32_t SpinLockWait(std::atomic<uint32_t> *w, int n,
const SpinLockWaitTransition trans[],
base_internal::SchedulingMode scheduling_mode) {
for (int loop = 0; ; loop++) {
int loop = 0;
for (;;) {
uint32_t v = w->load(std::memory_order_acquire);
int i;
for (i = 0; i != n && v != trans[i].from; i++) {
}
if (i == n) {
SpinLockDelay(w, v, loop, scheduling_mode); // no matching transition
SpinLockDelay(w, v, ++loop, scheduling_mode); // no matching transition
} else if (trans[i].to == v || // null transition
w->compare_exchange_strong(v, trans[i].to,
std::memory_order_acquire,
......@@ -77,5 +80,5 @@ int SpinLockSuggestedDelayNS(int loop) {
}
} // namespace base_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
......@@ -24,7 +24,7 @@
#include "absl/base/internal/scheduling_mode.h"
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace base_internal {
// SpinLockWait() waits until it can perform one of several transitions from
......@@ -63,7 +63,7 @@ void SpinLockDelay(std::atomic<uint32_t> *w, uint32_t value, int loop,
int SpinLockSuggestedDelayNS(int loop);
} // namespace base_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
// In some build configurations we pass --detect-odr-violations to the
......
......@@ -56,7 +56,7 @@
#include "absl/base/internal/unscaledcycleclock.h"
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace base_internal {
static once_flag init_system_info_once;
......@@ -402,5 +402,5 @@ pid_t GetTID() {
#endif
} // namespace base_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
......@@ -33,7 +33,7 @@
#include "absl/base/port.h"
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace base_internal {
// Nominal core processor cycles per second of each processor. This is _not_
......@@ -59,7 +59,7 @@ using pid_t = DWORD;
pid_t GetTID();
} // namespace base_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
#endif // ABSL_BASE_INTERNAL_SYSINFO_H_
......@@ -28,7 +28,7 @@
#include "absl/synchronization/mutex.h"
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace base_internal {
namespace {
......@@ -96,5 +96,5 @@ TEST(SysinfoTest, LinuxGetTID) {
} // namespace
} // namespace base_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
......@@ -28,7 +28,7 @@
#include "absl/base/internal/spinlock.h"
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace base_internal {
#if ABSL_THREAD_IDENTITY_MODE != ABSL_THREAD_IDENTITY_MODE_USE_CPP11
......@@ -69,6 +69,14 @@ void SetCurrentThreadIdentity(
// NOTE: Not async-safe. But can be open-coded.
absl::call_once(init_thread_identity_key_once, AllocateThreadIdentityKey,
reclaimer);
#ifdef __EMSCRIPTEN__
// Emscripten PThread implementation does not support signals.
// See https://kripken.github.io/emscripten-site/docs/porting/pthreads.html
// for more information.
pthread_setspecific(thread_identity_pthread_key,
reinterpret_cast<void*>(identity));
#else
// We must mask signals around the call to setspecific as with current glibc,
// a concurrent getspecific (needed for GetCurrentThreadIdentityIfPresent())
// may zero our value.
......@@ -82,6 +90,8 @@ void SetCurrentThreadIdentity(
pthread_setspecific(thread_identity_pthread_key,
reinterpret_cast<void*>(identity));
pthread_sigmask(SIG_SETMASK, &curr_signals, nullptr);
#endif // !__EMSCRIPTEN__
#elif ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_TLS
// NOTE: Not async-safe. But can be open-coded.
absl::call_once(init_thread_identity_key_once, AllocateThreadIdentityKey,
......@@ -121,5 +131,5 @@ ThreadIdentity* CurrentThreadIdentityIfPresent() {
#endif
} // namespace base_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
......@@ -33,7 +33,7 @@
#include "absl/base/internal/per_thread_tls.h"
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
struct SynchLocksHeld;
struct SynchWaitParams;
......@@ -237,6 +237,6 @@ inline ThreadIdentity* CurrentThreadIdentityIfPresent() {
#endif
} // namespace base_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
#endif // ABSL_BASE_INTERNAL_THREAD_IDENTITY_H_
......@@ -25,7 +25,7 @@
#include "absl/synchronization/mutex.h"
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace base_internal {
namespace {
......@@ -124,5 +124,5 @@ TEST(ThreadIdentityTest, ReusedThreadIdentityMutexTest) {
} // namespace
} // namespace base_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
......@@ -22,7 +22,7 @@
#include "absl/base/internal/raw_logging.h"
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace base_internal {
namespace {
......@@ -31,8 +31,8 @@ template <typename T>
#ifdef ABSL_HAVE_EXCEPTIONS
throw error;
#else
ABSL_RAW_LOG(ERROR, "%s", error.what());
abort();
ABSL_RAW_LOG(FATAL, "%s", error.what());
std::abort();
#endif
}
} // namespace
......@@ -104,5 +104,5 @@ void ThrowStdBadFunctionCall() { Throw(std::bad_function_call()); }
void ThrowStdBadAlloc() { Throw(std::bad_alloc()); }
} // namespace base_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
......@@ -20,7 +20,7 @@
#include <string>
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace base_internal {
// Helper functions that allow throwing exceptions consistently from anywhere.
......@@ -67,7 +67,7 @@ namespace base_internal {
// [[noreturn]] void ThrowStdBadArrayNewLength();
} // namespace base_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
#endif // ABSL_BASE_INTERNAL_THROW_DELEGATE_H_
......@@ -65,7 +65,8 @@ void __sanitizer_unaligned_store64(void *p, uint64_t v);
} // extern "C"
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace base_internal {
inline uint16_t UnalignedLoad16(const void *p) {
return __sanitizer_unaligned_load16(p);
......@@ -91,19 +92,71 @@ inline void UnalignedStore64(void *p, uint64_t v) {
__sanitizer_unaligned_store64(p, v);
}
} // inline namespace lts_2018_06_20
} // namespace base_internal
} // inline namespace lts_2018_12_18
} // namespace absl
#define ABSL_INTERNAL_UNALIGNED_LOAD16(_p) (absl::UnalignedLoad16(_p))
#define ABSL_INTERNAL_UNALIGNED_LOAD32(_p) (absl::UnalignedLoad32(_p))
#define ABSL_INTERNAL_UNALIGNED_LOAD64(_p) (absl::UnalignedLoad64(_p))
#define ABSL_INTERNAL_UNALIGNED_LOAD16(_p) \
(absl::base_internal::UnalignedLoad16(_p))
#define ABSL_INTERNAL_UNALIGNED_LOAD32(_p) \
(absl::base_internal::UnalignedLoad32(_p))
#define ABSL_INTERNAL_UNALIGNED_LOAD64(_p) \
(absl::base_internal::UnalignedLoad64(_p))
#define ABSL_INTERNAL_UNALIGNED_STORE16(_p, _val) \
(absl::base_internal::UnalignedStore16(_p, _val))
#define ABSL_INTERNAL_UNALIGNED_STORE32(_p, _val) \
(absl::base_internal::UnalignedStore32(_p, _val))
#define ABSL_INTERNAL_UNALIGNED_STORE64(_p, _val) \
(absl::base_internal::UnalignedStore64(_p, _val))
#elif defined(UNDEFINED_BEHAVIOR_SANITIZER)
namespace absl {
inline namespace lts_2018_12_18 {
namespace base_internal {
inline uint16_t UnalignedLoad16(const void *p) {
uint16_t t;
memcpy(&t, p, sizeof t);
return t;
}
inline uint32_t UnalignedLoad32(const void *p) {
uint32_t t;
memcpy(&t, p, sizeof t);
return t;
}
inline uint64_t UnalignedLoad64(const void *p) {
uint64_t t;
memcpy(&t, p, sizeof t);
return t;
}
inline void UnalignedStore16(void *p, uint16_t v) { memcpy(p, &v, sizeof v); }
inline void UnalignedStore32(void *p, uint32_t v) { memcpy(p, &v, sizeof v); }
inline void UnalignedStore64(void *p, uint64_t v) { memcpy(p, &v, sizeof v); }
} // namespace base_internal
} // inline namespace lts_2018_12_18
} // namespace absl
#define ABSL_INTERNAL_UNALIGNED_LOAD16(_p) \
(absl::base_internal::UnalignedLoad16(_p))
#define ABSL_INTERNAL_UNALIGNED_LOAD32(_p) \
(absl::base_internal::UnalignedLoad32(_p))
#define ABSL_INTERNAL_UNALIGNED_LOAD64(_p) \
(absl::base_internal::UnalignedLoad64(_p))
#define ABSL_INTERNAL_UNALIGNED_STORE16(_p, _val) \
(absl::UnalignedStore16(_p, _val))
(absl::base_internal::UnalignedStore16(_p, _val))
#define ABSL_INTERNAL_UNALIGNED_STORE32(_p, _val) \
(absl::UnalignedStore32(_p, _val))
(absl::base_internal::UnalignedStore32(_p, _val))
#define ABSL_INTERNAL_UNALIGNED_STORE64(_p, _val) \
(absl::UnalignedStore64(_p, _val))
(absl::base_internal::UnalignedStore64(_p, _val))
#elif defined(__x86_64__) || defined(_M_X64) || defined(__i386) || \
defined(_M_IX86) || defined(__ppc__) || defined(__PPC__) || \
......@@ -160,8 +213,8 @@ inline void UnalignedStore64(void *p, uint64_t v) {
// so we do that.
namespace absl {
inline namespace lts_2018_06_20 {
namespace internal {
inline namespace lts_2018_12_18 {
namespace base_internal {
struct Unaligned16Struct {
uint16_t value;
......@@ -173,24 +226,27 @@ struct Unaligned32Struct {
uint8_t dummy; // To make the size non-power-of-two.
} ABSL_ATTRIBUTE_PACKED;
} // namespace internal
} // inline namespace lts_2018_06_20
} // namespace base_internal
} // inline namespace lts_2018_12_18
} // namespace absl
#define ABSL_INTERNAL_UNALIGNED_LOAD16(_p) \
((reinterpret_cast<const ::absl::internal::Unaligned16Struct *>(_p))->value)
((reinterpret_cast<const ::absl::base_internal::Unaligned16Struct *>(_p)) \
->value)
#define ABSL_INTERNAL_UNALIGNED_LOAD32(_p) \
((reinterpret_cast<const ::absl::internal::Unaligned32Struct *>(_p))->value)
((reinterpret_cast<const ::absl::base_internal::Unaligned32Struct *>(_p)) \
->value)
#define ABSL_INTERNAL_UNALIGNED_STORE16(_p, _val) \
((reinterpret_cast< ::absl::internal::Unaligned16Struct *>(_p))->value = \
(_val))
((reinterpret_cast< ::absl::base_internal::Unaligned16Struct *>(_p)) \
->value = (_val))
#define ABSL_INTERNAL_UNALIGNED_STORE32(_p, _val) \
((reinterpret_cast< ::absl::internal::Unaligned32Struct *>(_p))->value = \
(_val))
((reinterpret_cast< ::absl::base_internal::Unaligned32Struct *>(_p)) \
->value = (_val))
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace base_internal {
inline uint64_t UnalignedLoad64(const void *p) {
uint64_t t;
......@@ -200,12 +256,14 @@ inline uint64_t UnalignedLoad64(const void *p) {
inline void UnalignedStore64(void *p, uint64_t v) { memcpy(p, &v, sizeof v); }
} // inline namespace lts_2018_06_20
} // namespace base_internal
} // inline namespace lts_2018_12_18
} // namespace absl
#define ABSL_INTERNAL_UNALIGNED_LOAD64(_p) (absl::UnalignedLoad64(_p))
#define ABSL_INTERNAL_UNALIGNED_LOAD64(_p) \
(absl::base_internal::UnalignedLoad64(_p))
#define ABSL_INTERNAL_UNALIGNED_STORE64(_p, _val) \
(absl::UnalignedStore64(_p, _val))
(absl::base_internal::UnalignedStore64(_p, _val))
#else
......@@ -217,7 +275,8 @@ inline void UnalignedStore64(void *p, uint64_t v) { memcpy(p, &v, sizeof v); }
// unaligned loads and stores.
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace base_internal {
inline uint16_t UnalignedLoad16(const void *p) {
uint16_t t;
......@@ -243,19 +302,23 @@ inline void UnalignedStore32(void *p, uint32_t v) { memcpy(p, &v, sizeof v); }
inline void UnalignedStore64(void *p, uint64_t v) { memcpy(p, &v, sizeof v); }
} // inline namespace lts_2018_06_20
} // namespace base_internal
} // inline namespace lts_2018_12_18
} // namespace absl
#define ABSL_INTERNAL_UNALIGNED_LOAD16(_p) (absl::UnalignedLoad16(_p))
#define ABSL_INTERNAL_UNALIGNED_LOAD32(_p) (absl::UnalignedLoad32(_p))
#define ABSL_INTERNAL_UNALIGNED_LOAD64(_p) (absl::UnalignedLoad64(_p))
#define ABSL_INTERNAL_UNALIGNED_LOAD16(_p) \
(absl::base_internal::UnalignedLoad16(_p))
#define ABSL_INTERNAL_UNALIGNED_LOAD32(_p) \
(absl::base_internal::UnalignedLoad32(_p))
#define ABSL_INTERNAL_UNALIGNED_LOAD64(_p) \
(absl::base_internal::UnalignedLoad64(_p))
#define ABSL_INTERNAL_UNALIGNED_STORE16(_p, _val) \
(absl::UnalignedStore16(_p, _val))
(absl::base_internal::UnalignedStore16(_p, _val))
#define ABSL_INTERNAL_UNALIGNED_STORE32(_p, _val) \
(absl::UnalignedStore32(_p, _val))
(absl::base_internal::UnalignedStore32(_p, _val))
#define ABSL_INTERNAL_UNALIGNED_STORE64(_p, _val) \
(absl::UnalignedStore64(_p, _val))
(absl::base_internal::UnalignedStore64(_p, _val))
#endif
......
......@@ -27,7 +27,7 @@
#include "absl/base/internal/sysinfo.h"
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace base_internal {
#if defined(__i386__)
......@@ -97,7 +97,7 @@ double UnscaledCycleClock::Frequency() {
#endif
} // namespace base_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
#endif // ABSL_USE_UNSCALED_CYCLECLOCK
......@@ -84,7 +84,7 @@
#define ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY
#endif
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace time_internal {
class UnscaledCycleClockWrapperForGetCurrentTime;
} // namespace time_internal
......@@ -114,7 +114,7 @@ class UnscaledCycleClock {
};
} // namespace base_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
#endif // ABSL_USE_UNSCALED_CYCLECLOCK
......
......@@ -25,7 +25,7 @@
#include "absl/strings/str_cat.h"
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace base_internal {
namespace {
......@@ -198,5 +198,5 @@ TEST(InvokeTest, SfinaeFriendly) {
} // namespace
} // namespace base_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
......@@ -21,7 +21,7 @@
#include "absl/base/attributes.h"
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
// Four severity levels are defined. Logging APIs should terminate the program
// when a message is logged at severity `kFatal`; the other levels have no
......@@ -40,7 +40,7 @@ constexpr std::array<absl::LogSeverity, 4> LogSeverities() {
absl::LogSeverity::kError, absl::LogSeverity::kFatal}};
}
// Returns the all-caps std::string representation (e.g. "INFO") of the specified
// Returns the all-caps string representation (e.g. "INFO") of the specified
// severity level if it is one of the normal levels and "UNKNOWN" otherwise.
constexpr const char* LogSeverityName(absl::LogSeverity s) {
return s == absl::LogSeverity::kInfo
......@@ -63,7 +63,7 @@ constexpr absl::LogSeverity NormalizeLogSeverity(int s) {
return NormalizeLogSeverity(static_cast<absl::LogSeverity>(s));
}
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
#endif // ABSL_BASE_INTERNAL_LOG_SEVERITY_H_
......@@ -43,14 +43,14 @@
(sizeof(::absl::macros_internal::ArraySizeHelper(array)))
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace macros_internal {
// Note: this internal template function declaration is used by ABSL_ARRAYSIZE.
// The function doesn't need a definition, as we only use its type.
template <typename T, size_t N>
auto ArraySizeHelper(const T (&array)[N]) -> char (&)[N];
} // namespace macros_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
// kLinkerInitialized
......@@ -74,13 +74,13 @@ auto ArraySizeHelper(const T (&array)[N]) -> char (&)[N];
// // Invocation
// static MyClass my_global(absl::base_internal::kLinkerInitialized);
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace base_internal {
enum LinkerInitialized {
kLinkerInitialized = 0,
};
} // namespace base_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
// ABSL_FALLTHROUGH_INTENDED
......@@ -203,4 +203,14 @@ enum LinkerInitialized {
: [] { assert(false && #expr); }()) // NOLINT
#endif
#ifdef ABSL_HAVE_EXCEPTIONS
#define ABSL_INTERNAL_TRY try
#define ABSL_INTERNAL_CATCH_ANY catch (...)
#define ABSL_INTERNAL_RETHROW do { throw; } while (false)
#else // ABSL_HAVE_EXCEPTIONS
#define ABSL_INTERNAL_TRY if (true)
#define ABSL_INTERNAL_CATCH_ANY else if (false)
#define ABSL_INTERNAL_RETHROW do {} while (false)
#endif // ABSL_HAVE_EXCEPTIONS
#endif // ABSL_BASE_MACROS_H_
......@@ -18,12 +18,20 @@
#include "absl/base/internal/raw_logging.h"
#include <tuple>
#include "gtest/gtest.h"
#include "absl/strings/str_cat.h"
namespace {
TEST(RawLoggingCompilationTest, Log) {
ABSL_RAW_LOG(INFO, "RAW INFO: %d", 1);
ABSL_RAW_LOG(INFO, "RAW INFO: %d %d", 1, 2);
ABSL_RAW_LOG(INFO, "RAW INFO: %d %d %d", 1, 2, 3);
ABSL_RAW_LOG(INFO, "RAW INFO: %d %d %d %d", 1, 2, 3, 4);
ABSL_RAW_LOG(INFO, "RAW INFO: %d %d %d %d %d", 1, 2, 3, 4, 5);
ABSL_RAW_LOG(WARNING, "RAW WARNING: %d", 1);
ABSL_RAW_LOG(ERROR, "RAW ERROR: %d", 1);
}
......@@ -32,7 +40,7 @@ TEST(RawLoggingCompilationTest, PassingCheck) {
}
// Not all platforms support output from raw log, so we don't verify any
// particular output for RAW check failures (expecting the empty std::string
// particular output for RAW check failures (expecting the empty string
// accomplishes this). This test is primarily a compilation test, but we
// are verifying process death when EXPECT_DEATH works for a platform.
const char kExpectedDeathOutput[] = "";
......@@ -47,4 +55,25 @@ TEST(RawLoggingDeathTest, LogFatal) {
kExpectedDeathOutput);
}
TEST(InternalLog, CompilationTest) {
ABSL_INTERNAL_LOG(INFO, "Internal Log");
std::string log_msg = "Internal Log";
ABSL_INTERNAL_LOG(INFO, log_msg);
ABSL_INTERNAL_LOG(INFO, log_msg + " 2");
float d = 1.1f;
ABSL_INTERNAL_LOG(INFO, absl::StrCat("Internal log ", 3, " + ", d));
}
TEST(InternalLogDeathTest, FailingCheck) {
EXPECT_DEATH_IF_SUPPORTED(ABSL_INTERNAL_CHECK(1 == 0, "explanation"),
kExpectedDeathOutput);
}
TEST(InternalLogDeathTest, LogFatal) {
EXPECT_DEATH_IF_SUPPORTED(ABSL_INTERNAL_LOG(FATAL, "my dog has fleas"),
kExpectedDeathOutput);
}
} // namespace
......@@ -36,7 +36,7 @@ constexpr int32_t kNumThreads = 10;
constexpr int32_t kIters = 1000;
namespace absl {
inline namespace lts_2018_06_20 {
inline namespace lts_2018_12_18 {
namespace base_internal {
// This is defined outside of anonymous namespace so that it can be
......@@ -156,7 +156,8 @@ TEST(SpinLock, WaitCyclesEncoding) {
// Test corner cases
int64_t start_time = time_distribution(generator);
EXPECT_EQ(0, SpinLockTest::EncodeWaitCycles(start_time, start_time));
EXPECT_EQ(kSpinLockSleeper,
SpinLockTest::EncodeWaitCycles(start_time, start_time));
EXPECT_EQ(0, SpinLockTest::DecodeWaitCycles(0));
EXPECT_EQ(0, SpinLockTest::DecodeWaitCycles(kLockwordReservedMask));
EXPECT_EQ(kMaxCycles & ~kProfileTimestampMask,
......@@ -264,5 +265,5 @@ TEST(SpinLockWithThreads, DoesNotDeadlock) {
} // namespace
} // namespace base_internal
} // inline namespace lts_2018_06_20
} // inline namespace lts_2018_12_18
} // namespace absl
......@@ -31,7 +31,6 @@
// that evaluate to a concrete mutex object whenever possible. If the mutex
// you want to refer to is not in scope, you may use a member pointer
// (e.g. &MyClass::mutex_) to refer to a mutex in some (unknown) object.
//
#ifndef ABSL_BASE_THREAD_ANNOTATIONS_H_
#define ABSL_BASE_THREAD_ANNOTATIONS_H_
......@@ -109,13 +108,23 @@
// The mutex is expected to be held both on entry to, and exit from, the
// function.
//
// An exclusive lock allows read-write access to the guarded data member(s), and
// only one thread can acquire a lock exclusively at any one time. A shared lock
// allows read-only access, and any number of threads can acquire a shared lock
// concurrently.
//
// Generally, non-const methods should be annotated with
// EXCLUSIVE_LOCKS_REQUIRED, while const methods should be annotated with
// SHARED_LOCKS_REQUIRED.
//
// Example:
//
// Mutex mu1, mu2;
// int a GUARDED_BY(mu1);
// int b GUARDED_BY(mu2);
//
// void foo() EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2) { ... };
// void foo() EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2) { ... }
// void bar() const SHARED_LOCKS_REQUIRED(mu1, mu2) { ... }
#define EXCLUSIVE_LOCKS_REQUIRED(...) \
THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__))
......
#
# Copyright 2018 The Abseil Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""Creates config_setting that allows selecting based on 'compiler' value."""
def create_llvm_config(name, visibility):
# The "do_not_use_tools_cpp_compiler_present" attribute exists to
# distinguish between older versions of Bazel that do not support
# "@bazel_tools//tools/cpp:compiler" flag_value, and newer ones that do.
# In the future, the only way to select on the compiler will be through
# flag_values{"@bazel_tools//tools/cpp:compiler"} and the else branch can
# be removed.
if hasattr(cc_common, "do_not_use_tools_cpp_compiler_present"):
native.config_setting(
name = name,
flag_values = {
"@bazel_tools//tools/cpp:compiler": "llvm",
},
visibility = visibility,
)
else:
native.config_setting(
name = name,
values = {"compiler": "llvm"},
visibility = visibility,
)
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <initializer_list>
#include "absl/container/fixed_array.h"
#include "gtest/gtest.h"
#include "absl/base/internal/exception_safety_testing.h"
namespace absl {
inline namespace lts_2018_12_18 {
namespace {
constexpr size_t kInlined = 25;
constexpr size_t kSmallSize = kInlined / 2;
constexpr size_t kLargeSize = kInlined * 2;
constexpr int kInitialValue = 5;
constexpr int kUpdatedValue = 10;
using ::testing::TestThrowingCtor;
using Thrower = testing::ThrowingValue<testing::TypeSpec::kEverythingThrows>;
using FixedArr = absl::FixedArray<Thrower, kInlined>;
using MoveThrower = testing::ThrowingValue<testing::TypeSpec::kNoThrowMove>;
using MoveFixedArr = absl::FixedArray<MoveThrower, kInlined>;
TEST(FixedArrayExceptionSafety, CopyConstructor) {
auto small = FixedArr(kSmallSize);
TestThrowingCtor<FixedArr>(small);
auto large = FixedArr(kLargeSize);
TestThrowingCtor<FixedArr>(large);
}
TEST(FixedArrayExceptionSafety, MoveConstructor) {
TestThrowingCtor<FixedArr>(FixedArr(kSmallSize));
TestThrowingCtor<FixedArr>(FixedArr(kLargeSize));
// TypeSpec::kNoThrowMove
TestThrowingCtor<MoveFixedArr>(MoveFixedArr(kSmallSize));
TestThrowingCtor<MoveFixedArr>(MoveFixedArr(kLargeSize));
}
TEST(FixedArrayExceptionSafety, SizeConstructor) {
TestThrowingCtor<FixedArr>(kSmallSize);
TestThrowingCtor<FixedArr>(kLargeSize);
}
TEST(FixedArrayExceptionSafety, SizeValueConstructor) {
TestThrowingCtor<FixedArr>(kSmallSize, Thrower());
TestThrowingCtor<FixedArr>(kLargeSize, Thrower());
}
TEST(FixedArrayExceptionSafety, IteratorConstructor) {
auto small = FixedArr(kSmallSize);
TestThrowingCtor<FixedArr>(small.begin(), small.end());
auto large = FixedArr(kLargeSize);
TestThrowingCtor<FixedArr>(large.begin(), large.end());
}
TEST(FixedArrayExceptionSafety, InitListConstructor) {
constexpr int small_inlined = 3;
using SmallFixedArr = absl::FixedArray<Thrower, small_inlined>;
TestThrowingCtor<SmallFixedArr>(std::initializer_list<Thrower>{});
// Test inlined allocation
TestThrowingCtor<SmallFixedArr>(
std::initializer_list<Thrower>{Thrower{}, Thrower{}});
// Test out of line allocation
TestThrowingCtor<SmallFixedArr>(std::initializer_list<Thrower>{
Thrower{}, Thrower{}, Thrower{}, Thrower{}, Thrower{}});
}
testing::AssertionResult ReadMemory(FixedArr* fixed_arr) {
// Marked volatile to prevent optimization. Used for running asan tests.
volatile int sum = 0;
for (const auto& thrower : *fixed_arr) {
sum += thrower.Get();
}
return testing::AssertionSuccess() << "Values sum to [" << sum << "]";
}
TEST(FixedArrayExceptionSafety, Fill) {
auto test_fill = testing::MakeExceptionSafetyTester()
.WithContracts(ReadMemory)
.WithOperation([&](FixedArr* fixed_arr_ptr) {
auto thrower =
Thrower(kUpdatedValue, testing::nothrow_ctor);
fixed_arr_ptr->fill(thrower);
});
EXPECT_TRUE(
test_fill.WithInitialValue(FixedArr(kSmallSize, Thrower(kInitialValue)))
.Test());
EXPECT_TRUE(
test_fill.WithInitialValue(FixedArr(kLargeSize, Thrower(kInitialValue)))
.Test());
}
} // namespace
} // inline namespace lts_2018_12_18
} // namespace absl
......@@ -15,9 +15,11 @@
#include "absl/container/fixed_array.h"
#include <stdio.h>
#include <cstring>
#include <list>
#include <memory>
#include <numeric>
#include <scoped_allocator>
#include <stdexcept>
#include <string>
#include <vector>
......@@ -25,6 +27,7 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/base/internal/exception_testing.h"
#include "absl/hash/hash_testing.h"
#include "absl/memory/memory.h"
using ::testing::ElementsAreArray;
......@@ -607,6 +610,216 @@ TEST(FixedArrayTest, Fill) {
empty.fill(fill_val);
}
// TODO(johnsoncj): Investigate InlinedStorage default initialization in GCC 4.x
#ifndef __GNUC__
TEST(FixedArrayTest, DefaultCtorDoesNotValueInit) {
using T = char;
constexpr auto capacity = 10;
using FixedArrType = absl::FixedArray<T, capacity>;
using FixedArrBuffType =
absl::aligned_storage_t<sizeof(FixedArrType), alignof(FixedArrType)>;
constexpr auto scrubbed_bits = 0x95;
constexpr auto length = capacity / 2;
FixedArrBuffType buff;
std::memset(std::addressof(buff), scrubbed_bits, sizeof(FixedArrBuffType));
FixedArrType* arr =
::new (static_cast<void*>(std::addressof(buff))) FixedArrType(length);
EXPECT_THAT(*arr, testing::Each(scrubbed_bits));
arr->~FixedArrType();
}
#endif // __GNUC__
// This is a stateful allocator, but the state lives outside of the
// allocator (in whatever test is using the allocator). This is odd
// but helps in tests where the allocator is propagated into nested
// containers - that chain of allocators uses the same state and is
// thus easier to query for aggregate allocation information.
template <typename T>
class CountingAllocator : public std::allocator<T> {
public:
using Alloc = std::allocator<T>;
using pointer = typename Alloc::pointer;
using size_type = typename Alloc::size_type;
CountingAllocator() : bytes_used_(nullptr), instance_count_(nullptr) {}
explicit CountingAllocator(int64_t* b)
: bytes_used_(b), instance_count_(nullptr) {}
CountingAllocator(int64_t* b, int64_t* a)
: bytes_used_(b), instance_count_(a) {}
template <typename U>
explicit CountingAllocator(const CountingAllocator<U>& x)
: Alloc(x),
bytes_used_(x.bytes_used_),
instance_count_(x.instance_count_) {}
pointer allocate(size_type n, const void* const hint = nullptr) {
assert(bytes_used_ != nullptr);
*bytes_used_ += n * sizeof(T);
return Alloc::allocate(n, hint);
}
void deallocate(pointer p, size_type n) {
Alloc::deallocate(p, n);
assert(bytes_used_ != nullptr);
*bytes_used_ -= n * sizeof(T);
}
template <typename... Args>
void construct(pointer p, Args&&... args) {
Alloc::construct(p, absl::forward<Args>(args)...);
if (instance_count_) {
*instance_count_ += 1;
}
}
void destroy(pointer p) {
Alloc::destroy(p);
if (instance_count_) {
*instance_count_ -= 1;
}
}
template <typename U>
class rebind {
public:
using other = CountingAllocator<U>;
};
int64_t* bytes_used_;
int64_t* instance_count_;
};
TEST(AllocatorSupportTest, CountInlineAllocations) {
constexpr size_t inlined_size = 4;
using Alloc = CountingAllocator<int>;
using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;
int64_t allocated = 0;
int64_t active_instances = 0;
{
const int ia[] = {0, 1, 2, 3, 4, 5, 6, 7};
Alloc alloc(&allocated, &active_instances);
AllocFxdArr arr(ia, ia + inlined_size, alloc);
static_cast<void>(arr);
}
EXPECT_EQ(allocated, 0);
EXPECT_EQ(active_instances, 0);
}
TEST(AllocatorSupportTest, CountOutoflineAllocations) {
constexpr size_t inlined_size = 4;
using Alloc = CountingAllocator<int>;
using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;
int64_t allocated = 0;
int64_t active_instances = 0;
{
const int ia[] = {0, 1, 2, 3, 4, 5, 6, 7};
Alloc alloc(&allocated, &active_instances);
AllocFxdArr arr(ia, ia + ABSL_ARRAYSIZE(ia), alloc);
EXPECT_EQ(allocated, arr.size() * sizeof(int));
static_cast<void>(arr);
}
EXPECT_EQ(active_instances, 0);
}
TEST(AllocatorSupportTest, CountCopyInlineAllocations) {
constexpr size_t inlined_size = 4;
using Alloc = CountingAllocator<int>;
using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;
int64_t allocated1 = 0;
int64_t allocated2 = 0;
int64_t active_instances = 0;
Alloc alloc(&allocated1, &active_instances);
Alloc alloc2(&allocated2, &active_instances);
{
int initial_value = 1;
AllocFxdArr arr1(inlined_size / 2, initial_value, alloc);
EXPECT_EQ(allocated1, 0);
AllocFxdArr arr2(arr1, alloc2);
EXPECT_EQ(allocated2, 0);
static_cast<void>(arr1);
static_cast<void>(arr2);
}
EXPECT_EQ(active_instances, 0);
}
TEST(AllocatorSupportTest, CountCopyOutoflineAllocations) {
constexpr size_t inlined_size = 4;
using Alloc = CountingAllocator<int>;
using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;
int64_t allocated1 = 0;
int64_t allocated2 = 0;
int64_t active_instances = 0;
Alloc alloc(&allocated1, &active_instances);
Alloc alloc2(&allocated2, &active_instances);
{
int initial_value = 1;
AllocFxdArr arr1(inlined_size * 2, initial_value, alloc);
EXPECT_EQ(allocated1, arr1.size() * sizeof(int));
AllocFxdArr arr2(arr1, alloc2);
EXPECT_EQ(allocated2, inlined_size * 2 * sizeof(int));
static_cast<void>(arr1);
static_cast<void>(arr2);
}
EXPECT_EQ(active_instances, 0);
}
TEST(AllocatorSupportTest, SizeValAllocConstructor) {
using testing::AllOf;
using testing::Each;
using testing::SizeIs;
constexpr size_t inlined_size = 4;
using Alloc = CountingAllocator<int>;
using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;
{
auto len = inlined_size / 2;
auto val = 0;
int64_t allocated = 0;
AllocFxdArr arr(len, val, Alloc(&allocated));
EXPECT_EQ(allocated, 0);
EXPECT_THAT(arr, AllOf(SizeIs(len), Each(0)));
}
{
auto len = inlined_size * 2;
auto val = 0;
int64_t allocated = 0;
AllocFxdArr arr(len, val, Alloc(&allocated));
EXPECT_EQ(allocated, len * sizeof(int));
EXPECT_THAT(arr, AllOf(SizeIs(len), Each(0)));
}
}
#ifdef ADDRESS_SANITIZER
TEST(FixedArrayTest, AddressSanitizerAnnotations1) {
absl::FixedArray<int, 32> a(10);
......
// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "absl/container/flat_hash_map.h"
#include "absl/container/internal/hash_generator_testing.h"
#include "absl/container/internal/unordered_map_constructor_test.h"
#include "absl/container/internal/unordered_map_lookup_test.h"
#include "absl/container/internal/unordered_map_modifiers_test.h"
#include "absl/types/any.h"
namespace absl {
inline namespace lts_2018_12_18 {
namespace container_internal {
namespace {
using ::absl::container_internal::hash_internal::Enum;
using ::absl::container_internal::hash_internal::EnumClass;
using ::testing::_;
using ::testing::Pair;
using ::testing::UnorderedElementsAre;
template <class K, class V>
using Map =
flat_hash_map<K, V, StatefulTestingHash, StatefulTestingEqual, Alloc<>>;
static_assert(!std::is_standard_layout<NonStandardLayout>(), "");
using MapTypes =
::testing::Types<Map<int, int>, Map<std::string, int>, Map<Enum, std::string>,
Map<EnumClass, int>, Map<int, NonStandardLayout>,
Map<NonStandardLayout, int>>;
INSTANTIATE_TYPED_TEST_CASE_P(FlatHashMap, ConstructorTest, MapTypes);
INSTANTIATE_TYPED_TEST_CASE_P(FlatHashMap, LookupTest, MapTypes);
INSTANTIATE_TYPED_TEST_CASE_P(FlatHashMap, ModifiersTest, MapTypes);
TEST(FlatHashMap, StandardLayout) {
struct Int {
explicit Int(size_t value) : value(value) {}
Int() : value(0) { ADD_FAILURE(); }
Int(const Int& other) : value(other.value) { ADD_FAILURE(); }
Int(Int&&) = default;
bool operator==(const Int& other) const { return value == other.value; }
size_t value;
};
static_assert(std::is_standard_layout<Int>(), "");
struct Hash {
size_t operator()(const Int& obj) const { return obj.value; }
};
// Verify that neither the key nor the value get default-constructed or
// copy-constructed.
{
flat_hash_map<Int, Int, Hash> m;
m.try_emplace(Int(1), Int(2));
m.try_emplace(Int(3), Int(4));
m.erase(Int(1));
m.rehash(2 * m.bucket_count());
}
{
flat_hash_map<Int, Int, Hash> m;
m.try_emplace(Int(1), Int(2));
m.try_emplace(Int(3), Int(4));
m.erase(Int(1));
m.clear();
}
}
// gcc becomes unhappy if this is inside the method, so pull it out here.
struct balast {};
TEST(FlatHashMap, IteratesMsan) {
// Because SwissTable randomizes on pointer addresses, we keep old tables
// around to ensure we don't reuse old memory.
std::vector<absl::flat_hash_map<int, balast>> garbage;
for (int i = 0; i < 100; ++i) {
absl::flat_hash_map<int, balast> t;
for (int j = 0; j < 100; ++j) {
t[j];
for (const auto& p : t) EXPECT_THAT(p, Pair(_, _));
}
garbage.push_back(std::move(t));
}
}
// Demonstration of the "Lazy Key" pattern. This uses heterogeneous insert to
// avoid creating expensive key elements when the item is already present in the
// map.
struct LazyInt {
explicit LazyInt(size_t value, int* tracker)
: value(value), tracker(tracker) {}
explicit operator size_t() const {
++*tracker;
return value;
}
size_t value;
int* tracker;
};
struct Hash {
using is_transparent = void;
int* tracker;
size_t operator()(size_t obj) const {
++*tracker;
return obj;
}
size_t operator()(const LazyInt& obj) const {
++*tracker;
return obj.value;
}
};
struct Eq {
using is_transparent = void;
bool operator()(size_t lhs, size_t rhs) const {
return lhs == rhs;
}
bool operator()(size_t lhs, const LazyInt& rhs) const {
return lhs == rhs.value;
}
};
TEST(FlatHashMap, LazyKeyPattern) {
// hashes are only guaranteed in opt mode, we use assertions to track internal
// state that can cause extra calls to hash.
int conversions = 0;
int hashes = 0;
flat_hash_map<size_t, size_t, Hash, Eq> m(0, Hash{&hashes});
m[LazyInt(1, &conversions)] = 1;
EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 1)));
EXPECT_EQ(conversions, 1);
#ifdef NDEBUG
EXPECT_EQ(hashes, 1);
#endif
m[LazyInt(1, &conversions)] = 2;
EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 2)));
EXPECT_EQ(conversions, 1);
#ifdef NDEBUG
EXPECT_EQ(hashes, 2);
#endif
m.try_emplace(LazyInt(2, &conversions), 3);
EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 2), Pair(2, 3)));
EXPECT_EQ(conversions, 2);
#ifdef NDEBUG
EXPECT_EQ(hashes, 3);
#endif
m.try_emplace(LazyInt(2, &conversions), 4);
EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 2), Pair(2, 3)));
EXPECT_EQ(conversions, 2);
#ifdef NDEBUG
EXPECT_EQ(hashes, 4);
#endif
}
TEST(FlatHashMap, BitfieldArgument) {
union {
int n : 1;
};
n = 0;
flat_hash_map<int, int> m;
m.erase(n);
m.count(n);
m.prefetch(n);
m.find(n);
m.contains(n);
m.equal_range(n);
m.insert_or_assign(n, n);
m.insert_or_assign(m.end(), n, n);
m.try_emplace(n);
m.try_emplace(m.end(), n);
m.at(n);
m[n];
}
TEST(FlatHashMap, MergeExtractInsert) {
// We can't test mutable keys, or non-copyable keys with flat_hash_map.
// Test that the nodes have the proper API.
absl::flat_hash_map<int, int> m = {{1, 7}, {2, 9}};
auto node = m.extract(1);
EXPECT_TRUE(node);
EXPECT_EQ(node.key(), 1);
EXPECT_EQ(node.mapped(), 7);
EXPECT_THAT(m, UnorderedElementsAre(Pair(2, 9)));
node.mapped() = 17;
m.insert(std::move(node));
EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 17), Pair(2, 9)));
}
#if !defined(__ANDROID__) && !defined(__APPLE__) && !defined(__EMSCRIPTEN__)
TEST(FlatHashMap, Any) {
absl::flat_hash_map<int, absl::any> m;
m.emplace(1, 7);
auto it = m.find(1);
ASSERT_NE(it, m.end());
EXPECT_EQ(7, absl::any_cast<int>(it->second));
m.emplace(std::piecewise_construct, std::make_tuple(2), std::make_tuple(8));
it = m.find(2);
ASSERT_NE(it, m.end());
EXPECT_EQ(8, absl::any_cast<int>(it->second));
m.emplace(std::piecewise_construct, std::make_tuple(3),
std::make_tuple(absl::any(9)));
it = m.find(3);
ASSERT_NE(it, m.end());
EXPECT_EQ(9, absl::any_cast<int>(it->second));
struct H {
size_t operator()(const absl::any&) const { return 0; }
};
struct E {
bool operator()(const absl::any&, const absl::any&) const { return true; }
};
absl::flat_hash_map<absl::any, int, H, E> m2;
m2.emplace(1, 7);
auto it2 = m2.find(1);
ASSERT_NE(it2, m2.end());
EXPECT_EQ(7, it2->second);
}
#endif // __ANDROID__
} // namespace
} // namespace container_internal
} // inline namespace lts_2018_12_18
} // namespace absl
// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "absl/container/flat_hash_set.h"
#include <vector>
#include "absl/container/internal/hash_generator_testing.h"
#include "absl/container/internal/unordered_set_constructor_test.h"
#include "absl/container/internal/unordered_set_lookup_test.h"
#include "absl/container/internal/unordered_set_modifiers_test.h"
#include "absl/memory/memory.h"
#include "absl/strings/string_view.h"
namespace absl {
inline namespace lts_2018_12_18 {
namespace container_internal {
namespace {
using ::absl::container_internal::hash_internal::Enum;
using ::absl::container_internal::hash_internal::EnumClass;
using ::testing::Pointee;
using ::testing::UnorderedElementsAre;
using ::testing::UnorderedElementsAreArray;
template <class T>
using Set =
absl::flat_hash_set<T, StatefulTestingHash, StatefulTestingEqual, Alloc<T>>;
using SetTypes =
::testing::Types<Set<int>, Set<std::string>, Set<Enum>, Set<EnumClass>>;
INSTANTIATE_TYPED_TEST_CASE_P(FlatHashSet, ConstructorTest, SetTypes);
INSTANTIATE_TYPED_TEST_CASE_P(FlatHashSet, LookupTest, SetTypes);
INSTANTIATE_TYPED_TEST_CASE_P(FlatHashSet, ModifiersTest, SetTypes);
TEST(FlatHashSet, EmplaceString) {
std::vector<std::string> v = {"a", "b"};
absl::flat_hash_set<absl::string_view> hs(v.begin(), v.end());
EXPECT_THAT(hs, UnorderedElementsAreArray(v));
}
TEST(FlatHashSet, BitfieldArgument) {
union {
int n : 1;
};
n = 0;
absl::flat_hash_set<int> s = {n};
s.insert(n);
s.insert(s.end(), n);
s.insert({n});
s.erase(n);
s.count(n);
s.prefetch(n);
s.find(n);
s.contains(n);
s.equal_range(n);
}
TEST(FlatHashSet, MergeExtractInsert) {
struct Hash {
size_t operator()(const std::unique_ptr<int>& p) const { return *p; }
};
struct Eq {
bool operator()(const std::unique_ptr<int>& a,
const std::unique_ptr<int>& b) const {
return *a == *b;
}
};
absl::flat_hash_set<std::unique_ptr<int>, Hash, Eq> set1, set2;
set1.insert(absl::make_unique<int>(7));
set1.insert(absl::make_unique<int>(17));
set2.insert(absl::make_unique<int>(7));
set2.insert(absl::make_unique<int>(19));
EXPECT_THAT(set1, UnorderedElementsAre(Pointee(7), Pointee(17)));
EXPECT_THAT(set2, UnorderedElementsAre(Pointee(7), Pointee(19)));
set1.merge(set2);
EXPECT_THAT(set1, UnorderedElementsAre(Pointee(7), Pointee(17), Pointee(19)));
EXPECT_THAT(set2, UnorderedElementsAre(Pointee(7)));
auto node = set1.extract(absl::make_unique<int>(7));
EXPECT_TRUE(node);
EXPECT_THAT(node.value(), Pointee(7));
EXPECT_THAT(set1, UnorderedElementsAre(Pointee(17), Pointee(19)));
auto insert_result = set2.insert(std::move(node));
EXPECT_FALSE(node);
EXPECT_FALSE(insert_result.inserted);
EXPECT_TRUE(insert_result.node);
EXPECT_THAT(insert_result.node.value(), Pointee(7));
EXPECT_EQ(**insert_result.position, 7);
EXPECT_NE(insert_result.position->get(), insert_result.node.value().get());
EXPECT_THAT(set2, UnorderedElementsAre(Pointee(7)));
node = set1.extract(absl::make_unique<int>(17));
EXPECT_TRUE(node);
EXPECT_THAT(node.value(), Pointee(17));
EXPECT_THAT(set1, UnorderedElementsAre(Pointee(19)));
node.value() = absl::make_unique<int>(23);
insert_result = set2.insert(std::move(node));
EXPECT_FALSE(node);
EXPECT_TRUE(insert_result.inserted);
EXPECT_FALSE(insert_result.node);
EXPECT_EQ(**insert_result.position, 23);
EXPECT_THAT(set2, UnorderedElementsAre(Pointee(7), Pointee(23)));
}
} // namespace
} // namespace container_internal
} // inline namespace lts_2018_12_18
} // namespace absl
......@@ -66,7 +66,7 @@ BENCHMARK(BM_StdVectorFill)->Range(0, 1024);
// The purpose of the next two benchmarks is to verify that
// absl::InlinedVector is efficient when moving is more efficent than
// copying. To do so, we use strings that are larger than the short
// std::string optimization.
// string optimization.
bool StringRepresentedInline(std::string s) {
const char* chars = s.data();
std::string s1 = std::move(s);
......
......@@ -31,6 +31,7 @@
#include "absl/base/internal/raw_logging.h"
#include "absl/base/macros.h"
#include "absl/container/internal/test_instance_tracker.h"
#include "absl/hash/hash_testing.h"
#include "absl/memory/memory.h"
#include "absl/strings/str_cat.h"
......@@ -905,6 +906,8 @@ TYPED_TEST_P(InstanceTest, Swap) {
InstanceTracker tracker;
InstanceVec a, b;
const size_t inlined_capacity = a.capacity();
auto min_len = std::min(l1, l2);
auto max_len = std::max(l1, l2);
for (int i = 0; i < l1; i++) a.push_back(Instance(i));
for (int i = 0; i < l2; i++) b.push_back(Instance(100+i));
EXPECT_EQ(tracker.instances(), l1 + l2);
......@@ -918,15 +921,15 @@ TYPED_TEST_P(InstanceTest, Swap) {
EXPECT_EQ(tracker.swaps(), 0); // Allocations are swapped.
EXPECT_EQ(tracker.moves(), 0);
} else if (a.size() <= inlined_capacity && b.size() <= inlined_capacity) {
EXPECT_EQ(tracker.swaps(), std::min(l1, l2));
// TODO(bsamwel): This should use moves when the type is movable.
EXPECT_EQ(tracker.copies(), std::max(l1, l2) - std::min(l1, l2));
EXPECT_EQ(tracker.swaps(), min_len);
EXPECT_EQ((tracker.moves() ? tracker.moves() : tracker.copies()),
max_len - min_len);
} else {
// One is allocated and the other isn't. The allocation is transferred
// without copying elements, and the inlined instances are copied/moved.
EXPECT_EQ(tracker.swaps(), 0);
// TODO(bsamwel): This should use moves when the type is movable.
EXPECT_EQ(tracker.copies(), std::min(l1, l2));
EXPECT_EQ((tracker.moves() ? tracker.moves() : tracker.copies()),
min_len);
}
EXPECT_EQ(l1, b.size());
......@@ -1725,42 +1728,87 @@ TEST(AllocatorSupportTest, ScopedAllocatorWorks) {
std::scoped_allocator_adaptor<CountingAllocator<StdVector>>;
using AllocVec = absl::InlinedVector<StdVector, 4, MyAlloc>;
// MSVC 2017's std::vector allocates different amounts of memory in debug
// versus opt mode.
int64_t test_allocated = 0;
StdVector v(CountingAllocator<int>{&test_allocated});
// The amount of memory allocated by a default constructed vector<int>
auto default_std_vec_allocated = test_allocated;
v.push_back(1);
// The amound of memory allocated by a copy-constructed vector<int> with one
// element.
int64_t one_element_std_vec_copy_allocated = test_allocated;
int64_t allocated = 0;
AllocVec vec(MyAlloc{CountingAllocator<StdVector>{&allocated}});
EXPECT_EQ(allocated, 0);
// This default constructs a vector<int>, but the allocator should pass itself
// into the vector<int>.
// into the vector<int>, so check allocation compared to that.
// The absl::InlinedVector does not allocate any memory.
// The vector<int> does not allocate any memory.
// The vector<int> may allocate any memory.
auto expected = default_std_vec_allocated;
vec.resize(1);
EXPECT_EQ(allocated, 0);
EXPECT_EQ(allocated, expected);
// We make vector<int> allocate memory.
// It must go through the allocator even though we didn't construct the
// vector directly.
// vector directly. This assumes that vec[0] doesn't need to grow its
// allocation.
expected += sizeof(int);
vec[0].push_back(1);
EXPECT_EQ(allocated, sizeof(int) * 1);
EXPECT_EQ(allocated, expected);
// Another allocating vector.
expected += one_element_std_vec_copy_allocated;
vec.push_back(vec[0]);
EXPECT_EQ(allocated, sizeof(int) * 2);
EXPECT_EQ(allocated, expected);
// Overflow the inlined memory.
// The absl::InlinedVector will now allocate.
expected += sizeof(StdVector) * 8 + default_std_vec_allocated * 3;
vec.resize(5);
EXPECT_EQ(allocated, sizeof(int) * 2 + sizeof(StdVector) * 8);
EXPECT_EQ(allocated, expected);
// Adding one more in external mode should also work.
expected += one_element_std_vec_copy_allocated;
vec.push_back(vec[0]);
EXPECT_EQ(allocated, sizeof(int) * 3 + sizeof(StdVector) * 8);
EXPECT_EQ(allocated, expected);
// And extending these should still work.
// And extending these should still work. This assumes that vec[0] does not
// need to grow its allocation.
expected += sizeof(int);
vec[0].push_back(1);
EXPECT_EQ(allocated, sizeof(int) * 4 + sizeof(StdVector) * 8);
EXPECT_EQ(allocated, expected);
vec.clear();
EXPECT_EQ(allocated, 0);
}
TEST(AllocatorSupportTest, SizeAllocConstructor) {
constexpr int inlined_size = 4;
using Alloc = CountingAllocator<int>;
using AllocVec = absl::InlinedVector<int, inlined_size, Alloc>;
{
auto len = inlined_size / 2;
int64_t allocated = 0;
auto v = AllocVec(len, Alloc(&allocated));
// Inline storage used; allocator should not be invoked
EXPECT_THAT(allocated, 0);
EXPECT_THAT(v, AllOf(SizeIs(len), Each(0)));
}
{
auto len = inlined_size * 2;
int64_t allocated = 0;
auto v = AllocVec(len, Alloc(&allocated));
// Out of line storage used; allocation of 8 elements expected
EXPECT_THAT(allocated, len * sizeof(int));
EXPECT_THAT(v, AllOf(SizeIs(len), Each(0)));
}
}
} // anonymous namespace
// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Helper class to perform the Empty Base Optimization.
// Ts can contain classes and non-classes, empty or not. For the ones that
// are empty classes, we perform the optimization. If all types in Ts are empty
// classes, then CompressedTuple<Ts...> is itself an empty class.
//
// To access the members, use member get<N>() function.
//
// Eg:
// absl::container_internal::CompressedTuple<int, T1, T2, T3> value(7, t1, t2,
// t3);
// assert(value.get<0>() == 7);
// T1& t1 = value.get<1>();
// const T2& t2 = value.get<2>();
// ...
//
// http://en.cppreference.com/w/cpp/language/ebo
#ifndef ABSL_CONTAINER_INTERNAL_COMPRESSED_TUPLE_H_
#define ABSL_CONTAINER_INTERNAL_COMPRESSED_TUPLE_H_
#include <tuple>
#include <type_traits>
#include <utility>
#include "absl/utility/utility.h"
#ifdef _MSC_VER
// We need to mark these classes with this declspec to ensure that
// CompressedTuple happens.
#define ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC __declspec(empty_bases)
#else // _MSC_VER
#define ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC
#endif // _MSC_VER
namespace absl {
inline namespace lts_2018_12_18 {
namespace container_internal {
template <typename... Ts>
class CompressedTuple;
namespace internal_compressed_tuple {
template <typename D, size_t I>
struct Elem;
template <typename... B, size_t I>
struct Elem<CompressedTuple<B...>, I>
: std::tuple_element<I, std::tuple<B...>> {};
template <typename D, size_t I>
using ElemT = typename Elem<D, I>::type;
// Use the __is_final intrinsic if available. Where it's not available, classes
// declared with the 'final' specifier cannot be used as CompressedTuple
// elements.
// TODO(sbenza): Replace this with std::is_final in C++14.
template <typename T>
constexpr bool IsFinal() {
#if defined(__clang__) || defined(__GNUC__)
return __is_final(T);
#else
return false;
#endif
}
template <typename T>
constexpr bool ShouldUseBase() {
return std::is_class<T>::value && std::is_empty<T>::value && !IsFinal<T>();
}
// The storage class provides two specializations:
// - For empty classes, it stores T as a base class.
// - For everything else, it stores T as a member.
template <typename D, size_t I, bool = ShouldUseBase<ElemT<D, I>>()>
struct Storage {
using T = ElemT<D, I>;
T value;
constexpr Storage() = default;
explicit constexpr Storage(T&& v) : value(absl::forward<T>(v)) {}
constexpr const T& get() const { return value; }
T& get() { return value; }
};
template <typename D, size_t I>
struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC Storage<D, I, true>
: ElemT<D, I> {
using T = internal_compressed_tuple::ElemT<D, I>;
constexpr Storage() = default;
explicit constexpr Storage(T&& v) : T(absl::forward<T>(v)) {}
constexpr const T& get() const { return *this; }
T& get() { return *this; }
};
template <typename D, typename I>
struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTupleImpl;
template <typename... Ts, size_t... I>
struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC
CompressedTupleImpl<CompressedTuple<Ts...>, absl::index_sequence<I...>>
// We use the dummy identity function through std::integral_constant to
// convince MSVC of accepting and expanding I in that context. Without it
// you would get:
// error C3548: 'I': parameter pack cannot be used in this context
: Storage<CompressedTuple<Ts...>,
std::integral_constant<size_t, I>::value>... {
constexpr CompressedTupleImpl() = default;
explicit constexpr CompressedTupleImpl(Ts&&... args)
: Storage<CompressedTuple<Ts...>, I>(absl::forward<Ts>(args))... {}
};
} // namespace internal_compressed_tuple
// Helper class to perform the Empty Base Class Optimization.
// Ts can contain classes and non-classes, empty or not. For the ones that
// are empty classes, we perform the CompressedTuple. If all types in Ts are
// empty classes, then CompressedTuple<Ts...> is itself an empty class.
//
// To access the members, use member .get<N>() function.
//
// Eg:
// absl::container_internal::CompressedTuple<int, T1, T2, T3> value(7, t1, t2,
// t3);
// assert(value.get<0>() == 7);
// T1& t1 = value.get<1>();
// const T2& t2 = value.get<2>();
// ...
//
// http://en.cppreference.com/w/cpp/language/ebo
template <typename... Ts>
class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple
: private internal_compressed_tuple::CompressedTupleImpl<
CompressedTuple<Ts...>, absl::index_sequence_for<Ts...>> {
private:
template <int I>
using ElemT = internal_compressed_tuple::ElemT<CompressedTuple, I>;
public:
constexpr CompressedTuple() = default;
explicit constexpr CompressedTuple(Ts... base)
: CompressedTuple::CompressedTupleImpl(absl::forward<Ts>(base)...) {}
template <int I>
ElemT<I>& get() {
return internal_compressed_tuple::Storage<CompressedTuple, I>::get();
}
template <int I>
constexpr const ElemT<I>& get() const {
return internal_compressed_tuple::Storage<CompressedTuple, I>::get();
}
};
// Explicit specialization for a zero-element tuple
// (needed to avoid ambiguous overloads for the default constructor).
template <>
class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple<> {};
} // namespace container_internal
} // inline namespace lts_2018_12_18
} // namespace absl
#undef ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC
#endif // ABSL_CONTAINER_INTERNAL_COMPRESSED_TUPLE_H_
// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "absl/container/internal/compressed_tuple.h"
#include <string>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
namespace absl {
inline namespace lts_2018_12_18 {
namespace container_internal {
namespace {
template <int>
struct Empty {};
template <typename T>
struct NotEmpty {
T value;
};
template <typename T, typename U>
struct TwoValues {
T value1;
U value2;
};
TEST(CompressedTupleTest, Sizeof) {
EXPECT_EQ(sizeof(int), sizeof(CompressedTuple<int>));
EXPECT_EQ(sizeof(int), sizeof(CompressedTuple<int, Empty<0>>));
EXPECT_EQ(sizeof(int), sizeof(CompressedTuple<int, Empty<0>, Empty<1>>));
EXPECT_EQ(sizeof(int),
sizeof(CompressedTuple<int, Empty<0>, Empty<1>, Empty<2>>));
EXPECT_EQ(sizeof(TwoValues<int, double>),
sizeof(CompressedTuple<int, NotEmpty<double>>));
EXPECT_EQ(sizeof(TwoValues<int, double>),
sizeof(CompressedTuple<int, Empty<0>, NotEmpty<double>>));
EXPECT_EQ(sizeof(TwoValues<int, double>),
sizeof(CompressedTuple<int, Empty<0>, NotEmpty<double>, Empty<1>>));
}
TEST(CompressedTupleTest, Access) {
struct S {
std::string x;
};
CompressedTuple<int, Empty<0>, S> x(7, {}, S{"ABC"});
EXPECT_EQ(sizeof(x), sizeof(TwoValues<int, S>));
EXPECT_EQ(7, x.get<0>());
EXPECT_EQ("ABC", x.get<2>().x);
}
TEST(CompressedTupleTest, NonClasses) {
CompressedTuple<int, const char*> x(7, "ABC");
EXPECT_EQ(7, x.get<0>());
EXPECT_STREQ("ABC", x.get<1>());
}
TEST(CompressedTupleTest, MixClassAndNonClass) {
CompressedTuple<int, const char*, Empty<0>, NotEmpty<double>> x(7, "ABC", {},
{1.25});
struct Mock {
int v;
const char* p;
double d;
};
EXPECT_EQ(sizeof(x), sizeof(Mock));
EXPECT_EQ(7, x.get<0>());
EXPECT_STREQ("ABC", x.get<1>());
EXPECT_EQ(1.25, x.get<3>().value);
}
TEST(CompressedTupleTest, Nested) {
CompressedTuple<int, CompressedTuple<int>,
CompressedTuple<int, CompressedTuple<int>>>
x(1, CompressedTuple<int>(2),
CompressedTuple<int, CompressedTuple<int>>(3, CompressedTuple<int>(4)));
EXPECT_EQ(1, x.get<0>());
EXPECT_EQ(2, x.get<1>().get<0>());
EXPECT_EQ(3, x.get<2>().get<0>());
EXPECT_EQ(4, x.get<2>().get<1>().get<0>());
CompressedTuple<Empty<0>, Empty<0>,
CompressedTuple<Empty<0>, CompressedTuple<Empty<0>>>>
y;
std::set<Empty<0>*> empties{&y.get<0>(), &y.get<1>(), &y.get<2>().get<0>(),
&y.get<2>().get<1>().get<0>()};
#ifdef _MSC_VER
// MSVC has a bug where many instances of the same base class are layed out in
// the same address when using __declspec(empty_bases).
// This will be fixed in a future version of MSVC.
int expected = 1;
#else
int expected = 4;
#endif
EXPECT_EQ(expected, sizeof(y));
EXPECT_EQ(expected, empties.size());
EXPECT_EQ(sizeof(y), sizeof(Empty<0>) * empties.size());
EXPECT_EQ(4 * sizeof(char),
sizeof(CompressedTuple<CompressedTuple<char, char>,
CompressedTuple<char, char>>));
EXPECT_TRUE(
(std::is_empty<CompressedTuple<CompressedTuple<Empty<0>>,
CompressedTuple<Empty<1>>>>::value));
}
TEST(CompressedTupleTest, Reference) {
int i = 7;
std::string s = "Very long std::string that goes in the heap";
CompressedTuple<int, int&, std::string, std::string&> x(i, i, s, s);
// Sanity check. We should have not moved from `s`
EXPECT_EQ(s, "Very long std::string that goes in the heap");
EXPECT_EQ(x.get<0>(), x.get<1>());
EXPECT_NE(&x.get<0>(), &x.get<1>());
EXPECT_EQ(&x.get<1>(), &i);
EXPECT_EQ(x.get<2>(), x.get<3>());
EXPECT_NE(&x.get<2>(), &x.get<3>());
EXPECT_EQ(&x.get<3>(), &s);
}
TEST(CompressedTupleTest, NoElements) {
CompressedTuple<> x;
static_cast<void>(x); // Silence -Wunused-variable.
EXPECT_TRUE(std::is_empty<CompressedTuple<>>::value);
}
TEST(CompressedTupleTest, Constexpr) {
constexpr CompressedTuple<int, double, CompressedTuple<int>> x(
7, 1.25, CompressedTuple<int>(5));
constexpr int x0 = x.get<0>();
constexpr double x1 = x.get<1>();
constexpr int x2 = x.get<2>().get<0>();
EXPECT_EQ(x0, 7);
EXPECT_EQ(x1, 1.25);
EXPECT_EQ(x2, 5);
}
#if defined(__clang__) || defined(__GNUC__)
TEST(CompressedTupleTest, EmptyFinalClass) {
struct S final {
int f() const { return 5; }
};
CompressedTuple<S> x;
EXPECT_EQ(x.get<0>().f(), 5);
}
#endif
} // namespace
} // namespace container_internal
} // inline namespace lts_2018_12_18
} // namespace absl
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment