Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Danfoss VLT Micro - 176F7330 #2267

Open
wants to merge 144 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
Show all changes
144 commits
Select commit Hold shift + click to select a range
5dd9547
starting to create the gpio module
cagnulein Jan 5, 2022
963beca
first very raw release #525
Jan 11, 2022
5c344a5
fixed zwift interface on gpiotreadmill
cagnulein Jan 13, 2022
ab8fe4f
fix build issue #525
cagnulein Jan 14, 2022
d7e6cf5
fix build issue #525
cagnulein Jan 14, 2022
0aa1284
fix gpio delay #525
cagnulein Jan 14, 2022
5aaa37e
Improve the setting of the speed and the slope
Jan 16, 2022
4e81c60
Merge pull request #587 from december-soul/treadmill-gpio
cagnulein Jan 16, 2022
8539fe9
move GPIO worker into thread
december-soul Jan 25, 2022
5e93ea9
Merge branch 'cagnulein:treadmill-gpio' into treadmill-gpio
december-soul Jan 25, 2022
8a56aab
add descructor to clean up thread
december-soul Jan 25, 2022
9d2ef58
Merge branch 'treadmill-gpio' of https://github.com/december-soul/qdo…
december-soul Jan 25, 2022
477f58c
use semaphore to avoid press simultaneously the buttons
december-soul Jan 27, 2022
6aacfe3
Merge pull request #627 from december-soul/treadmill-gpio
cagnulein Jan 27, 2022
8f41a2c
added connectedAndDiscovered(); to gpiotreadmill
cagnulein Jul 27, 2022
283c101
Merge branch 'master' into treadmill-gpio
cagnulein Jul 27, 2022
f195432
Update bluetooth.cpp
cagnulein Jul 28, 2022
f8f8e6c
Local input for headless mode #938
cagnulein Sep 12, 2022
ad4514a
Local input for headless mode #938
cagnulein Sep 12, 2022
4f30516
Merge branch 'master' into treadmill-gpio
cagnulein Sep 12, 2022
7a58c77
Local input for headless mode #938
cagnulein Sep 12, 2022
7d88f9b
Merge branch 'treadmill-gpio' of https://github.com/cagnulein/qdomyos…
cagnulein Sep 12, 2022
70dff0b
Rename consolereader.h to ConsoleReader.h
cagnulein Sep 13, 2022
21349a6
Rename consolereader.cpp to ConsoleReader.cpp
cagnulein Sep 13, 2022
daa8dca
Update main.cpp
cagnulein Sep 13, 2022
6a16672
fixing inclination calls #938
cagnulein Sep 15, 2022
d693743
Local input for headless mode #938
cagnulein Sep 16, 2022
c9b1002
workaround
cagnulein Sep 17, 2022
94f5c37
disabling qml too if the no-gui selector is enabled
cagnulein Sep 19, 2022
d9034ef
Local input for headless mode #938
cagnulein Sep 26, 2022
5b0bd28
Merge branch 'master' into treadmill-modbus
cagnulein Dec 15, 2023
d136b72
Update qdomyos-zwift.pri
cagnulein Dec 15, 2023
f33f06d
modbus porting completed
cagnulein Dec 15, 2023
9e916bd
Update bluetooth.cpp
cagnulein Dec 15, 2023
6761b1b
fixing CI for the other archs
cagnulein Dec 15, 2023
4a91c37
Update qdomyos-zwift.pri
cagnulein Dec 15, 2023
57c951c
fixing android build
cagnulein Dec 15, 2023
3b15f07
Update gpiotreadmill.h
cagnulein Dec 15, 2023
5b59e5d
removed debug
cagnulein Dec 15, 2023
76bc2bd
debug restored
cagnulein Dec 15, 2023
b44e482
fixing linker
cagnulein Dec 15, 2023
7d7fd41
removing consolereader
cagnulein Dec 15, 2023
6ca55b3
Update qdomyos-zwift.pri
cagnulein Dec 15, 2023
af73de3
Update qdomyos-zwift.pri
cagnulein Dec 15, 2023
a80b66b
Update qdomyos-zwift.pri
cagnulein Dec 15, 2023
536f876
Update main.yml
cagnulein Dec 15, 2023
39a6c74
Update main.yml
cagnulein Dec 15, 2023
a06f9f7
Update main.yml
cagnulein Dec 15, 2023
871b403
Update gpiotreadmill.cpp
cagnulein Dec 15, 2023
f41944f
adapting for http://www.chinalctech.com/m/view.php?aid=490&fbclid=IwA…
cagnulein Dec 15, 2023
4210e2b
fixing init and forcing gpio treadmill
cagnulein Dec 15, 2023
b2d666b
Update gpiotreadmill.cpp
cagnulein Dec 16, 2023
d279bc9
crash fixed
cagnulein Dec 16, 2023
a3aa6f9
speeding up the change
cagnulein Dec 16, 2023
9b8e92b
Update gpiotreadmill.h
cagnulein Dec 16, 2023
550b84e
Update gpiotreadmill.h
cagnulein Dec 16, 2023
62df4cc
close gpiotreadmill.cpp
cagnulein Dec 16, 2023
064b34d
minstepspeed to 0.1
cagnulein Dec 17, 2023
a1c8b9b
Merge branch 'treadmill-modbus' of https://github.com/cagnulein/qdomy…
cagnulein Dec 17, 2023
6153f42
Update gpiotreadmill.cpp
cagnulein Dec 17, 2023
0409ade
key pressed
cagnulein Dec 17, 2023
1b13d8d
Update homeform.cpp
cagnulein Dec 17, 2023
d23115e
modbus error handling
cagnulein Dec 17, 2023
b02c9de
Merge branch 'master' into treadmill-modbus
cagnulein Dec 23, 2023
6fda282
Merge branch 'master' into treadmill-modbus
cagnulein Dec 23, 2023
8043b28
first test on CI
cagnulein Jan 1, 2024
6dd8f6c
Update main.yml
cagnulein Jan 1, 2024
c45c842
Update qdomyos-zwift.pri
cagnulein Jan 1, 2024
eeae2ee
mingw-w64-x86_64-protobuf
cagnulein Jan 1, 2024
6afc73f
Update qdomyos-zwift.pri
cagnulein Jan 1, 2024
10f7387
Update main.yml
cagnulein Jan 1, 2024
128812b
adding protobuf to src folder
cagnulein Jan 1, 2024
5057ddb
Update main.yml
cagnulein Jan 1, 2024
5e5ee11
Update main.yml
cagnulein Jan 1, 2024
8dd29e2
adding absl
cagnulein Jan 3, 2024
ffeb51e
absl from mingw
cagnulein Jan 3, 2024
c3b04dc
building protobuf
cagnulein Jan 3, 2024
58270e7
Update main.yml
cagnulein Jan 3, 2024
9b34624
Update main.yml
cagnulein Jan 3, 2024
6663b2c
Update main.yml
cagnulein Jan 3, 2024
06123b5
Update main.yml
cagnulein Jan 4, 2024
c5e53a9
Update main.yml
cagnulein Jan 4, 2024
cae6726
Update main.yml
cagnulein Jan 4, 2024
0e8bab3
Update main.yml
cagnulein Jan 4, 2024
af0abb3
Update main.yml
cagnulein Jan 4, 2024
9413349
Update main.yml
cagnulein Jan 4, 2024
e4e4952
adding mingw64 binary
cagnulein Jan 4, 2024
b059dd6
adding mingw libabsl
cagnulein Jan 4, 2024
9f758dd
Update main.yml
cagnulein Jan 4, 2024
9de579f
builds on mingw
cagnulein Jan 16, 2024
194ca72
required lib for libabsl
cagnulein Jan 16, 2024
efe0cbc
trying to fix mingw build
cagnulein Jan 16, 2024
6621c83
Update main.yml
cagnulein Jan 16, 2024
a3c0bec
Merge branch 'master' into zwift-api-windows
cagnulein Jan 31, 2024
737f1fa
trying to msvc first
cagnulein Jan 31, 2024
f804c01
Update qdomyos-zwift.pri
cagnulein Jan 31, 2024
49f6fa9
trying to put the protobuf lib on the same src dir
cagnulein Jan 31, 2024
323d051
Merge branch 'master' into zwift-api-windows
cagnulein Feb 26, 2024
4876712
again msvc first
cagnulein Feb 26, 2024
24078a9
JLL T550 #2161
cagnulein Feb 26, 2024
187dd9a
Update main.yml
cagnulein Feb 27, 2024
cbf0c91
Update main.yml
cagnulein Feb 27, 2024
7e12ca0
Update qdomyos-zwift.pri
cagnulein Feb 27, 2024
183e7dc
Revert "Update qdomyos-zwift.pri"
cagnulein Feb 27, 2024
dadaece
adding absl on msvc
cagnulein Feb 27, 2024
6603195
building absl inside protobuf for debug
cagnulein Feb 27, 2024
f23dda5
Update qdomyos-zwift.pri
cagnulein Feb 27, 2024
b5f90bd
adding vcpkg
cagnulein Feb 27, 2024
cd0040c
adding submodule
cagnulein Feb 27, 2024
1beb7f6
vcpkg
cagnulein Feb 27, 2024
f0541b7
Update main.yml
cagnulein Feb 27, 2024
d36b28e
Update main.yml
cagnulein Feb 27, 2024
f6bdbfa
Update main.yml
cagnulein Feb 27, 2024
58b4ddd
Update main.yml
cagnulein Feb 27, 2024
d1f51c4
using vcpkg
cagnulein Feb 27, 2024
598a2a6
Update main.yml
cagnulein Feb 27, 2024
d865887
Update qdomyos-zwift.pri
cagnulein Feb 27, 2024
1cdfb1e
Update qdomyos-zwift.pri
cagnulein Feb 27, 2024
9f4ab19
include removing, using vcpkg
cagnulein Feb 27, 2024
eb52fcf
Update main.yml
cagnulein Feb 27, 2024
d5e795f
Update main.yml
cagnulein Feb 27, 2024
4ac43dc
protobuf
cagnulein Feb 27, 2024
4bb2012
Update trainprogram.cpp
cagnulein Feb 27, 2024
c667974
Update main.yml
cagnulein Feb 27, 2024
571fd08
starting to port the same on linux
cagnulein Feb 27, 2024
4c6401e
Update trainprogram.cpp
cagnulein Feb 27, 2024
24bf95a
Update main.yml
cagnulein Feb 28, 2024
d0f2ab2
Update main.yml
cagnulein Feb 28, 2024
5465e30
Merge branch 'master' into zwift-api-windows
cagnulein Feb 29, 2024
97856b7
Update trainprogram.cpp
cagnulein Feb 29, 2024
6b825c6
Update main.yml
cagnulein Feb 29, 2024
d4c5853
Update qdomyos-zwift.pri
cagnulein Feb 29, 2024
70fd6f9
Update main.yml
cagnulein Feb 29, 2024
23c8628
Merge branch 'master' into zwift-api-windows
cagnulein Feb 29, 2024
8bcacf5
Merge branch 'master' into treadmill-modbus
cagnulein Feb 29, 2024
2cba38c
Merge branch 'zwift-api-windows' into treadmill-modbus
cagnulein Feb 29, 2024
e2feffa
fixing includes
cagnulein Feb 29, 2024
daaf788
first commit
cagnulein Apr 2, 2024
7628457
Update main.cpp
cagnulein Apr 8, 2024
50a189b
Merge branch 'master' into Danfoss-VLT-Micro---176F7330
cagnulein Apr 8, 2024
15d0c82
trying to read 1 register at a time
cagnulein Apr 9, 2024
05719c1
adding start, stop and frequency change
cagnulein Apr 15, 2024
252a455
Update gpiotreadmill.cpp
cagnulein Apr 17, 2024
e599808
Update gpiotreadmill.cpp
cagnulein Apr 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
absl from mingw
cagnulein committed Jan 3, 2024
commit ffeb51eecc525c981b138325ca33c0b12d9aa3be
114 changes: 57 additions & 57 deletions src/absl/algorithm/container.h
Original file line number Diff line number Diff line change
@@ -77,9 +77,8 @@ using ContainerIterPairType =
decltype(std::make_pair(ContainerIter<C1>(), ContainerIter<C2>()));

template <typename C>
using ContainerDifferenceType =
decltype(std::distance(std::declval<ContainerIter<C>>(),
std::declval<ContainerIter<C>>()));
using ContainerDifferenceType = decltype(std::distance(
std::declval<ContainerIter<C>>(), std::declval<ContainerIter<C>>()));

template <typename C>
using ContainerPointerType =
@@ -97,10 +96,14 @@ using ContainerPointerType =
// These are meant for internal use only.

template <typename C>
ContainerIter<C> c_begin(C& c) { return begin(c); }
ContainerIter<C> c_begin(C& c) {
return begin(c);
}

template <typename C>
ContainerIter<C> c_end(C& c) { return end(c); }
ContainerIter<C> c_end(C& c) {
return end(c);
}

template <typename T>
struct IsUnorderedContainer : std::false_type {};
@@ -343,8 +346,8 @@ container_algorithm_internal::ContainerDifferenceType<const C> c_count_if(
// return the first element where two ordered containers differ. Applies `==` to
// the first N elements of `c1` and `c2`, where N = min(size(c1), size(c2)).
template <typename C1, typename C2>
container_algorithm_internal::ContainerIterPairType<C1, C2>
c_mismatch(C1& c1, C2& c2) {
container_algorithm_internal::ContainerIterPairType<C1, C2> c_mismatch(C1& c1,
C2& c2) {
auto first1 = container_algorithm_internal::c_begin(c1);
auto last1 = container_algorithm_internal::c_end(c1);
auto first2 = container_algorithm_internal::c_begin(c2);
@@ -365,8 +368,8 @@ c_mismatch(C1& c1, C2& c2) {
// the function's test condition. Applies `pred`to the first N elements of `c1`
// and `c2`, where N = min(size(c1), size(c2)).
template <typename C1, typename C2, typename BinaryPredicate>
container_algorithm_internal::ContainerIterPairType<C1, C2>
c_mismatch(C1& c1, C2& c2, BinaryPredicate pred) {
container_algorithm_internal::ContainerIterPairType<C1, C2> c_mismatch(
C1& c1, C2& c2, BinaryPredicate pred) {
auto first1 = container_algorithm_internal::c_begin(c1);
auto last1 = container_algorithm_internal::c_end(c1);
auto first2 = container_algorithm_internal::c_begin(c2);
@@ -655,31 +658,29 @@ OutputIterator c_replace_copy(const C& c, OutputIterator result, T&& old_value,
// some condition, and return the results within an iterator.
template <typename C, typename OutputIterator, typename Pred, typename T>
OutputIterator c_replace_copy_if(const C& c, OutputIterator result, Pred&& pred,
T&& new_value) {
const T& new_value) {
return std::replace_copy_if(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c), result,
std::forward<Pred>(pred),
std::forward<T>(new_value));
std::forward<Pred>(pred), new_value);
}

// c_fill()
//
// Container-based version of the <algorithm> `std::fill()` function to fill a
// container with some value.
template <typename C, typename T>
void c_fill(C& c, T&& value) {
void c_fill(C& c, const T& value) {
std::fill(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c), std::forward<T>(value));
container_algorithm_internal::c_end(c), value);
}

// c_fill_n()
//
// Container-based version of the <algorithm> `std::fill_n()` function to fill
// the first N elements in a container with some value.
template <typename C, typename Size, typename T>
void c_fill_n(C& c, Size n, T&& value) {
std::fill_n(container_algorithm_internal::c_begin(c), n,
std::forward<T>(value));
void c_fill_n(C& c, Size n, const T& value) {
std::fill_n(container_algorithm_internal::c_begin(c), n, value);
}

// c_generate()
@@ -716,10 +717,11 @@ container_algorithm_internal::ContainerIter<C> c_generate_n(C& c, Size n,
// copy a container's elements while removing any elements matching the given
// `value`.
template <typename C, typename OutputIterator, typename T>
OutputIterator c_remove_copy(const C& c, OutputIterator result, T&& value) {
OutputIterator c_remove_copy(const C& c, OutputIterator result,
const T& value) {
return std::remove_copy(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c), result,
std::forward<T>(value));
value);
}

// c_remove_copy_if()
@@ -1064,20 +1066,19 @@ void c_nth_element(
// which does not compare less than `value`.
template <typename Sequence, typename T>
container_algorithm_internal::ContainerIter<Sequence> c_lower_bound(
Sequence& sequence, T&& value) {
Sequence& sequence, const T& value) {
return std::lower_bound(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence),
std::forward<T>(value));
container_algorithm_internal::c_end(sequence), value);
}

// Overload of c_lower_bound() for performing a `comp` comparison other than
// the default `operator<`.
template <typename Sequence, typename T, typename LessThan>
container_algorithm_internal::ContainerIter<Sequence> c_lower_bound(
Sequence& sequence, T&& value, LessThan&& comp) {
Sequence& sequence, const T& value, LessThan&& comp) {
return std::lower_bound(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence),
std::forward<T>(value), std::forward<LessThan>(comp));
container_algorithm_internal::c_end(sequence), value,
std::forward<LessThan>(comp));
}

// c_upper_bound()
@@ -1087,20 +1088,19 @@ container_algorithm_internal::ContainerIter<Sequence> c_lower_bound(
// which is greater than `value`.
template <typename Sequence, typename T>
container_algorithm_internal::ContainerIter<Sequence> c_upper_bound(
Sequence& sequence, T&& value) {
Sequence& sequence, const T& value) {
return std::upper_bound(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence),
std::forward<T>(value));
container_algorithm_internal::c_end(sequence), value);
}

// Overload of c_upper_bound() for performing a `comp` comparison other than
// the default `operator<`.
template <typename Sequence, typename T, typename LessThan>
container_algorithm_internal::ContainerIter<Sequence> c_upper_bound(
Sequence& sequence, T&& value, LessThan&& comp) {
Sequence& sequence, const T& value, LessThan&& comp) {
return std::upper_bound(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence),
std::forward<T>(value), std::forward<LessThan>(comp));
container_algorithm_internal::c_end(sequence), value,
std::forward<LessThan>(comp));
}

// c_equal_range()
@@ -1110,20 +1110,19 @@ container_algorithm_internal::ContainerIter<Sequence> c_upper_bound(
// sorted container which compare equal to `value`.
template <typename Sequence, typename T>
container_algorithm_internal::ContainerIterPairType<Sequence, Sequence>
c_equal_range(Sequence& sequence, T&& value) {
c_equal_range(Sequence& sequence, const T& value) {
return std::equal_range(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence),
std::forward<T>(value));
container_algorithm_internal::c_end(sequence), value);
}

// Overload of c_equal_range() for performing a `comp` comparison other than
// the default `operator<`.
template <typename Sequence, typename T, typename LessThan>
container_algorithm_internal::ContainerIterPairType<Sequence, Sequence>
c_equal_range(Sequence& sequence, T&& value, LessThan&& comp) {
c_equal_range(Sequence& sequence, const T& value, LessThan&& comp) {
return std::equal_range(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence),
std::forward<T>(value), std::forward<LessThan>(comp));
container_algorithm_internal::c_end(sequence), value,
std::forward<LessThan>(comp));
}

// c_binary_search()
@@ -1132,20 +1131,20 @@ c_equal_range(Sequence& sequence, T&& value, LessThan&& comp) {
// to test if any element in the sorted container contains a value equivalent to
// 'value'.
template <typename Sequence, typename T>
bool c_binary_search(Sequence&& sequence, T&& value) {
bool c_binary_search(const Sequence& sequence, const T& value) {
return std::binary_search(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence),
std::forward<T>(value));
value);
}

// Overload of c_binary_search() for performing a `comp` comparison other than
// the default `operator<`.
template <typename Sequence, typename T, typename LessThan>
bool c_binary_search(Sequence&& sequence, T&& value, LessThan&& comp) {
bool c_binary_search(const Sequence& sequence, const T& value,
LessThan&& comp) {
return std::binary_search(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence),
std::forward<T>(value),
std::forward<LessThan>(comp));
value, std::forward<LessThan>(comp));
}

//------------------------------------------------------------------------------
@@ -1560,17 +1559,17 @@ container_algorithm_internal::ContainerIter<Sequence> c_max_element(
// smallest and largest values, respectively, using `operator<` to make the
// comparisons.
template <typename C>
container_algorithm_internal::ContainerIterPairType<C, C>
c_minmax_element(C& c) {
container_algorithm_internal::ContainerIterPairType<C, C> c_minmax_element(
C& c) {
return std::minmax_element(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c));
}

// Overload of c_minmax_element() for performing `comp` comparisons other than
// `operator<`.
template <typename C, typename LessThan>
container_algorithm_internal::ContainerIterPairType<C, C>
c_minmax_element(C& c, LessThan&& comp) {
container_algorithm_internal::ContainerIterPairType<C, C> c_minmax_element(
C& c, LessThan&& comp) {
return std::minmax_element(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c),
std::forward<LessThan>(comp));
@@ -1588,7 +1587,8 @@ c_minmax_element(C& c, LessThan&& comp) {
// that capital letters ("A-Z") have ASCII values less than lowercase letters
// ("a-z").
template <typename Sequence1, typename Sequence2>
bool c_lexicographical_compare(Sequence1&& sequence1, Sequence2&& sequence2) {
bool c_lexicographical_compare(const Sequence1& sequence1,
const Sequence2& sequence2) {
return std::lexicographical_compare(
container_algorithm_internal::c_begin(sequence1),
container_algorithm_internal::c_end(sequence1),
@@ -1599,8 +1599,8 @@ bool c_lexicographical_compare(Sequence1&& sequence1, Sequence2&& sequence2) {
// Overload of c_lexicographical_compare() for performing a lexicographical
// comparison using a `comp` operator instead of `operator<`.
template <typename Sequence1, typename Sequence2, typename LessThan>
bool c_lexicographical_compare(Sequence1&& sequence1, Sequence2&& sequence2,
LessThan&& comp) {
bool c_lexicographical_compare(const Sequence1& sequence1,
const Sequence2& sequence2, LessThan&& comp) {
return std::lexicographical_compare(
container_algorithm_internal::c_begin(sequence1),
container_algorithm_internal::c_end(sequence1),
@@ -1655,18 +1655,18 @@ bool c_prev_permutation(C& c, LessThan&& comp) {

// c_iota()
//
// Container-based version of the <algorithm> `std::iota()` function
// Container-based version of the <numeric> `std::iota()` function
// to compute successive values of `value`, as if incremented with `++value`
// after each element is written. and write them to the container.
template <typename Sequence, typename T>
void c_iota(Sequence& sequence, T&& value) {
void c_iota(Sequence& sequence, const T& value) {
std::iota(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence),
std::forward<T>(value));
container_algorithm_internal::c_end(sequence), value);
}

// c_accumulate()
//
// Container-based version of the <algorithm> `std::accumulate()` function
// Container-based version of the <numeric> `std::accumulate()` function
// to accumulate the element values of a container to `init` and return that
// accumulation by value.
//
@@ -1693,7 +1693,7 @@ decay_t<T> c_accumulate(const Sequence& sequence, T&& init,

// c_inner_product()
//
// Container-based version of the <algorithm> `std::inner_product()` function
// Container-based version of the <numeric> `std::inner_product()` function
// to compute the cumulative inner product of container element pairs.
//
// Note: Due to a language technicality this function has return type
@@ -1724,7 +1724,7 @@ decay_t<T> c_inner_product(const Sequence1& factors1, const Sequence2& factors2,

// c_adjacent_difference()
//
// Container-based version of the <algorithm> `std::adjacent_difference()`
// Container-based version of the <numeric> `std::adjacent_difference()`
// function to compute the difference between each element and the one preceding
// it and write it to an iterator.
template <typename InputSequence, typename OutputIt>
@@ -1747,7 +1747,7 @@ OutputIt c_adjacent_difference(const InputSequence& input,

// c_partial_sum()
//
// Container-based version of the <algorithm> `std::partial_sum()` function
// Container-based version of the <numeric> `std::partial_sum()` function
// to compute the partial sum of the elements in a sequence and write them
// to an iterator. The partial sum is the sum of all element values so far in
// the sequence.
121 changes: 97 additions & 24 deletions src/absl/base/attributes.h
Original file line number Diff line number Diff line change
@@ -211,11 +211,20 @@
// out of bounds or does other scary things with memory.
// NOTE: GCC supports AddressSanitizer(asan) since 4.8.
// https://gcc.gnu.org/gcc-4.8/changes.html
#if ABSL_HAVE_ATTRIBUTE(no_sanitize_address)
#if defined(ABSL_HAVE_ADDRESS_SANITIZER) && \
ABSL_HAVE_ATTRIBUTE(no_sanitize_address)
#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
#elif defined(_MSC_VER) && _MSC_VER >= 1928
#elif defined(ABSL_HAVE_ADDRESS_SANITIZER) && defined(_MSC_VER) && \
_MSC_VER >= 1928
// https://docs.microsoft.com/en-us/cpp/cpp/no-sanitize-address
#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS __declspec(no_sanitize_address)
#elif defined(ABSL_HAVE_HWADDRESS_SANITIZER) && ABSL_HAVE_ATTRIBUTE(no_sanitize)
// HWAddressSanitizer is a sanitizer similar to AddressSanitizer, which uses CPU
// features to detect similar bugs with less CPU and memory overhead.
// NOTE: GCC supports HWAddressSanitizer(hwasan) since 11.
// https://gcc.gnu.org/gcc-11/changes.html
#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS \
__attribute__((no_sanitize("hwaddress")))
#else
#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS
#endif
@@ -265,7 +274,7 @@
//
// Tells the ControlFlowIntegrity sanitizer to not instrument a given function.
// See https://clang.llvm.org/docs/ControlFlowIntegrity.html for details.
#if ABSL_HAVE_ATTRIBUTE(no_sanitize)
#if ABSL_HAVE_ATTRIBUTE(no_sanitize) && defined(__llvm__)
#define ABSL_ATTRIBUTE_NO_SANITIZE_CFI __attribute__((no_sanitize("cfi")))
#else
#define ABSL_ATTRIBUTE_NO_SANITIZE_CFI
@@ -322,8 +331,8 @@
// This functionality is supported by GNU linker.
#ifndef ABSL_ATTRIBUTE_SECTION_VARIABLE
#ifdef _AIX
// __attribute__((section(#name))) on AIX is achived by using the `.csect` psudo
// op which includes an additional integer as part of its syntax indcating
// __attribute__((section(#name))) on AIX is achieved by using the `.csect`
// psudo op which includes an additional integer as part of its syntax indcating
// alignment. If data fall under different alignments then you might get a
// compilation error indicating a `Section type conflict`.
#define ABSL_ATTRIBUTE_SECTION_VARIABLE(name)
@@ -676,6 +685,28 @@
#define ABSL_DEPRECATED(message)
#endif

// When deprecating Abseil code, it is sometimes necessary to turn off the
// warning within Abseil, until the deprecated code is actually removed. The
// deprecated code can be surrounded with these directives to acheive that
// result.
//
// class ABSL_DEPRECATED("Use Bar instead") Foo;
//
// ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING
// Baz ComputeBazFromFoo(Foo f);
// ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING
#if defined(__GNUC__) || defined(__clang__)
// Clang also supports these GCC pragmas.
#define ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
#define ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING \
_Pragma("GCC diagnostic pop")
#else
#define ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING
#define ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING
#endif // defined(__GNUC__) || defined(__clang__)

// ABSL_CONST_INIT
//
// A variable declaration annotated with the `ABSL_CONST_INIT` attribute will
@@ -716,26 +747,9 @@
#define ABSL_CONST_INIT
#endif

// ABSL_ATTRIBUTE_PURE_FUNCTION
//
// ABSL_ATTRIBUTE_PURE_FUNCTION is used to annotate declarations of "pure"
// functions. A function is pure if its return value is only a function of its
// arguments. The pure attribute prohibits a function from modifying the state
// of the program that is observable by means other than inspecting the
// function's return value. Declaring such functions with the pure attribute
// allows the compiler to avoid emitting some calls in repeated invocations of
// the function with the same argument values.
//
// Example:
//
// ABSL_ATTRIBUTE_PURE_FUNCTION int64_t ToInt64Milliseconds(Duration d);
#if ABSL_HAVE_CPP_ATTRIBUTE(gnu::pure)
#define ABSL_ATTRIBUTE_PURE_FUNCTION [[gnu::pure]]
#elif ABSL_HAVE_ATTRIBUTE(pure)
#define ABSL_ATTRIBUTE_PURE_FUNCTION __attribute__((pure))
#else
// These annotations are not available yet due to fear of breaking code.
#define ABSL_ATTRIBUTE_PURE_FUNCTION
#endif
#define ABSL_ATTRIBUTE_CONST_FUNCTION

// ABSL_ATTRIBUTE_LIFETIME_BOUND indicates that a resource owned by a function
// parameter or implicit object parameter is retained by the return value of the
@@ -759,4 +773,63 @@
#define ABSL_ATTRIBUTE_LIFETIME_BOUND
#endif

// ABSL_ATTRIBUTE_TRIVIAL_ABI
// Indicates that a type is "trivially relocatable" -- meaning it can be
// relocated without invoking the constructor/destructor, using a form of move
// elision.
//
// From a memory safety point of view, putting aside destructor ordering, it's
// safe to apply ABSL_ATTRIBUTE_TRIVIAL_ABI if an object's location
// can change over the course of its lifetime: if a constructor can be run one
// place, and then the object magically teleports to another place where some
// methods are run, and then the object teleports to yet another place where it
// is destroyed. This is notably not true for self-referential types, where the
// move-constructor must keep the self-reference up to date. If the type changed
// location without invoking the move constructor, it would have a dangling
// self-reference.
//
// The use of this teleporting machinery means that the number of paired
// move/destroy operations can change, and so it is a bad idea to apply this to
// a type meant to count the number of moves.
//
// Warning: applying this can, rarely, break callers. Objects passed by value
// will be destroyed at the end of the call, instead of the end of the
// full-expression containing the call. In addition, it changes the ABI
// of functions accepting this type by value (e.g. to pass in registers).
//
// See also the upstream documentation:
// https://clang.llvm.org/docs/AttributeReference.html#trivial-abi
//
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::trivial_abi)
#define ABSL_ATTRIBUTE_TRIVIAL_ABI [[clang::trivial_abi]]
#define ABSL_HAVE_ATTRIBUTE_TRIVIAL_ABI 1
#elif ABSL_HAVE_ATTRIBUTE(trivial_abi)
#define ABSL_ATTRIBUTE_TRIVIAL_ABI __attribute__((trivial_abi))
#define ABSL_HAVE_ATTRIBUTE_TRIVIAL_ABI 1
#else
#define ABSL_ATTRIBUTE_TRIVIAL_ABI
#endif

// ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS
//
// Indicates a data member can be optimized to occupy no space (if it is empty)
// and/or its tail padding can be used for other members.
//
// For code that is assured to only build with C++20 or later, prefer using
// the standard attribute `[[no_unique_address]]` directly instead of this
// macro.
//
// https://devblogs.microsoft.com/cppblog/msvc-cpp20-and-the-std-cpp20-switch/#c20-no_unique_address
// Current versions of MSVC have disabled `[[no_unique_address]]` since it
// breaks ABI compatibility, but offers `[[msvc::no_unique_address]]` for
// situations when it can be assured that it is desired. Since Abseil does not
// claim ABI compatibility in mixed builds, we can offer it unconditionally.
#if defined(_MSC_VER) && _MSC_VER >= 1929
#define ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]
#elif ABSL_HAVE_CPP_ATTRIBUTE(no_unique_address)
#define ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS [[no_unique_address]]
#else
#define ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS
#endif

#endif // ABSL_BASE_ATTRIBUTES_H_
2 changes: 1 addition & 1 deletion src/absl/base/call_once.h
Original file line number Diff line number Diff line change
@@ -123,7 +123,7 @@ class SchedulingHelper {

private:
base_internal::SchedulingMode mode_;
bool guard_result_;
bool guard_result_ = false;
};

// Bit patterns for call_once state machine values. Internal implementation
16 changes: 8 additions & 8 deletions src/absl/base/casts.h
Original file line number Diff line number Diff line change
@@ -149,16 +149,16 @@ using std::bit_cast;

#else // defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L

template <typename Dest, typename Source,
typename std::enable_if<
sizeof(Dest) == sizeof(Source) &&
type_traits_internal::is_trivially_copyable<Source>::value &&
type_traits_internal::is_trivially_copyable<Dest>::value
template <
typename Dest, typename Source,
typename std::enable_if<sizeof(Dest) == sizeof(Source) &&
std::is_trivially_copyable<Source>::value &&
std::is_trivially_copyable<Dest>::value
#if !ABSL_HAVE_BUILTIN(__builtin_bit_cast)
&& std::is_default_constructible<Dest>::value
&& std::is_default_constructible<Dest>::value
#endif // !ABSL_HAVE_BUILTIN(__builtin_bit_cast)
,
int>::type = 0>
,
int>::type = 0>
#if ABSL_HAVE_BUILTIN(__builtin_bit_cast)
inline constexpr Dest bit_cast(const Source& source) {
return __builtin_bit_cast(Dest, source);
230 changes: 128 additions & 102 deletions src/absl/base/config.h

Large diffs are not rendered by default.

27 changes: 26 additions & 1 deletion src/absl/base/dynamic_annotations.h
Original file line number Diff line number Diff line change
@@ -46,13 +46,18 @@
#define ABSL_BASE_DYNAMIC_ANNOTATIONS_H_

#include <stddef.h>
#include <stdint.h>

#include "absl/base/attributes.h"
#include "absl/base/config.h"
#ifdef __cplusplus
#include "absl/base/macros.h"
#endif

#ifdef ABSL_HAVE_HWADDRESS_SANITIZER
#include <sanitizer/hwasan_interface.h>
#endif

// TODO(rogeeff): Remove after the backward compatibility period.
#include "absl/base/internal/dynamic_annotations.h" // IWYU pragma: export

@@ -111,7 +116,7 @@

#if ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED == 1
// Some of the symbols used in this section (e.g. AnnotateBenignRaceSized) are
// defined by the compiler-based santizer implementation, not by the Abseil
// defined by the compiler-based sanitizer implementation, not by the Abseil
// library. Therefore they do not use ABSL_INTERNAL_C_SYMBOL.

// -------------------------------------------------------------
@@ -456,6 +461,26 @@ ABSL_NAMESPACE_END

#endif // ABSL_HAVE_ADDRESS_SANITIZER

// -------------------------------------------------------------------------
// HWAddress sanitizer annotations

#ifdef __cplusplus
namespace absl {
#ifdef ABSL_HAVE_HWADDRESS_SANITIZER
// Under HWASAN changes the tag of the pointer.
template <typename T>
T* HwasanTagPointer(T* ptr, uintptr_t tag) {
return reinterpret_cast<T*>(__hwasan_tag_pointer(ptr, tag));
}
#else
template <typename T>
T* HwasanTagPointer(T* ptr, uintptr_t) {
return ptr;
}
#endif
} // namespace absl
#endif

// -------------------------------------------------------------------------
// Undefine the macros intended only for this file.

6 changes: 3 additions & 3 deletions src/absl/base/internal/atomic_hook_test_helper.h
Original file line number Diff line number Diff line change
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef ABSL_BASE_ATOMIC_HOOK_TEST_HELPER_H_
#define ABSL_BASE_ATOMIC_HOOK_TEST_HELPER_H_
#ifndef ABSL_BASE_INTERNAL_ATOMIC_HOOK_TEST_HELPER_H_
#define ABSL_BASE_INTERNAL_ATOMIC_HOOK_TEST_HELPER_H_

#include "absl/base/internal/atomic_hook.h"

@@ -31,4 +31,4 @@ void RegisterFunc(VoidF func);
ABSL_NAMESPACE_END
} // namespace absl

#endif // ABSL_BASE_ATOMIC_HOOK_TEST_HELPER_H_
#endif // ABSL_BASE_INTERNAL_ATOMIC_HOOK_TEST_HELPER_H_
21 changes: 3 additions & 18 deletions src/absl/base/internal/cycleclock.h
Original file line number Diff line number Diff line change
@@ -47,6 +47,7 @@

#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/internal/cycleclock_config.h"
#include "absl/base/internal/unscaledcycleclock.h"

namespace absl {
@@ -76,25 +77,9 @@ class CycleClock {
#if ABSL_USE_UNSCALED_CYCLECLOCK
static CycleClockSourceFunc LoadCycleClockSource();

#ifdef NDEBUG
#ifdef ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY
// Not debug mode and the UnscaledCycleClock frequency is the CPU
// frequency. Scale the CycleClock to prevent overflow if someone
// tries to represent the time as cycles since the Unix epoch.
static constexpr int32_t kShift = 1;
#else
// Not debug mode and the UnscaledCycleClock isn't operating at the
// raw CPU frequency. There is no need to do any scaling, so don't
// needlessly sacrifice precision.
static constexpr int32_t kShift = 0;
#endif
#else // NDEBUG
// In debug mode use a different shift to discourage depending on a
// particular shift value.
static constexpr int32_t kShift = 2;
#endif // NDEBUG
static constexpr int32_t kShift = kCycleClockShift;
static constexpr double kFrequencyScale = kCycleClockFrequencyScale;

static constexpr double kFrequencyScale = 1.0 / (1 << kShift);
ABSL_CONST_INIT static std::atomic<CycleClockSourceFunc> cycle_clock_source_;
#endif // ABSL_USE_UNSCALED_CYCLECLOC

55 changes: 55 additions & 0 deletions src/absl/base/internal/cycleclock_config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright 2022 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
//
// https://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_CYCLECLOCK_CONFIG_H_
#define ABSL_BASE_INTERNAL_CYCLECLOCK_CONFIG_H_

#include <cstdint>

#include "absl/base/config.h"
#include "absl/base/internal/inline_variable.h"
#include "absl/base/internal/unscaledcycleclock_config.h"

namespace absl {
ABSL_NAMESPACE_BEGIN
namespace base_internal {

#if ABSL_USE_UNSCALED_CYCLECLOCK
#ifdef NDEBUG
#ifdef ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY
// Not debug mode and the UnscaledCycleClock frequency is the CPU
// frequency. Scale the CycleClock to prevent overflow if someone
// tries to represent the time as cycles since the Unix epoch.
ABSL_INTERNAL_INLINE_CONSTEXPR(int32_t, kCycleClockShift, 1);
#else
// Not debug mode and the UnscaledCycleClock isn't operating at the
// raw CPU frequency. There is no need to do any scaling, so don't
// needlessly sacrifice precision.
ABSL_INTERNAL_INLINE_CONSTEXPR(int32_t, kCycleClockShift, 0);
#endif
#else // NDEBUG
// In debug mode use a different shift to discourage depending on a
// particular shift value.
ABSL_INTERNAL_INLINE_CONSTEXPR(int32_t, kCycleClockShift, 2);
#endif // NDEBUG

ABSL_INTERNAL_INLINE_CONSTEXPR(double, kCycleClockFrequencyScale,
1.0 / (1 << kCycleClockShift));
#endif // ABSL_USE_UNSCALED_CYCLECLOC

} // namespace base_internal
ABSL_NAMESPACE_END
} // namespace absl

#endif // ABSL_BASE_INTERNAL_CYCLECLOCK_CONFIG_H_
7 changes: 4 additions & 3 deletions src/absl/base/internal/direct_mmap.h
Original file line number Diff line number Diff line change
@@ -72,7 +72,7 @@ namespace base_internal {
// Platform specific logic extracted from
// https://chromium.googlesource.com/linux-syscall-support/+/master/linux_syscall_support.h
inline void* DirectMmap(void* start, size_t length, int prot, int flags, int fd,
off64_t offset) noexcept {
off_t offset) noexcept {
#if defined(__i386__) || defined(__ARM_ARCH_3__) || defined(__ARM_EABI__) || \
defined(__m68k__) || defined(__sh__) || \
(defined(__hppa__) && !defined(__LP64__)) || \
@@ -97,11 +97,12 @@ inline void* DirectMmap(void* start, size_t length, int prot, int flags, int fd,
#ifdef __BIONIC__
// SYS_mmap2 has problems on Android API level <= 16.
// Workaround by invoking __mmap2() instead.
return __mmap2(start, length, prot, flags, fd, offset / pagesize);
return __mmap2(start, length, prot, flags, fd,
static_cast<size_t>(offset / pagesize));
#else
return reinterpret_cast<void*>(
syscall(SYS_mmap2, start, length, prot, flags, fd,
static_cast<off_t>(offset / pagesize)));
static_cast<unsigned long>(offset / pagesize))); // NOLINT
#endif
#elif defined(__s390x__)
// On s390x, mmap() arguments are passed in memory.
2 changes: 1 addition & 1 deletion src/absl/base/internal/exception_safety_testing.h
Original file line number Diff line number Diff line change
@@ -946,7 +946,7 @@ class ExceptionSafetyTest {
* `std::unique_ptr<T> operator()() const` where T is the type being tested.
* It is used for reliably creating identical T instances to test on.
*
* - Operation: The operation object (passsed in via tester.WithOperation(...)
* - Operation: The operation object (passed in via tester.WithOperation(...)
* or tester.Test(...)) must be invocable with the signature
* `void operator()(T*) const` where T is the type being tested. It is used
* for performing steps on a T instance that may throw and that need to be
6 changes: 3 additions & 3 deletions src/absl/base/internal/inline_variable.h
Original file line number Diff line number Diff line change
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef ABSL_BASE_INTERNAL_INLINE_VARIABLE_EMULATION_H_
#define ABSL_BASE_INTERNAL_INLINE_VARIABLE_EMULATION_H_
#ifndef ABSL_BASE_INTERNAL_INLINE_VARIABLE_H_
#define ABSL_BASE_INTERNAL_INLINE_VARIABLE_H_

#include <type_traits>

@@ -104,4 +104,4 @@

#endif // __cpp_inline_variables

#endif // ABSL_BASE_INTERNAL_INLINE_VARIABLE_EMULATION_H_
#endif // ABSL_BASE_INTERNAL_INLINE_VARIABLE_H_
6 changes: 3 additions & 3 deletions src/absl/base/internal/inline_variable_testing.h
Original file line number Diff line number Diff line change
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef ABSL_BASE_INLINE_VARIABLE_TESTING_H_
#define ABSL_BASE_INLINE_VARIABLE_TESTING_H_
#ifndef ABSL_BASE_INTERNAL_INLINE_VARIABLE_TESTING_H_
#define ABSL_BASE_INTERNAL_INLINE_VARIABLE_TESTING_H_

#include "absl/base/internal/inline_variable.h"

@@ -43,4 +43,4 @@ const int& get_int_b();
ABSL_NAMESPACE_END
} // namespace absl

#endif // ABSL_BASE_INLINE_VARIABLE_TESTING_H_
#endif // ABSL_BASE_INTERNAL_INLINE_VARIABLE_TESTING_H_
5 changes: 3 additions & 2 deletions src/absl/base/internal/low_level_alloc.h
Original file line number Diff line number Diff line change
@@ -46,7 +46,8 @@
// 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) || defined(__asmjs__) || defined(__wasm__)
#elif defined(_WIN32) || defined(__asmjs__) || defined(__wasm__) || \
defined(__hexagon__)
#define ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING 1
#endif

@@ -103,7 +104,7 @@ class LowLevelAlloc {
// the provided flags. For example, the call NewArena(kAsyncSignalSafe)
// is itself async-signal-safe, as well as generatating an arena that provides
// async-signal-safe Alloc/Free.
static Arena *NewArena(int32_t flags);
static Arena *NewArena(uint32_t flags);

// Destroys an arena allocated by NewArena and returns true,
// provided no allocated blocks remain in the arena.
106 changes: 106 additions & 0 deletions src/absl/base/internal/nullability_impl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// Copyright 2023 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
//
// https://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_NULLABILITY_IMPL_H_
#define ABSL_BASE_INTERNAL_NULLABILITY_IMPL_H_

#include <memory>
#include <type_traits>

#include "absl/base/attributes.h"
#include "absl/meta/type_traits.h"

namespace absl {

namespace nullability_internal {

// `IsNullabilityCompatible` checks whether its first argument is a class
// explicitly tagged as supporting nullability annotations. The tag is the type
// declaration `absl_nullability_compatible`.
template <typename, typename = void>
struct IsNullabilityCompatible : std::false_type {};

template <typename T>
struct IsNullabilityCompatible<
T, absl::void_t<typename T::absl_nullability_compatible>> : std::true_type {
};

template <typename T>
constexpr bool IsSupportedType = IsNullabilityCompatible<T>::value;

template <typename T>
constexpr bool IsSupportedType<T*> = true;

template <typename T, typename U>
constexpr bool IsSupportedType<T U::*> = true;

template <typename T, typename... Deleter>
constexpr bool IsSupportedType<std::unique_ptr<T, Deleter...>> = true;

template <typename T>
constexpr bool IsSupportedType<std::shared_ptr<T>> = true;

template <typename T>
struct EnableNullable {
static_assert(nullability_internal::IsSupportedType<std::remove_cv_t<T>>,
"Template argument must be a raw or supported smart pointer "
"type. See absl/base/nullability.h.");
using type = T;
};

template <typename T>
struct EnableNonnull {
static_assert(nullability_internal::IsSupportedType<std::remove_cv_t<T>>,
"Template argument must be a raw or supported smart pointer "
"type. See absl/base/nullability.h.");
using type = T;
};

template <typename T>
struct EnableNullabilityUnknown {
static_assert(nullability_internal::IsSupportedType<std::remove_cv_t<T>>,
"Template argument must be a raw or supported smart pointer "
"type. See absl/base/nullability.h.");
using type = T;
};

// Note: we do not apply Clang nullability attributes (e.g. _Nullable). These
// only support raw pointers, and conditionally enabling them only for raw
// pointers inhibits template arg deduction. Ideally, they would support all
// pointer-like types.
template <typename T, typename = typename EnableNullable<T>::type>
using NullableImpl
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate)
[[clang::annotate("Nullable")]]
#endif
= T;

template <typename T, typename = typename EnableNonnull<T>::type>
using NonnullImpl
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate)
[[clang::annotate("Nonnull")]]
#endif
= T;

template <typename T, typename = typename EnableNullabilityUnknown<T>::type>
using NullabilityUnknownImpl
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate)
[[clang::annotate("Nullability_Unspecified")]]
#endif
= T;

} // namespace nullability_internal
} // namespace absl

#endif // ABSL_BASE_INTERNAL_NULLABILITY_IMPL_H_
35 changes: 17 additions & 18 deletions src/absl/base/internal/prefetch.h
Original file line number Diff line number Diff line change
@@ -12,10 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.

// TODO(b/265984188): remove all uses and delete this header.

#ifndef ABSL_BASE_INTERNAL_PREFETCH_H_
#define ABSL_BASE_INTERNAL_PREFETCH_H_

#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/prefetch.h"

#ifdef __SSE__
#include <xmmintrin.h>
@@ -72,10 +76,21 @@ namespace absl {
ABSL_NAMESPACE_BEGIN
namespace base_internal {

void PrefetchT0(const void* addr);
ABSL_DEPRECATED("Use absl::PrefetchToLocalCache() instead")
inline void PrefetchT0(const void* address) {
absl::PrefetchToLocalCache(address);
}

ABSL_DEPRECATED("Use absl::PrefetchToLocalCache() instead")
inline void PrefetchNta(const void* address) {
absl::PrefetchToLocalCacheNta(address);
}

ABSL_DEPRECATED("Use __builtin_prefetch() for advanced prefetch logic instead")
void PrefetchT1(const void* addr);

ABSL_DEPRECATED("Use __builtin_prefetch() for advanced prefetch logic instead")
void PrefetchT2(const void* addr);
void PrefetchNta(const void* addr);

// Implementation details follow.

@@ -90,10 +105,6 @@ void PrefetchNta(const void* addr);
// safe for all currently supported platforms. However, prefetch for
// store may have problems depending on the target platform.
//
inline void PrefetchT0(const void* addr) {
// Note: this uses prefetcht0 on Intel.
__builtin_prefetch(addr, 0, 3);
}
inline void PrefetchT1(const void* addr) {
// Note: this uses prefetcht1 on Intel.
__builtin_prefetch(addr, 0, 2);
@@ -102,33 +113,21 @@ inline void PrefetchT2(const void* addr) {
// Note: this uses prefetcht2 on Intel.
__builtin_prefetch(addr, 0, 1);
}
inline void PrefetchNta(const void* addr) {
// Note: this uses prefetchtnta on Intel.
__builtin_prefetch(addr, 0, 0);
}

#elif defined(ABSL_INTERNAL_HAVE_SSE)

#define ABSL_INTERNAL_HAVE_PREFETCH 1

inline void PrefetchT0(const void* addr) {
_mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_T0);
}
inline void PrefetchT1(const void* addr) {
_mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_T1);
}
inline void PrefetchT2(const void* addr) {
_mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_T2);
}
inline void PrefetchNta(const void* addr) {
_mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_NTA);
}

#else
inline void PrefetchT0(const void*) {}
inline void PrefetchT1(const void*) {}
inline void PrefetchT2(const void*) {}
inline void PrefetchNta(const void*) {}
#endif

} // namespace base_internal
71 changes: 45 additions & 26 deletions src/absl/base/internal/raw_logging.h
Original file line number Diff line number Diff line change
@@ -43,12 +43,12 @@

#define ABSL_RAW_LOG(severity, ...) \
do { \
constexpr const char* absl_raw_logging_internal_basename = \
::absl::raw_logging_internal::Basename(__FILE__, \
sizeof(__FILE__) - 1); \
::absl::raw_logging_internal::RawLog(ABSL_RAW_LOGGING_INTERNAL_##severity, \
absl_raw_logging_internal_basename, \
__LINE__, __VA_ARGS__); \
constexpr const char* absl_raw_log_internal_basename = \
::absl::raw_log_internal::Basename(__FILE__, sizeof(__FILE__) - 1); \
::absl::raw_log_internal::RawLog(ABSL_RAW_LOG_INTERNAL_##severity, \
absl_raw_log_internal_basename, __LINE__, \
__VA_ARGS__); \
ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_##severity; \
} while (0)

// Similar to CHECK(condition) << message, but for low-level modules:
@@ -72,14 +72,13 @@
//
// 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_filename = __FILE__; \
::absl::raw_logging_internal::internal_log_function( \
ABSL_RAW_LOGGING_INTERNAL_##severity, \
absl_raw_logging_internal_filename, __LINE__, message); \
if (ABSL_RAW_LOGGING_INTERNAL_##severity == ::absl::LogSeverity::kFatal) \
ABSL_INTERNAL_UNREACHABLE; \
#define ABSL_INTERNAL_LOG(severity, message) \
do { \
constexpr const char* absl_raw_log_internal_filename = __FILE__; \
::absl::raw_log_internal::internal_log_function( \
ABSL_RAW_LOG_INTERNAL_##severity, absl_raw_log_internal_filename, \
__LINE__, message); \
ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_##severity; \
} while (0)

#define ABSL_INTERNAL_CHECK(condition, message) \
@@ -91,16 +90,36 @@
} \
} 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
#define ABSL_RAW_LOGGING_INTERNAL_FATAL ::absl::LogSeverity::kFatal
#define ABSL_RAW_LOGGING_INTERNAL_LEVEL(severity) \
#ifndef NDEBUG

#define ABSL_RAW_DLOG(severity, ...) ABSL_RAW_LOG(severity, __VA_ARGS__)
#define ABSL_RAW_DCHECK(condition, message) ABSL_RAW_CHECK(condition, message)

#else // NDEBUG

#define ABSL_RAW_DLOG(severity, ...) \
while (false) ABSL_RAW_LOG(severity, __VA_ARGS__)
#define ABSL_RAW_DCHECK(condition, message) \
while (false) ABSL_RAW_CHECK(condition, message)

#endif // NDEBUG

#define ABSL_RAW_LOG_INTERNAL_INFO ::absl::LogSeverity::kInfo
#define ABSL_RAW_LOG_INTERNAL_WARNING ::absl::LogSeverity::kWarning
#define ABSL_RAW_LOG_INTERNAL_ERROR ::absl::LogSeverity::kError
#define ABSL_RAW_LOG_INTERNAL_FATAL ::absl::LogSeverity::kFatal
#define ABSL_RAW_LOG_INTERNAL_LEVEL(severity) \
::absl::NormalizeLogSeverity(severity)

#define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_INFO
#define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_WARNING
#define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_ERROR
#define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_FATAL ABSL_UNREACHABLE()
#define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_LEVEL(severity)

namespace absl {
ABSL_NAMESPACE_BEGIN
namespace raw_logging_internal {
namespace raw_log_internal {

// Helper function to implement ABSL_RAW_LOG
// Logs format... at "severity" level, reporting it
@@ -110,8 +129,8 @@ void RawLog(absl::LogSeverity severity, const char* file, int line,
const char* format, ...) ABSL_PRINTF_ATTRIBUTE(4, 5);

// Writes the provided buffer directly to stderr, in a signal-safe, low-level
// manner.
void AsyncSignalSafeWriteToStderr(const char* s, size_t len);
// manner. Preserves errno.
void AsyncSignalSafeWriteError(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
@@ -130,7 +149,7 @@ constexpr const char* Basename(const char* fname, int offset) {
// TODO(gfalcon): Come up with a better name for this method.
bool RawLoggingFullySupported();

// Function type for a raw_logging customization hook for suppressing messages
// Function type for a raw_log customization hook for suppressing messages
// by severity, and for writing custom prefixes on non-suppressed messages.
//
// The installed hook is called for every raw log invocation. The message will
@@ -139,7 +158,7 @@ bool RawLoggingFullySupported();
// also provided with an output buffer, where it can write a custom log message
// prefix.
//
// The raw_logging system does not allocate memory or grab locks. User-provided
// The raw_log system does not allocate memory or grab locks. User-provided
// hooks must avoid these operations, and must not throw exceptions.
//
// 'severity' is the severity level of the message being written.
@@ -152,7 +171,7 @@ using LogFilterAndPrefixHook = bool (*)(absl::LogSeverity severity,
const char* file, int line, char** buf,
int* buf_size);

// Function type for a raw_logging customization hook called to abort a process
// Function type for a raw_log customization hook called to abort a process
// when a FATAL message is logged. If the provided AbortHook() returns, the
// logging system will call abort().
//
@@ -189,7 +208,7 @@ void RegisterLogFilterAndPrefixHook(LogFilterAndPrefixHook func);
void RegisterAbortHook(AbortHook func);
void RegisterInternalLogFunction(InternalLogFunction func);

} // namespace raw_logging_internal
} // namespace raw_log_internal
ABSL_NAMESPACE_END
} // namespace absl

8 changes: 2 additions & 6 deletions src/absl/base/internal/spinlock.h
Original file line number Diff line number Diff line change
@@ -29,10 +29,8 @@
#ifndef ABSL_BASE_INTERNAL_SPINLOCK_H_
#define ABSL_BASE_INTERNAL_SPINLOCK_H_

#include <stdint.h>
#include <sys/types.h>

#include <atomic>
#include <cstdint>

#include "absl/base/attributes.h"
#include "absl/base/const_init.h"
@@ -41,8 +39,6 @@
#include "absl/base/internal/raw_logging.h"
#include "absl/base/internal/scheduling_mode.h"
#include "absl/base/internal/tsan_mutex_interface.h"
#include "absl/base/macros.h"
#include "absl/base/port.h"
#include "absl/base/thread_annotations.h"

namespace absl {
@@ -137,7 +133,7 @@ class ABSL_LOCKABLE SpinLock {
int64_t wait_end_time);

// Extract number of wait cycles in a lock value.
static uint64_t DecodeWaitCycles(uint32_t lock_value);
static int64_t DecodeWaitCycles(uint32_t lock_value);

// Provide access to protected method above. Use for testing only.
friend struct SpinLockTest;
5 changes: 4 additions & 1 deletion src/absl/base/internal/spinlock_win32.inc
Original file line number Diff line number Diff line change
@@ -27,7 +27,10 @@ void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)(
} else if (loop == 1) {
Sleep(0);
} else {
Sleep(absl::base_internal::SpinLockSuggestedDelayNS(loop) / 1000000);
// SpinLockSuggestedDelayNS() always returns a positive integer, so this
// static_cast is safe.
Sleep(static_cast<DWORD>(
absl::base_internal::SpinLockSuggestedDelayNS(loop) / 1000000));
}
}

9 changes: 9 additions & 0 deletions src/absl/base/internal/thread_annotations.h
Original file line number Diff line number Diff line change
@@ -38,6 +38,13 @@
#ifndef ABSL_BASE_INTERNAL_THREAD_ANNOTATIONS_H_
#define ABSL_BASE_INTERNAL_THREAD_ANNOTATIONS_H_

// ABSL_LEGACY_THREAD_ANNOTATIONS is a *temporary* compatibility macro that can
// be defined on the compile command-line to restore the legacy spellings of the
// thread annotations macros/functions. The macros in this file are available
// under ABSL_ prefixed spellings in absl/base/thread_annotations.h. This macro
// and the legacy spellings will be removed in the future.
#ifdef ABSL_LEGACY_THREAD_ANNOTATIONS

#if defined(__clang__)
#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
#else
@@ -268,4 +275,6 @@ inline T& ts_unchecked_read(T& v) NO_THREAD_SAFETY_ANALYSIS {

} // namespace thread_safety_analysis

#endif // defined(ABSL_LEGACY_THREAD_ANNOTATIONS)

#endif // ABSL_BASE_INTERNAL_THREAD_ANNOTATIONS_H_
26 changes: 15 additions & 11 deletions src/absl/base/internal/thread_identity.h
Original file line number Diff line number Diff line change
@@ -62,8 +62,8 @@ struct PerThreadSynch {
return reinterpret_cast<ThreadIdentity*>(this);
}

PerThreadSynch *next; // Circular waiter queue; initialized to 0.
PerThreadSynch *skip; // If non-zero, all entries in Mutex queue
PerThreadSynch* next; // Circular waiter queue; initialized to 0.
PerThreadSynch* skip; // If non-zero, all entries in Mutex queue
// up to and including "skip" have same
// condition as this, and will be woken later
bool may_skip; // if false while on mutex queue, a mutex unlocker
@@ -104,10 +104,7 @@ struct PerThreadSynch {
//
// Transitions from kAvailable to kQueued require no barrier, they
// are externally ordered by the Mutex.
enum State {
kAvailable,
kQueued
};
enum State { kAvailable, kQueued };
std::atomic<State> state;

// The wait parameters of the current wait. waitp is null if the
@@ -122,18 +119,22 @@ struct PerThreadSynch {
// pointer unchanged.
SynchWaitParams* waitp;

intptr_t readers; // Number of readers in mutex.
intptr_t readers; // Number of readers in mutex.

// When priority will next be read (cycles).
int64_t next_priority_read_cycles;

// Locks held; used during deadlock detection.
// Allocated in Synch_GetAllLocks() and freed in ReclaimThreadIdentity().
SynchLocksHeld *all_locks;
SynchLocksHeld* all_locks;
};

// The instances of this class are allocated in NewThreadIdentity() with an
// alignment of PerThreadSynch::kAlignment.
//
// NOTE: The layout of fields in this structure is critical, please do not
// add, remove, or modify the field placements without fully auditing the
// layout.
struct ThreadIdentity {
// Must be the first member. The Mutex implementation requires that
// the PerThreadSynch object associated with each thread is
@@ -143,7 +144,7 @@ struct ThreadIdentity {

// Private: Reserved for absl::synchronization_internal::Waiter.
struct WaiterState {
alignas(void*) char data[128];
alignas(void*) char data[256];
} waiter_state;

// Used by PerThreadSem::{Get,Set}ThreadBlockedCounter().
@@ -166,7 +167,10 @@ struct ThreadIdentity {
//
// Does not malloc(*), and is async-signal safe.
// [*] Technically pthread_setspecific() does malloc on first use; however this
// is handled internally within tcmalloc's initialization already.
// is handled internally within tcmalloc's initialization already. Note that
// darwin does *not* use tcmalloc, so this can catch you if using MallocHooks
// on Apple platforms. Whatever function is calling your MallocHooks will need
// to watch for recursion on Apple platforms.
//
// New ThreadIdentity objects can be constructed and associated with a thread
// by calling GetOrCreateCurrentThreadIdentity() in per-thread-sem.h.
@@ -213,7 +217,7 @@ void ClearCurrentThreadIdentity();
#define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_CPP11
#elif defined(__APPLE__) && defined(ABSL_HAVE_THREAD_LOCAL)
#define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_CPP11
#elif ABSL_PER_THREAD_TLS && defined(__GOOGLE_GRTE_VERSION__) && \
#elif ABSL_PER_THREAD_TLS && defined(__GOOGLE_GRTE_VERSION__) && \
(__GOOGLE_GRTE_VERSION__ >= 20140228L)
// Support for async-safe TLS was specifically added in GRTEv4. It's not
// present in the upstream eglibc.
43 changes: 3 additions & 40 deletions src/absl/base/internal/unscaledcycleclock.h
Original file line number Diff line number Diff line change
@@ -42,48 +42,11 @@
#include <TargetConditionals.h>
#endif

#include "absl/base/port.h"

// The following platforms have an implementation of a hardware counter.
#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) || \
defined(__powerpc__) || defined(__ppc__) || defined(__riscv) || \
defined(_M_IX86) || (defined(_M_X64) && !defined(_M_ARM64EC))
#define ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION 1
#else
#define ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION 0
#endif

// The following platforms often disable access to the hardware
// counter (through a sandbox) even if the underlying hardware has a
// usable counter. The CycleTimer interface also requires a *scaled*
// CycleClock that runs at atleast 1 MHz. We've found some Android
// ARM64 devices where this is not the case, so we disable it by
// default on Android ARM64.
#if defined(__native_client__) || (defined(__APPLE__)) || \
(defined(__ANDROID__) && defined(__aarch64__))
#define ABSL_USE_UNSCALED_CYCLECLOCK_DEFAULT 0
#else
#define ABSL_USE_UNSCALED_CYCLECLOCK_DEFAULT 1
#endif

// UnscaledCycleClock is an optional internal feature.
// Use "#if ABSL_USE_UNSCALED_CYCLECLOCK" to test for its presence.
// Can be overridden at compile-time via -DABSL_USE_UNSCALED_CYCLECLOCK=0|1
#if !defined(ABSL_USE_UNSCALED_CYCLECLOCK)
#define ABSL_USE_UNSCALED_CYCLECLOCK \
(ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION && \
ABSL_USE_UNSCALED_CYCLECLOCK_DEFAULT)
#endif
#include "absl/base/config.h"
#include "absl/base/internal/unscaledcycleclock_config.h"

#if ABSL_USE_UNSCALED_CYCLECLOCK

// This macro can be used to test if UnscaledCycleClock::Frequency()
// is NominalCPUFrequency() on a particular platform.
#if (defined(__i386__) || defined(__x86_64__) || defined(__riscv) || \
defined(_M_IX86) || defined(_M_X64))
#define ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY
#endif

namespace absl {
ABSL_NAMESPACE_BEGIN
namespace time_internal {
@@ -119,7 +82,7 @@ class UnscaledCycleClock {
inline int64_t UnscaledCycleClock::Now() {
uint64_t low, high;
__asm__ volatile("rdtsc" : "=a"(low), "=d"(high));
return (high << 32) | low;
return static_cast<int64_t>((high << 32) | low);
}

#endif
62 changes: 62 additions & 0 deletions src/absl/base/internal/unscaledcycleclock_config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright 2022 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
//
// https://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_UNSCALEDCYCLECLOCK_CONFIG_H_
#define ABSL_BASE_INTERNAL_UNSCALEDCYCLECLOCK_CONFIG_H_

#if defined(__APPLE__)
#include <TargetConditionals.h>
#endif

// The following platforms have an implementation of a hardware counter.
#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) || \
defined(__powerpc__) || defined(__ppc__) || defined(__riscv) || \
defined(_M_IX86) || (defined(_M_X64) && !defined(_M_ARM64EC))
#define ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION 1
#else
#define ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION 0
#endif

// The following platforms often disable access to the hardware
// counter (through a sandbox) even if the underlying hardware has a
// usable counter. The CycleTimer interface also requires a *scaled*
// CycleClock that runs at atleast 1 MHz. We've found some Android
// ARM64 devices where this is not the case, so we disable it by
// default on Android ARM64.
#if defined(__native_client__) || (defined(__APPLE__)) || \
(defined(__ANDROID__) && defined(__aarch64__))
#define ABSL_USE_UNSCALED_CYCLECLOCK_DEFAULT 0
#else
#define ABSL_USE_UNSCALED_CYCLECLOCK_DEFAULT 1
#endif

// UnscaledCycleClock is an optional internal feature.
// Use "#if ABSL_USE_UNSCALED_CYCLECLOCK" to test for its presence.
// Can be overridden at compile-time via -DABSL_USE_UNSCALED_CYCLECLOCK=0|1
#if !defined(ABSL_USE_UNSCALED_CYCLECLOCK)
#define ABSL_USE_UNSCALED_CYCLECLOCK \
(ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION && \
ABSL_USE_UNSCALED_CYCLECLOCK_DEFAULT)
#endif

#if ABSL_USE_UNSCALED_CYCLECLOCK
// This macro can be used to test if UnscaledCycleClock::Frequency()
// is NominalCPUFrequency() on a particular platform.
#if (defined(__i386__) || defined(__x86_64__) || defined(__riscv) || \
defined(_M_IX86) || defined(_M_X64))
#define ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY
#endif
#endif

#endif // ABSL_BASE_INTERNAL_UNSCALEDCYCLECLOCK_CONFIG_H_
25 changes: 4 additions & 21 deletions src/absl/base/macros.h
Original file line number Diff line number Diff line change
@@ -103,17 +103,11 @@ ABSL_NAMESPACE_END
// aborts the program in release mode (when NDEBUG is defined). The
// implementation should abort the program as quickly as possible and ideally it
// should not be possible to ignore the abort request.
#if (ABSL_HAVE_BUILTIN(__builtin_trap) && \
ABSL_HAVE_BUILTIN(__builtin_unreachable)) || \
(defined(__GNUC__) && !defined(__clang__))
#define ABSL_INTERNAL_HARDENING_ABORT() \
do { \
__builtin_trap(); \
__builtin_unreachable(); \
#define ABSL_INTERNAL_HARDENING_ABORT() \
do { \
ABSL_INTERNAL_IMMEDIATE_ABORT_IMPL(); \
ABSL_INTERNAL_UNREACHABLE_IMPL(); \
} while (false)
#else
#define ABSL_INTERNAL_HARDENING_ABORT() abort()
#endif

// ABSL_HARDENING_ASSERT()
//
@@ -144,15 +138,4 @@ ABSL_NAMESPACE_END
#define ABSL_INTERNAL_RETHROW do {} while (false)
#endif // ABSL_HAVE_EXCEPTIONS

// `ABSL_INTERNAL_UNREACHABLE` is an unreachable statement. A program which
// reaches one has undefined behavior, and the compiler may optimize
// accordingly.
#if defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable)
#define ABSL_INTERNAL_UNREACHABLE __builtin_unreachable()
#elif defined(_MSC_VER)
#define ABSL_INTERNAL_UNREACHABLE __assume(0)
#else
#define ABSL_INTERNAL_UNREACHABLE
#endif

#endif // ABSL_BASE_MACROS_H_
224 changes: 224 additions & 0 deletions src/absl/base/nullability.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
// Copyright 2023 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
//
// https://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.
//
// -----------------------------------------------------------------------------
// File: nullability.h
// -----------------------------------------------------------------------------
//
// This header file defines a set of "templated annotations" for designating the
// expected nullability of pointers. These annotations allow you to designate
// pointers in one of three classification states:
//
// * "Non-null" (for pointers annotated `Nonnull<T>`), indicating that it is
// invalid for the given pointer to ever be null.
// * "Nullable" (for pointers annotated `Nullable<T>`), indicating that it is
// valid for the given pointer to be null.
// * "Unknown" (for pointers annotated `NullabilityUnknown<T>`), indicating
// that the given pointer has not been yet classified as either nullable or
// non-null. This is the default state of unannotated pointers.
//
// NOTE: unannotated pointers implicitly bear the annotation
// `NullabilityUnknown<T>`; you should rarely, if ever, see this annotation used
// in the codebase explicitly.
//
// -----------------------------------------------------------------------------
// Nullability and Contracts
// -----------------------------------------------------------------------------
//
// These nullability annotations allow you to more clearly specify contracts on
// software components by narrowing the *preconditions*, *postconditions*, and
// *invariants* of pointer state(s) in any given interface. It then depends on
// context who is responsible for fulfilling the annotation's requirements.
//
// For example, a function may receive a pointer argument. Designating that
// pointer argument as "non-null" tightens the precondition of the contract of
// that function. It is then the responsibility of anyone calling such a
// function to ensure that the passed pointer is not null.
//
// Similarly, a function may have a pointer as a return value. Designating that
// return value as "non-null" tightens the postcondition of the contract of that
// function. In this case, however, it is the responsibility of the function
// itself to ensure that the returned pointer is not null.
//
// Clearly defining these contracts allows providers (and consumers) of such
// pointers to have more confidence in their null state. If a function declares
// a return value as "non-null", for example, the caller should not need to
// check whether the returned value is `nullptr`; it can simply assume the
// pointer is valid.
//
// Of course most interfaces already have expectations on the nullability state
// of pointers, and these expectations are, in effect, a contract; often,
// however, those contracts are either poorly or partially specified, assumed,
// or misunderstood. These nullability annotations are designed to allow you to
// formalize those contracts within the codebase.
//
// -----------------------------------------------------------------------------
// Using Nullability Annotations
// -----------------------------------------------------------------------------
//
// It is important to note that these annotations are not distinct strong
// *types*. They are alias templates defined to be equal to the underlying
// pointer type. A pointer annotated `Nonnull<T*>`, for example, is simply a
// pointer of type `T*`. Each annotation acts as a form of documentation about
// the contract for the given pointer. Each annotation requires providers or
// consumers of these pointers across API boundaries to take appropriate steps
// when setting or using these pointers:
//
// * "Non-null" pointers should never be null. It is the responsibility of the
// provider of this pointer to ensure that the pointer may never be set to
// null. Consumers of such pointers can treat such pointers as non-null.
// * "Nullable" pointers may or may not be null. Consumers of such pointers
// should precede any usage of that pointer (e.g. a dereference operation)
// with a a `nullptr` check.
// * "Unknown" pointers may be either "non-null" or "nullable" but have not been
// definitively determined to be in either classification state. Providers of
// such pointers across API boundaries should determine -- over time -- to
// annotate the pointer in either of the above two states. Consumers of such
// pointers across an API boundary should continue to treat such pointers as
// they currently do.
//
// Example:
//
// // PaySalary() requires the passed pointer to an `Employee` to be non-null.
// void PaySalary(absl::Nonnull<Employee *> e) {
// pay(e->salary); // OK to dereference
// }
//
// // CompleteTransaction() guarantees the returned pointer to an `Account` to
// // be non-null.
// absl::Nonnull<Account *> balance CompleteTransaction(double fee) {
// ...
// }
//
// // Note that specifying a nullability annotation does not prevent someone
// // from violating the contract:
//
// Nullable<Employee *> find(Map& employees, std::string_view name);
//
// void g(Map& employees) {
// Employee *e = find(employees, "Pat");
// // `e` can now be null.
// PaySalary(e); // Violates contract, but compiles!
// }
//
// Nullability annotations, in other words, are useful for defining and
// narrowing contracts; *enforcement* of those contracts depends on use and any
// additional (static or dynamic analysis) tooling.
//
// NOTE: The "unknown" annotation state indicates that a pointer's contract has
// not yet been positively identified. The unknown state therefore acts as a
// form of documentation of your technical debt, and a codebase that adopts
// nullability annotations should aspire to annotate every pointer as either
// "non-null" or "nullable".
//
// -----------------------------------------------------------------------------
// Applicability of Nullability Annotations
// -----------------------------------------------------------------------------
//
// By default, nullability annotations are applicable to raw and smart
// pointers. User-defined types can indicate compatibility with nullability
// annotations by providing an `absl_nullability_compatible` nested type. The
// actual definition of this inner type is not relevant as it is used merely as
// a marker. It is common to use a using declaration of
// `absl_nullability_compatible` set to void.
//
// // Example:
// struct MyPtr {
// using absl_nullability_compatible = void;
// ...
// };
//
// DISCLAIMER:
// ===========================================================================
// These nullability annotations are primarily a human readable signal about the
// intended contract of the pointer. They are not *types* and do not currently
// provide any correctness guarantees. For example, a pointer annotated as
// `Nonnull<T*>` is *not guaranteed* to be non-null, and the compiler won't
// alert or prevent assignment of a `Nullable<T*>` to a `Nonnull<T*>`.
// ===========================================================================
#ifndef ABSL_BASE_NULLABILITY_H_
#define ABSL_BASE_NULLABILITY_H_

#include "absl/base/internal/nullability_impl.h"

namespace absl {

// absl::Nonnull
//
// The indicated pointer is never null. It is the responsibility of the provider
// of this pointer across an API boundary to ensure that the pointer is never be
// set to null. Consumers of this pointer across an API boundary may safely
// dereference the pointer.
//
// Example:
//
// // `employee` is designated as not null.
// void PaySalary(absl::Nonnull<Employee *> employee) {
// pay(*employee); // OK to dereference
// }
template <typename T>
using Nonnull = nullability_internal::NonnullImpl<T>;

// absl::Nullable
//
// The indicated pointer may, by design, be either null or non-null. Consumers
// of this pointer across an API boundary should perform a `nullptr` check
// before performing any operation using the pointer.
//
// Example:
//
// // `employee` may be null.
// void PaySalary(absl::Nullable<Employee *> employee) {
// if (employee != nullptr) {
// Pay(*employee); // OK to dereference
// }
// }
template <typename T>
using Nullable = nullability_internal::NullableImpl<T>;

// absl::NullabilityUnknown (default)
//
// The indicated pointer has not yet been determined to be definitively
// "non-null" or "nullable." Providers of such pointers across API boundaries
// should, over time, annotate such pointers as either "non-null" or "nullable."
// Consumers of these pointers across an API boundary should treat such pointers
// with the same caution they treat currently unannotated pointers. Most
// existing code will have "unknown" pointers, which should eventually be
// migrated into one of the above two nullability states: `Nonnull<T>` or
// `Nullable<T>`.
//
// NOTE: Because this annotation is the global default state, pointers without
// any annotation are assumed to have "unknown" semantics. This assumption is
// designed to minimize churn and reduce clutter within the codebase.
//
// Example:
//
// // `employee`s nullability state is unknown.
// void PaySalary(absl::NullabilityUnknown<Employee *> employee) {
// Pay(*employee); // Potentially dangerous. API provider should investigate.
// }
//
// Note that a pointer without an annotation, by default, is assumed to have the
// annotation `NullabilityUnknown`.
//
// // `employee`s nullability state is unknown.
// void PaySalary(Employee* employee) {
// Pay(*employee); // Potentially dangerous. API provider should investigate.
// }
template <typename T>
using NullabilityUnknown = nullability_internal::NullabilityUnknownImpl<T>;

} // namespace absl

#endif // ABSL_BASE_NULLABILITY_H_
64 changes: 58 additions & 6 deletions src/absl/base/optimization.h
Original file line number Diff line number Diff line change
@@ -91,6 +91,7 @@
#define ABSL_CACHELINE_SIZE 64
#endif
#endif
#endif

#ifndef ABSL_CACHELINE_SIZE
// A reasonable default guess. Note that overestimates tend to waste more
@@ -141,12 +142,11 @@
// the generated machine code.
// 3) Prefer applying this attribute to individual variables. Avoid
// applying it to types. This tends to localize the effect.
#if defined(__clang__) || defined(__GNUC__)
#define ABSL_CACHELINE_ALIGNED __attribute__((aligned(ABSL_CACHELINE_SIZE)))
#elif defined(_MSC_VER)
#define ABSL_CACHELINE_SIZE 64
#define ABSL_CACHELINE_ALIGNED __declspec(align(ABSL_CACHELINE_SIZE))
#else
#define ABSL_CACHELINE_SIZE 64
#define ABSL_CACHELINE_ALIGNED
#endif

@@ -181,6 +181,53 @@
#define ABSL_PREDICT_TRUE(x) (x)
#endif

// `ABSL_INTERNAL_IMMEDIATE_ABORT_IMPL()` aborts the program in the fastest
// possible way, with no attempt at logging. One use is to implement hardening
// aborts with ABSL_OPTION_HARDENED. Since this is an internal symbol, it
// should not be used directly outside of Abseil.
#if ABSL_HAVE_BUILTIN(__builtin_trap) || \
(defined(__GNUC__) && !defined(__clang__))
#define ABSL_INTERNAL_IMMEDIATE_ABORT_IMPL() __builtin_trap()
#else
#define ABSL_INTERNAL_IMMEDIATE_ABORT_IMPL() abort()
#endif

// `ABSL_INTERNAL_UNREACHABLE_IMPL()` is the platform specific directive to
// indicate that a statement is unreachable, and to allow the compiler to
// optimize accordingly. Clients should use `ABSL_UNREACHABLE()`, which is
// defined below.
#if defined(__cpp_lib_unreachable) && __cpp_lib_unreachable >= 202202L
#define ABSL_INTERNAL_UNREACHABLE_IMPL() std::unreachable()
#elif defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable)
#define ABSL_INTERNAL_UNREACHABLE_IMPL() __builtin_unreachable()
#elif ABSL_HAVE_BUILTIN(__builtin_assume)
#define ABSL_INTERNAL_UNREACHABLE_IMPL() __builtin_assume(false)
#elif defined(_MSC_VER)
#define ABSL_INTERNAL_UNREACHABLE_IMPL() __assume(false)
#else
#define ABSL_INTERNAL_UNREACHABLE_IMPL()
#endif

// `ABSL_UNREACHABLE()` is an unreachable statement. A program which reaches
// one has undefined behavior, and the compiler may optimize accordingly.
#if ABSL_OPTION_HARDENED == 1 && defined(NDEBUG)
// Abort in hardened mode to avoid dangerous undefined behavior.
#define ABSL_UNREACHABLE() \
do { \
ABSL_INTERNAL_IMMEDIATE_ABORT_IMPL(); \
ABSL_INTERNAL_UNREACHABLE_IMPL(); \
} while (false)
#else
// The assert only fires in debug mode to aid in debugging.
// When NDEBUG is defined, reaching ABSL_UNREACHABLE() is undefined behavior.
#define ABSL_UNREACHABLE() \
do { \
/* NOLINTNEXTLINE: misc-static-assert */ \
assert(false && "ABSL_UNREACHABLE reached"); \
ABSL_INTERNAL_UNREACHABLE_IMPL(); \
} while (false)
#endif

// ABSL_ASSUME(cond)
//
// Informs the compiler that a condition is always true and that it can assume
@@ -209,18 +256,23 @@
#define ABSL_ASSUME(cond) assert(cond)
#elif ABSL_HAVE_BUILTIN(__builtin_assume)
#define ABSL_ASSUME(cond) __builtin_assume(cond)
#elif defined(_MSC_VER)
#define ABSL_ASSUME(cond) __assume(cond)
#elif defined(__cpp_lib_unreachable) && __cpp_lib_unreachable >= 202202L
#define ABSL_ASSUME(cond) \
do { \
if (!(cond)) std::unreachable(); \
} while (false)
#elif defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable)
#define ABSL_ASSUME(cond) \
do { \
if (!(cond)) __builtin_unreachable(); \
} while (0)
#elif defined(_MSC_VER)
#define ABSL_ASSUME(cond) __assume(cond)
} while (false)
#else
#define ABSL_ASSUME(cond) \
do { \
static_cast<void>(false && (cond)); \
} while (0)
} while (false)
#endif

// ABSL_INTERNAL_UNIQUE_SMALL_NAME(cond)
18 changes: 6 additions & 12 deletions src/absl/base/options.h
Original file line number Diff line number Diff line change
@@ -67,12 +67,6 @@
#ifndef ABSL_BASE_OPTIONS_H_
#define ABSL_BASE_OPTIONS_H_

// Include a standard library header to allow configuration based on the
// standard library in use.
#ifdef __cplusplus
#include <ciso646>
#endif

// -----------------------------------------------------------------------------
// Type Compatibility Options
// -----------------------------------------------------------------------------
@@ -100,7 +94,7 @@
// User code should not inspect this macro. To check in the preprocessor if
// absl::any is a typedef of std::any, use the feature macro ABSL_USES_STD_ANY.

#define ABSL_OPTION_USE_STD_ANY 0
#define ABSL_OPTION_USE_STD_ANY 1


// ABSL_OPTION_USE_STD_OPTIONAL
@@ -127,7 +121,7 @@
// absl::optional is a typedef of std::optional, use the feature macro
// ABSL_USES_STD_OPTIONAL.

#define ABSL_OPTION_USE_STD_OPTIONAL 0
#define ABSL_OPTION_USE_STD_OPTIONAL 1


// ABSL_OPTION_USE_STD_STRING_VIEW
@@ -154,7 +148,7 @@
// absl::string_view is a typedef of std::string_view, use the feature macro
// ABSL_USES_STD_STRING_VIEW.

#define ABSL_OPTION_USE_STD_STRING_VIEW 0
#define ABSL_OPTION_USE_STD_STRING_VIEW 1

// ABSL_OPTION_USE_STD_VARIANT
//
@@ -180,7 +174,7 @@
// absl::variant is a typedef of std::variant, use the feature macro
// ABSL_USES_STD_VARIANT.

#define ABSL_OPTION_USE_STD_VARIANT 0
#define ABSL_OPTION_USE_STD_VARIANT 1


// ABSL_OPTION_USE_INLINE_NAMESPACE
@@ -206,7 +200,7 @@
// allowed.

#define ABSL_OPTION_USE_INLINE_NAMESPACE 1
#define ABSL_OPTION_INLINE_NAMESPACE_NAME debian3
#define ABSL_OPTION_INLINE_NAMESPACE_NAME lts_20230802

// ABSL_OPTION_HARDENED
//
@@ -233,6 +227,6 @@
// checks enabled by this option may abort the program in a different way and
// log additional information when `NDEBUG` is not defined.

#define ABSL_OPTION_HARDENED 1
#define ABSL_OPTION_HARDENED 0

#endif // ABSL_BASE_OPTIONS_H_
28 changes: 15 additions & 13 deletions src/absl/base/policy_checks.h
Original file line number Diff line number Diff line change
@@ -44,17 +44,17 @@
// Toolchain Check
// -----------------------------------------------------------------------------

// We support MSVC++ 14.0 update 2 and later.
// We support Visual Studio 2019 (MSVC++ 16.0) and later.
// This minimum will go up.
#if defined(_MSC_FULL_VER) && _MSC_FULL_VER < 190023918 && !defined(__clang__)
#error "This package requires Visual Studio 2015 Update 2 or higher."
#if defined(_MSC_VER) && _MSC_VER < 1920 && !defined(__clang__)
#error "This package requires Visual Studio 2019 (MSVC++ 16.0) or higher."
#endif

// We support gcc 4.7 and later.
// We support GCC 7 and later.
// This minimum will go up.
#if defined(__GNUC__) && !defined(__clang__)
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 7)
#error "This package requires gcc 4.7 or higher."
#if __GNUC__ < 7
#error "This package requires GCC 7 or higher."
#endif
#endif

@@ -69,13 +69,15 @@
// C++ Version Check
// -----------------------------------------------------------------------------

// Enforce C++11 as the minimum. Note that Visual Studio has not
// advanced __cplusplus despite being good enough for our purposes, so
// so we exempt it from the check.
#if defined(__cplusplus) && !defined(_MSC_VER)
#if __cplusplus < 201103L
#error "C++ versions less than C++11 are not supported."
#endif
// Enforce C++14 as the minimum.
#if defined(_MSVC_LANG)
#if _MSVC_LANG < 201402L
#error "C++ versions less than C++14 are not supported."
#endif // _MSVC_LANG < 201402L
#elif defined(__cplusplus)
#if __cplusplus < 201402L
#error "C++ versions less than C++14 are not supported."
#endif // __cplusplus < 201402L
#endif

// -----------------------------------------------------------------------------
198 changes: 198 additions & 0 deletions src/absl/base/prefetch.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
// Copyright 2023 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
//
// https://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.
//
// -----------------------------------------------------------------------------
// File: prefetch.h
// -----------------------------------------------------------------------------
//
// This header file defines prefetch functions to prefetch memory contents
// into the first level cache (L1) for the current CPU. The prefetch logic
// offered in this header is limited to prefetching first level cachelines
// only, and is aimed at relatively 'simple' prefetching logic.
//
#ifndef ABSL_BASE_PREFETCH_H_
#define ABSL_BASE_PREFETCH_H_

#include "absl/base/config.h"

#if defined(ABSL_INTERNAL_HAVE_SSE)
#include <xmmintrin.h>
#endif

#if defined(_MSC_VER) && _MSC_VER >= 1900 && \
(defined(_M_X64) || defined(_M_IX86))
#include <intrin.h>
#pragma intrinsic(_mm_prefetch)
#endif

namespace absl {
ABSL_NAMESPACE_BEGIN

// Moves data into the L1 cache before it is read, or "prefetches" it.
//
// The value of `addr` is the address of the memory to prefetch. If
// the target and compiler support it, data prefetch instructions are
// generated. If the prefetch is done some time before the memory is
// read, it may be in the cache by the time the read occurs.
//
// This method prefetches data with the highest degree of temporal locality;
// data is prefetched where possible into all levels of the cache.
//
// Incorrect or gratuitous use of this function can degrade performance.
// Use this function only when representative benchmarks show an improvement.
//
// Example:
//
// // Computes incremental checksum for `data`.
// int ComputeChecksum(int sum, absl::string_view data);
//
// // Computes cumulative checksum for all values in `data`
// int ComputeChecksum(absl::Span<const std::string> data) {
// int sum = 0;
// auto it = data.begin();
// auto pit = data.begin();
// auto end = data.end();
// for (int dist = 8; dist > 0 && pit != data.end(); --dist, ++pit) {
// absl::PrefetchToLocalCache(pit->data());
// }
// for (; pit != end; ++pit, ++it) {
// sum = ComputeChecksum(sum, *it);
// absl::PrefetchToLocalCache(pit->data());
// }
// for (; it != end; ++it) {
// sum = ComputeChecksum(sum, *it);
// }
// return sum;
// }
//
void PrefetchToLocalCache(const void* addr);

// Moves data into the L1 cache before it is read, or "prefetches" it.
//
// This function is identical to `PrefetchToLocalCache()` except that it has
// non-temporal locality: the fetched data should not be left in any of the
// cache tiers. This is useful for cases where the data is used only once /
// short term, for example, invoking a destructor on an object.
//
// Incorrect or gratuitous use of this function can degrade performance.
// Use this function only when representative benchmarks show an improvement.
//
// Example:
//
// template <typename Iterator>
// void DestroyPointers(Iterator begin, Iterator end) {
// size_t distance = std::min(8U, bars.size());
//
// int dist = 8;
// auto prefetch_it = begin;
// while (prefetch_it != end && --dist;) {
// absl::PrefetchToLocalCacheNta(*prefetch_it++);
// }
// while (prefetch_it != end) {
// delete *begin++;
// absl::PrefetchToLocalCacheNta(*prefetch_it++);
// }
// while (begin != end) {
// delete *begin++;
// }
// }
//
void PrefetchToLocalCacheNta(const void* addr);

// Moves data into the L1 cache with the intent to modify it.
//
// This function is similar to `PrefetchToLocalCache()` except that it
// prefetches cachelines with an 'intent to modify' This typically includes
// invalidating cache entries for this address in all other cache tiers, and an
// exclusive access intent.
//
// Incorrect or gratuitous use of this function can degrade performance. As this
// function can invalidate cached cachelines on other caches and computer cores,
// incorrect usage of this function can have an even greater negative impact
// than incorrect regular prefetches.
// Use this function only when representative benchmarks show an improvement.
//
// Example:
//
// void* Arena::Allocate(size_t size) {
// void* ptr = AllocateBlock(size);
// absl::PrefetchToLocalCacheForWrite(p);
// return ptr;
// }
//
void PrefetchToLocalCacheForWrite(const void* addr);

#if ABSL_HAVE_BUILTIN(__builtin_prefetch) || defined(__GNUC__)

#define ABSL_HAVE_PREFETCH 1

// See __builtin_prefetch:
// https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html.
//
inline void PrefetchToLocalCache(const void* addr) {
__builtin_prefetch(addr, 0, 3);
}

inline void PrefetchToLocalCacheNta(const void* addr) {
__builtin_prefetch(addr, 0, 0);
}

inline void PrefetchToLocalCacheForWrite(const void* addr) {
// [x86] gcc/clang don't generate PREFETCHW for __builtin_prefetch(.., 1)
// unless -march=broadwell or newer; this is not generally the default, so we
// manually emit prefetchw. PREFETCHW is recognized as a no-op on older Intel
// processors and has been present on AMD processors since the K6-2.
#if defined(__x86_64__)
asm("prefetchw (%0)" : : "r"(addr));
#else
__builtin_prefetch(addr, 1, 3);
#endif
}

#elif defined(ABSL_INTERNAL_HAVE_SSE)

#define ABSL_HAVE_PREFETCH 1

inline void PrefetchToLocalCache(const void* addr) {
_mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_T0);
}

inline void PrefetchToLocalCacheNta(const void* addr) {
_mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_NTA);
}

inline void PrefetchToLocalCacheForWrite(const void* addr) {
#if defined(_MM_HINT_ET0)
_mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_ET0);
#elif !defined(_MSC_VER) && defined(__x86_64__)
// _MM_HINT_ET0 is not universally supported. As we commented further
// up, PREFETCHW is recognized as a no-op on older Intel processors
// and has been present on AMD processors since the K6-2. We have this
// disabled for MSVC compilers as this miscompiles on older MSVC compilers.
asm("prefetchw (%0)" : : "r"(addr));
#endif
}

#else

inline void PrefetchToLocalCache(const void* addr) {}
inline void PrefetchToLocalCacheNta(const void* addr) {}
inline void PrefetchToLocalCacheForWrite(const void* addr) {}

#endif

ABSL_NAMESPACE_END
} // namespace absl

#endif // ABSL_BASE_PREFETCH_H_
44 changes: 39 additions & 5 deletions src/absl/container/btree_map.h
Original file line number Diff line number Diff line change
@@ -42,10 +42,13 @@
// Importantly, insertions and deletions may invalidate outstanding iterators,
// pointers, and references to elements. Such invalidations are typically only
// an issue if insertion and deletion operations are interleaved with the use of
// more than one iterator, pointer, or reference simultaneously. For this
// reason, `insert()` and `erase()` return a valid iterator at the current
// position. Another important difference is that key-types must be
// copy-constructible.
// more than one iterator, pointer, or reference simultaneously. For this
// reason, `insert()`, `erase()`, and `extract_and_get_next()` return a valid
// iterator at the current position. Another important difference is that
// key-types must be copy-constructible.
//
// Another API difference is that btree iterators can be subtracted, and this
// is faster than using std::distance.

#ifndef ABSL_CONTAINER_BTREE_MAP_H_
#define ABSL_CONTAINER_BTREE_MAP_H_
@@ -322,7 +325,8 @@ class btree_map
// btree_map::extract()
//
// Extracts the indicated element, erasing it in the process, and returns it
// as a C++17-compatible node handle. Overloads are listed below.
// as a C++17-compatible node handle. Any references, pointers, or iterators
// are invalidated. Overloads are listed below.
//
// node_type extract(const_iterator position):
//
@@ -347,6 +351,21 @@ class btree_map
// It does NOT refer to the data layout of the underlying btree.
using Base::extract;

// btree_map::extract_and_get_next()
//
// Extracts the indicated element, erasing it in the process, and returns it
// as a C++17-compatible node handle along with an iterator to the next
// element.
//
// extract_and_get_next_return_type extract_and_get_next(
// const_iterator position):
//
// Extracts the element at the indicated position, returns a struct
// containing a member named `node`: a node handle owning that extracted
// data and a member named `next`: an iterator pointing to the next element
// in the btree.
using Base::extract_and_get_next;

// btree_map::merge()
//
// Extracts elements from a given `source` btree_map into this
@@ -698,6 +717,21 @@ class btree_multimap
// It does NOT refer to the data layout of the underlying btree.
using Base::extract;

// btree_multimap::extract_and_get_next()
//
// Extracts the indicated element, erasing it in the process, and returns it
// as a C++17-compatible node handle along with an iterator to the next
// element.
//
// extract_and_get_next_return_type extract_and_get_next(
// const_iterator position):
//
// Extracts the element at the indicated position, returns a struct
// containing a member named `node`: a node handle owning that extracted
// data and a member named `next`: an iterator pointing to the next element
// in the btree.
using Base::extract_and_get_next;

// btree_multimap::merge()
//
// Extracts all elements from a given `source` btree_multimap into this
46 changes: 37 additions & 9 deletions src/absl/container/btree_set.h
Original file line number Diff line number Diff line change
@@ -43,8 +43,11 @@
// pointers, and references to elements. Such invalidations are typically only
// an issue if insertion and deletion operations are interleaved with the use of
// more than one iterator, pointer, or reference simultaneously. For this
// reason, `insert()` and `erase()` return a valid iterator at the current
// position.
// reason, `insert()`, `erase()`, and `extract_and_get_next()` return a valid
// iterator at the current position.
//
// Another API difference is that btree iterators can be subtracted, and this
// is faster than using std::distance.

#ifndef ABSL_CONTAINER_BTREE_SET_H_
#define ABSL_CONTAINER_BTREE_SET_H_
@@ -269,7 +272,8 @@ class btree_set
// btree_set::extract()
//
// Extracts the indicated element, erasing it in the process, and returns it
// as a C++17-compatible node handle. Overloads are listed below.
// as a C++17-compatible node handle. Any references, pointers, or iterators
// are invalidated. Overloads are listed below.
//
// node_type extract(const_iterator position):
//
@@ -289,6 +293,21 @@ class btree_set
// It does NOT refer to the data layout of the underlying btree.
using Base::extract;

// btree_set::extract_and_get_next()
//
// Extracts the indicated element, erasing it in the process, and returns it
// as a C++17-compatible node handle along with an iterator to the next
// element.
//
// extract_and_get_next_return_type extract_and_get_next(
// const_iterator position):
//
// Extracts the element at the indicated position, returns a struct
// containing a member named `node`: a node handle owning that extracted
// data and a member named `next`: an iterator pointing to the next element
// in the btree.
using Base::extract_and_get_next;

// btree_set::merge()
//
// Extracts elements from a given `source` btree_set into this
@@ -611,6 +630,21 @@ class btree_multiset
// It does NOT refer to the data layout of the underlying btree.
using Base::extract;

// btree_multiset::extract_and_get_next()
//
// Extracts the indicated element, erasing it in the process, and returns it
// as a C++17-compatible node handle along with an iterator to the next
// element.
//
// extract_and_get_next_return_type extract_and_get_next(
// const_iterator position):
//
// Extracts the element at the indicated position, returns a struct
// containing a member named `node`: a node handle owning that extracted
// data and a member named `next`: an iterator pointing to the next element
// in the btree.
using Base::extract_and_get_next;

// btree_multiset::merge()
//
// Extracts all elements from a given `source` btree_multiset into this
@@ -760,12 +794,6 @@ struct set_slot_policy {
static void destroy(Alloc *alloc, slot_type *slot) {
absl::allocator_traits<Alloc>::destroy(*alloc, slot);
}

template <typename Alloc>
static void transfer(Alloc *alloc, slot_type *new_slot, slot_type *old_slot) {
construct(alloc, new_slot, old_slot);
destroy(alloc, old_slot);
}
};

// A parameters structure for holding the type parameters for a btree_set.
95 changes: 61 additions & 34 deletions src/absl/container/fixed_array.h
Original file line number Diff line number Diff line change
@@ -62,11 +62,10 @@ constexpr static auto kFixedArrayUseDefault = static_cast<size_t>(-1);
// A `FixedArray` provides a run-time fixed-size array, allocating a small array
// inline for efficiency.
//
// Most users should not specify an `inline_elements` argument and let
// `FixedArray` automatically determine the number of elements
// to store inline based on `sizeof(T)`. If `inline_elements` is specified, the
// `FixedArray` implementation will use inline storage for arrays with a
// length <= `inline_elements`.
// Most users should not specify the `N` template parameter and let `FixedArray`
// automatically determine the number of elements to store inline based on
// `sizeof(T)`. If `N` is specified, the `FixedArray` implementation will use
// inline storage for arrays with a length <= `N`.
//
// Note that a `FixedArray` constructed with a `size_type` argument will
// default-initialize its values by leaving trivially constructible types
@@ -118,14 +117,20 @@ class FixedArray {
(N == kFixedArrayUseDefault ? kInlineBytesDefault / sizeof(value_type)
: static_cast<size_type>(N));

FixedArray(
const FixedArray& other,
const allocator_type& a = allocator_type()) noexcept(NoexceptCopyable())
FixedArray(const FixedArray& other) noexcept(NoexceptCopyable())
: FixedArray(other,
AllocatorTraits::select_on_container_copy_construction(
other.storage_.alloc())) {}

FixedArray(const FixedArray& other,
const allocator_type& a) noexcept(NoexceptCopyable())
: FixedArray(other.begin(), other.end(), a) {}

FixedArray(
FixedArray&& other,
const allocator_type& a = allocator_type()) noexcept(NoexceptMovable())
FixedArray(FixedArray&& other) noexcept(NoexceptMovable())
: FixedArray(std::move(other), other.storage_.alloc()) {}

FixedArray(FixedArray&& other,
const allocator_type& a) noexcept(NoexceptMovable())
: FixedArray(std::make_move_iterator(other.begin()),
std::make_move_iterator(other.end()), a) {}

@@ -201,26 +206,30 @@ class FixedArray {
//
// Returns a const T* pointer to elements of the `FixedArray`. This pointer
// can be used to access (but not modify) the contained elements.
const_pointer data() const { return AsValueType(storage_.begin()); }
const_pointer data() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return AsValueType(storage_.begin());
}

// Overload of FixedArray::data() to return a T* pointer to elements of the
// fixed array. This pointer can be used to access and modify the contained
// elements.
pointer data() { return AsValueType(storage_.begin()); }
pointer data() ABSL_ATTRIBUTE_LIFETIME_BOUND {
return AsValueType(storage_.begin());
}

// FixedArray::operator[]
//
// Returns a reference the ith element of the fixed array.
// REQUIRES: 0 <= i < size()
reference operator[](size_type i) {
reference operator[](size_type i) ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(i < size());
return data()[i];
}

// Overload of FixedArray::operator()[] to return a const reference to the
// ith element of the fixed array.
// REQUIRES: 0 <= i < size()
const_reference operator[](size_type i) const {
const_reference operator[](size_type i) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(i < size());
return data()[i];
}
@@ -229,7 +238,7 @@ class FixedArray {
//
// Bounds-checked access. Returns a reference to the ith element of the fixed
// array, or throws std::out_of_range
reference at(size_type i) {
reference at(size_type i) ABSL_ATTRIBUTE_LIFETIME_BOUND {
if (ABSL_PREDICT_FALSE(i >= size())) {
base_internal::ThrowStdOutOfRange("FixedArray::at failed bounds check");
}
@@ -238,7 +247,7 @@ class FixedArray {

// Overload of FixedArray::at() to return a const reference to the ith element
// of the fixed array.
const_reference at(size_type i) const {
const_reference at(size_type i) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
if (ABSL_PREDICT_FALSE(i >= size())) {
base_internal::ThrowStdOutOfRange("FixedArray::at failed bounds check");
}
@@ -248,92 +257,104 @@ class FixedArray {
// FixedArray::front()
//
// Returns a reference to the first element of the fixed array.
reference front() {
reference front() ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(!empty());
return data()[0];
}

// Overload of FixedArray::front() to return a reference to the first element
// of a fixed array of const values.
const_reference front() const {
const_reference front() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(!empty());
return data()[0];
}

// FixedArray::back()
//
// Returns a reference to the last element of the fixed array.
reference back() {
reference back() ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(!empty());
return data()[size() - 1];
}

// Overload of FixedArray::back() to return a reference to the last element
// of a fixed array of const values.
const_reference back() const {
const_reference back() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(!empty());
return data()[size() - 1];
}

// FixedArray::begin()
//
// Returns an iterator to the beginning of the fixed array.
iterator begin() { return data(); }
iterator begin() ABSL_ATTRIBUTE_LIFETIME_BOUND { return data(); }

// Overload of FixedArray::begin() to return a const iterator to the
// beginning of the fixed array.
const_iterator begin() const { return data(); }
const_iterator begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND { return data(); }

// FixedArray::cbegin()
//
// Returns a const iterator to the beginning of the fixed array.
const_iterator cbegin() const { return begin(); }
const_iterator cbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return begin();
}

// FixedArray::end()
//
// Returns an iterator to the end of the fixed array.
iterator end() { return data() + size(); }
iterator end() ABSL_ATTRIBUTE_LIFETIME_BOUND { return data() + size(); }

// Overload of FixedArray::end() to return a const iterator to the end of the
// fixed array.
const_iterator end() const { return data() + size(); }
const_iterator end() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return data() + size();
}

// FixedArray::cend()
//
// Returns a const iterator to the end of the fixed array.
const_iterator cend() const { return end(); }
const_iterator cend() const ABSL_ATTRIBUTE_LIFETIME_BOUND { return end(); }

// FixedArray::rbegin()
//
// Returns a reverse iterator from the end of the fixed array.
reverse_iterator rbegin() { return reverse_iterator(end()); }
reverse_iterator rbegin() ABSL_ATTRIBUTE_LIFETIME_BOUND {
return reverse_iterator(end());
}

// Overload of FixedArray::rbegin() to return a const reverse iterator from
// the end of the fixed array.
const_reverse_iterator rbegin() const {
const_reverse_iterator rbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return const_reverse_iterator(end());
}

// FixedArray::crbegin()
//
// Returns a const reverse iterator from the end of the fixed array.
const_reverse_iterator crbegin() const { return rbegin(); }
const_reverse_iterator crbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return rbegin();
}

// FixedArray::rend()
//
// Returns a reverse iterator from the beginning of the fixed array.
reverse_iterator rend() { return reverse_iterator(begin()); }
reverse_iterator rend() ABSL_ATTRIBUTE_LIFETIME_BOUND {
return reverse_iterator(begin());
}

// Overload of FixedArray::rend() for returning a const reverse iterator
// from the beginning of the fixed array.
const_reverse_iterator rend() const {
const_reverse_iterator rend() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return const_reverse_iterator(begin());
}

// FixedArray::crend()
//
// Returns a reverse iterator from the beginning of the fixed array.
const_reverse_iterator crend() const { return rend(); }
const_reverse_iterator crend() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return rend();
}

// FixedArray::fill()
//
@@ -343,7 +364,7 @@ class FixedArray {
// Relational operators. Equality operators are elementwise using
// `operator==`, while order operators order FixedArrays lexicographically.
friend bool operator==(const FixedArray& lhs, const FixedArray& rhs) {
return absl::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
}

friend bool operator!=(const FixedArray& lhs, const FixedArray& rhs) {
@@ -465,12 +486,18 @@ class FixedArray {
StorageElement* begin() const { return data_; }
StorageElement* end() const { return begin() + size(); }
allocator_type& alloc() { return size_alloc_.template get<1>(); }
const allocator_type& alloc() const {
return size_alloc_.template get<1>();
}

private:
static bool UsingInlinedStorage(size_type n) {
return n <= inline_elements;
}

#ifdef ABSL_HAVE_ADDRESS_SANITIZER
ABSL_ATTRIBUTE_NOINLINE
#endif // ABSL_HAVE_ADDRESS_SANITIZER
StorageElement* InitializeData() {
if (UsingInlinedStorage(size())) {
InlinedStorage::AnnotateConstruct(size());
6 changes: 5 additions & 1 deletion src/absl/container/flat_hash_map.h
Original file line number Diff line number Diff line change
@@ -235,7 +235,11 @@ class flat_hash_map : public absl::container_internal::raw_hash_map<
// iterator erase(const_iterator first, const_iterator last):
//
// Erases the elements in the open interval [`first`, `last`), returning an
// iterator pointing to `last`.
// iterator pointing to `last`. The special case of calling
// `erase(begin(), end())` resets the reserved growth such that if
// `reserve(N)` has previously been called and there has been no intervening
// call to `clear()`, then after calling `erase(begin(), end())`, it is safe
// to assume that inserting N elements will not cause a rehash.
//
// size_type erase(const key_type& key):
//
15 changes: 6 additions & 9 deletions src/absl/container/flat_hash_set.h
Original file line number Diff line number Diff line change
@@ -227,7 +227,11 @@ class flat_hash_set
// iterator erase(const_iterator first, const_iterator last):
//
// Erases the elements in the open interval [`first`, `last`), returning an
// iterator pointing to `last`.
// iterator pointing to `last`. The special case of calling
// `erase(begin(), end())` resets the reserved growth such that if
// `reserve(N)` has previously been called and there has been no intervening
// call to `clear()`, then after calling `erase(begin(), end())`, it is safe
// to assume that inserting N elements will not cause a rehash.
//
// size_type erase(const key_type& key):
//
@@ -343,7 +347,7 @@ class flat_hash_set
// for the past-the-end iterator, which is invalidated.
//
// `swap()` requires that the flat hash set's hashing and key equivalence
// functions be Swappable, and are exchaged using unqualified calls to
// functions be Swappable, and are exchanged using unqualified calls to
// non-member `swap()`. If the set's allocator has
// `std::allocator_traits<allocator_type>::propagate_on_container_swap::value`
// set to `true`, the allocators are also exchanged using an unqualified call
@@ -474,13 +478,6 @@ struct FlatHashSetPolicy {
absl::allocator_traits<Allocator>::destroy(*alloc, slot);
}

template <class Allocator>
static void transfer(Allocator* alloc, slot_type* new_slot,
slot_type* old_slot) {
construct(alloc, new_slot, std::move(*old_slot));
destroy(alloc, old_slot);
}

static T& element(slot_type* slot) { return *slot; }

template <class F, class... Args>
Loading