Skip to content

Commit e5b892b

Browse files
authored
Correct CMake script. Improve C++ language feature selection (#243)
* cmake: correct minimum version the previous script would fail with CMake < 3.13 anyway. * cmake: canonical way to set C++ options * ci: use modern CMake syntax * doc: modern CMake syntax * most compilers have C++17 fallthrough * correct logic for [[noreturn]] --------- Co-authored-by: scivision <scivision@users.noreply.github.com>
1 parent d88c5e1 commit e5b892b

File tree

6 files changed

+123
-82
lines changed

6 files changed

+123
-82
lines changed

.github/workflows/linux.yml

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,24 @@ jobs:
1414
compiler: [g++, clang++]
1515
flags: [-std=c++11, -std=c++17]
1616
optimize: [-O2]
17+
18+
env:
19+
CXX: ${{ matrix.compiler }}
20+
CXXFLAGS: ${{ matrix.flags }} ${{ matrix.optimize }}
21+
CTEST_OUTPUT_ON_FAILURE: 1
22+
CTEST_NO_TESTS_ACTION: error
23+
CTEST_PARALLEL_LEVEL: 0
24+
CMAKE_BUILD_PARALLEL_LEVEL: 4
25+
1726
steps:
1827
- name: Checkout
19-
uses: actions/checkout@v2.0.0
20-
- name: Build and test
21-
env:
22-
CXX: ${{ matrix.compiler }}
23-
CXXFLAGS: ${{ matrix.flags }} ${{ matrix.optimize }}
24-
run: |
25-
mkdir build && cd build && cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -DCMAKE_BUILD_TYPE=Release .. && cmake --build . && make test
28+
uses: actions/checkout@v4
29+
30+
- name: CMake configure
31+
run: cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -DCMAKE_BUILD_TYPE=Release -B build
32+
33+
- name: CMake build
34+
run: cmake --build build
35+
36+
- name: CMake test
37+
run: ctest --test-dir build

.github/workflows/macos.yml

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,24 @@ jobs:
1414
compiler: [g++, clang++]
1515
flags: [-std=c++11, -std=c++17]
1616
optimize: [-O2]
17+
18+
env:
19+
CXX: ${{ matrix.compiler }}
20+
CXXFLAGS: ${{ matrix.flags }} ${{ matrix.optimize }}
21+
CTEST_OUTPUT_ON_FAILURE: 1
22+
CTEST_NO_TESTS_ACTION: error
23+
CTEST_PARALLEL_LEVEL: 0
24+
CMAKE_BUILD_PARALLEL_LEVEL: 4
25+
1726
steps:
1827
- name: Checkout
19-
uses: actions/checkout@v2.0.0
20-
- name: Build and test
21-
env:
22-
CXX: ${{ matrix.compiler }}
23-
CXXFLAGS: ${{ matrix.flags }} ${{ matrix.optimize }}
24-
run: |
25-
mkdir build && cd build && cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -DCMAKE_BUILD_TYPE=Release .. && cmake --build . && make test
28+
uses: actions/checkout@v4
29+
30+
- name: CMake configure
31+
run: cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -DCMAKE_BUILD_TYPE=Release -B build
32+
33+
- name: CMake build
34+
run: cmake --build build
35+
36+
- name: CMake test
37+
run: ctest --test-dir build

.github/workflows/windows.yml

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,23 @@ jobs:
1313
os: [windows-latest]
1414
flags: ["/std:c++11", "/std:c++latest"]
1515
optimize: [/O2]
16+
17+
env:
18+
CXXFLAGS: ${{ matrix.flags }} ${{ matrix.optimize }}
19+
CTEST_OUTPUT_ON_FAILURE: 1
20+
CTEST_NO_TESTS_ACTION: error
21+
CTEST_PARALLEL_LEVEL: 0
22+
CMAKE_BUILD_PARALLEL_LEVEL: 4
23+
1624
steps:
1725
- name: Checkout
18-
uses: actions/checkout@v2.0.0
19-
- name: Build and test
20-
env:
21-
CXX: ${{ matrix.compiler }}
22-
CXXFLAGS: ${{ matrix.flags }} ${{ matrix.optimize }}
23-
CTEST_OUTPUT_ON_FAILURE: 1
24-
run: |
25-
cmake -Bbuild -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -DCMAKE_BUILD_TYPE=Release && cmake --build build --target ALL_BUILD && cmake --build build --target RUN_TESTS
26+
uses: actions/checkout@v4
27+
28+
- name: CMake configure
29+
run: cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -B build
30+
31+
- name: CMake build
32+
run: cmake --build build --config Release
33+
34+
- name: CMake test
35+
run: ctest --test-dir build -C Release

CMakeLists.txt

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,12 @@
1717
1818
#]===================================================================]
1919

20-
cmake_minimum_required(VERSION 3.8)
20+
cmake_minimum_required(VERSION 3.13)
2121

2222
list (APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
2323

2424
include(DetectVersion)
2525

26-
cmake_policy(SET CMP0048 NEW) ## set VERSION as documented by the project() command.
27-
cmake_policy(SET CMP0076 NEW) ## accept new policy
28-
2926
if(NOT CMAKE_CXX_STANDARD)
3027
set(CMAKE_CXX_STANDARD 11) ## compile with C++11 support
3128
endif()
@@ -48,14 +45,14 @@ option(PHMAP_INSTALL "Enable installation" ${PHMAP_MASTER_PROJECT})
4845

4946

5047
set(PHMAP_DIR parallel_hashmap)
51-
set(PHMAP_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/${PHMAP_DIR}/phmap.h
52-
${CMAKE_CURRENT_SOURCE_DIR}/${PHMAP_DIR}/phmap_base.h
53-
${CMAKE_CURRENT_SOURCE_DIR}/${PHMAP_DIR}/phmap_bits.h
48+
set(PHMAP_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/${PHMAP_DIR}/phmap.h
49+
${CMAKE_CURRENT_SOURCE_DIR}/${PHMAP_DIR}/phmap_base.h
50+
${CMAKE_CURRENT_SOURCE_DIR}/${PHMAP_DIR}/phmap_bits.h
5451
${CMAKE_CURRENT_SOURCE_DIR}/${PHMAP_DIR}/phmap_config.h
55-
${CMAKE_CURRENT_SOURCE_DIR}/${PHMAP_DIR}/phmap_dump.h
56-
${CMAKE_CURRENT_SOURCE_DIR}/${PHMAP_DIR}/phmap_fwd_decl.h
57-
${CMAKE_CURRENT_SOURCE_DIR}/${PHMAP_DIR}/phmap_utils.h
58-
${CMAKE_CURRENT_SOURCE_DIR}/${PHMAP_DIR}/meminfo.h
52+
${CMAKE_CURRENT_SOURCE_DIR}/${PHMAP_DIR}/phmap_dump.h
53+
${CMAKE_CURRENT_SOURCE_DIR}/${PHMAP_DIR}/phmap_fwd_decl.h
54+
${CMAKE_CURRENT_SOURCE_DIR}/${PHMAP_DIR}/phmap_utils.h
55+
${CMAKE_CURRENT_SOURCE_DIR}/${PHMAP_DIR}/meminfo.h
5956
${CMAKE_CURRENT_SOURCE_DIR}/${PHMAP_DIR}/btree.h)
6057

6158
include(helpers)
@@ -72,14 +69,14 @@ target_include_directories(
7269
if(PHMAP_INSTALL)
7370
include(GNUInstallDirs)
7471
include(CMakePackageConfigHelpers)
75-
72+
7673
install(
7774
DIRECTORY ${PROJECT_SOURCE_DIR}/${PHMAP_DIR}/
7875
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PHMAP_DIR})
79-
76+
8077
install(TARGETS ${PROJECT_NAME}
8178
EXPORT ${PROJECT_NAME}-targets)
82-
79+
8380
export(EXPORT ${PROJECT_NAME}-targets
8481
FILE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake")
8582
endif()
@@ -89,7 +86,7 @@ option(PHMAP_BUILD_TESTS "Whether or not to build the tests" ${PHMAP_MASTE
8986
option(PHMAP_BUILD_EXAMPLES "Whether or not to build the examples" ${PHMAP_MASTER_PROJECT})
9087

9188
if(MSVC)
92-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj")
89+
add_compile_options("$<$<COMPILE_LANGUAGE:CXX>:/bigobj>")
9390
endif()
9491

9592
if (PHMAP_BUILD_TESTS OR PHMAP_BUILD_EXAMPLES)
@@ -100,7 +97,7 @@ if (PHMAP_BUILD_TESTS)
10097

10198
if (NOT PHMAP_GTEST_LIBS)
10299
include(cmake/DownloadGTest.cmake)
103-
100+
104101
check_target(gtest)
105102
check_target(gtest_main)
106103
check_target(gmock)
@@ -169,12 +166,12 @@ endif()
169166

170167
if (PHMAP_BUILD_EXAMPLES)
171168
if(NOT MSVC)
172-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic -Wall -Wextra -Wcast-align -Wcast-qual -Wdisabled-optimization -Winit-self -Wlogical-op -Wmissing-include-dirs -Woverloaded-virtual -Wredundant-decls -Wshadow -Wstrict-null-sentinel -Wswitch-default -Wno-unused")
169+
add_compile_options("$<$<COMPILE_LANGUAGE:CXX>:-pedantic;-Wall;-Wextra;-Wcast-align;-Wcast-qual;-Wdisabled-optimization;-Winit-self;-Wlogical-op;-Wmissing-include-dirs;-Woverloaded-virtual;-Wredundant-decls;-Wshadow;-Wstrict-null-sentinel;-Wswitch-default;-Wno-unused>")
173170
if (NOT CMAKE_COMPILER_IS_GNUCC OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 5.0)
174-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unknown-warning-option -Wno-gnu-zero-variadic-macro-arguments")
171+
add_compile_options("$<$<COMPILE_LANGUAGE:CXX>:-Wno-unknown-warning-option;-Wno-gnu-zero-variadic-macro-arguments>")
175172
endif()
176173
else()
177-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4 /Zc:__cplusplus")
174+
add_compile_options("$<$<COMPILE_LANGUAGE:CXX>:/W4;/Zc:__cplusplus>")
178175
endif()
179176

180177
set(THREADS_PREFER_PTHREAD_FLAG ON)
@@ -203,8 +200,8 @@ if (PHMAP_BUILD_EXAMPLES)
203200
add_executable(ex_p_bench examples/p_bench.cc phmap.natvis)
204201

205202
#set(Boost_INCLUDE_DIR /home/greg/dev/boost_1_82_0) # if boost installed in non-standard location
206-
set(Boost_USE_STATIC_LIBS OFF)
207-
set(Boost_USE_MULTITHREADED ON)
203+
set(Boost_USE_STATIC_LIBS OFF)
204+
set(Boost_USE_MULTITHREADED ON)
208205
set(Boost_USE_STATIC_RUNTIME OFF)
209206

210207
# llil4map.cc - see https://www.perlmonks.com/?node_id=11149643
@@ -223,8 +220,7 @@ if (PHMAP_BUILD_EXAMPLES)
223220
target_compile_options(ex_llil4map PRIVATE "${OpenMP_CXX_FLAGS}")
224221
file(COPY examples/llil_utils DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
225222
endif()
226-
223+
227224
target_link_libraries(ex_knucleotide Threads::Threads)
228225
target_link_libraries(ex_bench Threads::Threads)
229226
endif()
230-

README.md

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11

2-
<img src="https://github.com/greg7mdp/parallel-hashmap/blob/master/html/img/phash.png?raw=true" width="120" align="middle">
2+
<img src="https://github.com/greg7mdp/parallel-hashmap/blob/master/html/img/phash.png?raw=true" width="120" align="middle">
33

4-
# The Parallel Hashmap
4+
# The Parallel Hashmap
55

6-
[![License: Apache-2.0](https://img.shields.io/badge/License-Apache-yellow.svg)](https://opensource.org/licenses/Apache-2.0) [![Linux](https://github.com/greg7mdp/parallel-hashmap/actions/workflows/linux.yml/badge.svg)](https://github.com/greg7mdp/parallel-hashmap/actions/workflows/linux.yml) [![MacOS](https://github.com/greg7mdp/parallel-hashmap/actions/workflows/macos.yml/badge.svg)](https://github.com/greg7mdp/parallel-hashmap/actions/workflows/macos.yml) [![Windows](https://github.com/greg7mdp/parallel-hashmap/actions/workflows/windows.yml/badge.svg)](https://github.com/greg7mdp/parallel-hashmap/actions/workflows/windows.yml)
6+
[![License: Apache-2.0](https://img.shields.io/badge/License-Apache-yellow.svg)](https://opensource.org/licenses/Apache-2.0) [![Linux](https://github.com/greg7mdp/parallel-hashmap/actions/workflows/linux.yml/badge.svg)](https://github.com/greg7mdp/parallel-hashmap/actions/workflows/linux.yml) [![MacOS](https://github.com/greg7mdp/parallel-hashmap/actions/workflows/macos.yml/badge.svg)](https://github.com/greg7mdp/parallel-hashmap/actions/workflows/macos.yml) [![Windows](https://github.com/greg7mdp/parallel-hashmap/actions/workflows/windows.yml/badge.svg)](https://github.com/greg7mdp/parallel-hashmap/actions/workflows/windows.yml)
77

88
## Overview
99

10-
This repository aims to provide a set of excellent **hash map** implementations, as well as a **btree** alternative to std::map and std::set, with the following characteristics:
10+
This repository aims to provide a set of excellent **hash map** implementations, as well as a **btree** alternative to std::map and std::set, with the following characteristics:
1111

1212
- **Header only**: nothing to build, just copy the `parallel_hashmap` directory to your project and you are good to go.
1313

@@ -48,7 +48,15 @@ Copy the parallel_hashmap directory to your project. Update your include path. T
4848

4949
If you are using Visual Studio, you probably want to add `phmap.natvis` to your projects. This will allow for a clear display of the hash table contents in the debugger.
5050

51-
> A cmake configuration files (CMakeLists.txt) is provided for building the tests and examples. Command for building and running the tests is: `mkdir build && cd build && cmake -DPHMAP_BUILD_TESTS=ON -DPHMAP_BUILD_EXAMPLES=ON .. && cmake --build . && make test`
51+
> A cmake configuration files (CMakeLists.txt) is provided for building the tests and examples. Command for building and running the tests is:
52+
53+
```sh
54+
cmake -DPHMAP_BUILD_TESTS=ON -DPHMAP_BUILD_EXAMPLES=ON -B build
55+
56+
cmake --build build
57+
58+
ctest --test-dir build
59+
```
5260

5361
## Example
5462

@@ -58,27 +66,27 @@ If you are using Visual Studio, you probably want to add `phmap.natvis` to your
5866
#include <parallel_hashmap/phmap.h>
5967

6068
using phmap::flat_hash_map;
61-
69+
6270
int main()
6371
{
6472
// Create an unordered_map of three strings (that map to strings)
65-
flat_hash_map<std::string, std::string> email =
73+
flat_hash_map<std::string, std::string> email =
6674
{
6775
{ "tom", "tom@gmail.com"},
6876
{ "jeff", "jk@gmail.com"},
6977
{ "jim", "jimg@microsoft.com"}
7078
};
71-
72-
// Iterate and print keys and values
73-
for (const auto& n : email)
79+
80+
// Iterate and print keys and values
81+
for (const auto& n : email)
7482
std::cout << n.first << "'s email is: " << n.second << "\n";
75-
83+
7684
// Add a new entry
7785
email["bill"] = "bg@whatever.com";
78-
86+
7987
// and print it
8088
std::cout << "bill's email is: " << email["bill"] << "\n";
81-
89+
8290
return 0;
8391
}
8492
```
@@ -115,8 +123,8 @@ The full types with template parameters can be found in the [parallel_hashmap/ph
115123

116124
- The `parallel` hash maps are preferred when you have a few hash maps that will store a very large number of values. The `non-parallel` hash maps are preferred if you have a large number of hash maps, each storing a relatively small number of values.
117125

118-
- The benefits of the `parallel` hash maps are:
119-
a. reduced peak memory usage (when resizing), and
126+
- The benefits of the `parallel` hash maps are:
127+
a. reduced peak memory usage (when resizing), and
120128
b. multithreading support (and inherent internal parallelism)
121129

122130
**Key decision points for btree containers:**
@@ -139,7 +147,7 @@ When an ordering is not needed, a hash container is typically a better choice th
139147

140148
- The Abseil hash tables internally randomize a hash seed, so that the table iteration order is non-deterministic. This can be useful to prevent *Denial Of Service* attacks when a hash table is used for a customer facing web service, but it can make debugging more difficult. The *phmap* hashmaps by default do **not** implement this randomization, but it can be enabled by adding `#define PHMAP_NON_DETERMINISTIC 1` before including the header `phmap.h` (as is done in raw_hash_set_test.cc).
141149

142-
- Unlike the Abseil hash maps, we do an internal mixing of the hash value provided. This prevents serious degradation of the hash table performance when the hash function provided by the user has poor entropy distribution. The cost in performance is very minimal, and this helps provide reliable performance even with *imperfect* hash functions.
150+
- Unlike the Abseil hash maps, we do an internal mixing of the hash value provided. This prevents serious degradation of the hash table performance when the hash function provided by the user has poor entropy distribution. The cost in performance is very minimal, and this helps provide reliable performance even with *imperfect* hash functions.
143151

144152

145153
## Memory usage
@@ -189,10 +197,10 @@ In order to use a flat_hash_set or flat_hash_map, a hash function should be prov
189197

190198
- Provide a hash functor via the HashFcn template parameter
191199

192-
- As with boost, you may add a `hash_value()` friend function in your class.
200+
- As with boost, you may add a `hash_value()` friend function in your class.
193201

194202
For example:
195-
203+
196204
```c++
197205
#include <parallel_hashmap/phmap_utils.h> // minimal header providing phmap::HashState()
198206
#include <string>
@@ -201,8 +209,8 @@ using std::string;
201209
struct Person
202210
{
203211
bool operator==(const Person &o) const
204-
{
205-
return _first == o._first && _last == o._last && _age == o._age;
212+
{
213+
return _first == o._first && _last == o._last && _age == o._age;
206214
}
207215

208216
friend size_t hash_value(const Person &p)
@@ -230,8 +238,8 @@ using std::string;
230238
struct Person
231239
{
232240
bool operator==(const Person &o) const
233-
{
234-
return _first == o._first && _last == o._last && _age == o._age;
241+
{
242+
return _first == o._first && _last == o._last && _age == o._age;
235243
}
236244

237245
string _first;
@@ -253,7 +261,7 @@ namespace std
253261
}
254262
```
255263

256-
The `std::hash` specialization for `Person` combines the hash values for both first and last name and age, using the convenient phmap::HashState() function, and returns the combined hash value.
264+
The `std::hash` specialization for `Person` combines the hash values for both first and last name and age, using the convenient phmap::HashState() function, and returns the combined hash value.
257265

258266
### file "main.cpp"
259267

@@ -268,7 +276,7 @@ int main()
268276
// As we have defined a specialization of std::hash() for Person,
269277
// we can now create sparse_hash_set or sparse_hash_map of Persons
270278
// ----------------------------------------------------------------
271-
phmap::flat_hash_set<Person> persons =
279+
phmap::flat_hash_set<Person> persons =
272280
{ { "John", "Mitchell", 35 },
273281
{ "Jane", "Smith", 32 },
274282
{ "Jane", "Smith", 30 },
@@ -287,7 +295,7 @@ Parallel Hashmap containers follow the thread safety rules of the Standard C++ l
287295

288296
- A single phmap hash table is thread safe for reading from multiple threads. For example, given a hash table A, it is safe to read A from thread 1 and from thread 2 simultaneously.
289297

290-
- If a single hash table is being written to by one thread, then all reads and writes to that hash table on the same or other threads must be protected. For example, given a hash table A, if thread 1 is writing to A, then thread 2 must be prevented from reading from or writing to A.
298+
- If a single hash table is being written to by one thread, then all reads and writes to that hash table on the same or other threads must be protected. For example, given a hash table A, if thread 1 is writing to A, then thread 2 must be prevented from reading from or writing to A.
291299

292300
- It is safe to read and write to one instance of a type even if another thread is reading or writing to a different instance of the same type. For example, given hash tables A and B of the same type, it is safe if A is being written in thread 1 and B is being read in thread 2.
293301

@@ -304,4 +312,4 @@ While C++ is the native language of the Parallel Hashmap, we welcome bindings ma
304312

305313
## Acknowledgements
306314

307-
Many thanks to the Abseil developers for implementing the swiss table and btree data structures (see [abseil-cpp](https://github.com/abseil/abseil-cpp)) upon which this work is based, and to Google for releasing it as open-source.
315+
Many thanks to the Abseil developers for implementing the swiss table and btree data structures (see [abseil-cpp](https://github.com/abseil/abseil-cpp)) upon which this work is based, and to Google for releasing it as open-source.

0 commit comments

Comments
 (0)