blob: fb8b4d4e6a7156147e8c6c4bfa1f8c30b33c9f5f [file] [log] [blame]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
include(CheckIncludeFileCXX)
include(CheckCXXSourceCompiles)
# Find a threading library we can use.
set(FOUND_THREADS FALSE)
if(NOT FOUND_THREADS)
CHECK_CXX_SOURCE_COMPILES("
#include <thread>
#include <mutex>
#include <condition_variable>
int main() {
std::thread t;
std::mutex m;
std::recursive_mutex rm;
std::condition_variable_any cv;
std::lock_guard<std::mutex> lock_m(m);
std::lock_guard<std::recursive_mutex> lock_rm(rm);
return 0;
}
" QUICKSTEP_HAVE_CPP11_THREADS)
if (QUICKSTEP_HAVE_CPP11_THREADS)
CHECK_CXX_SOURCE_COMPILES("
#include <shared_mutex>
int main() {
std::shared_mutex m;
m.lock();
m.unlock();
m.lock_shared();
m.unlock_shared();
return 0;
}
" QUICKSTEP_HAVE_CPP17_SHARED_MUTEX)
if (NOT QUICKSTEP_HAVE_CPP17_SHARED_MUTEX)
CHECK_CXX_SOURCE_COMPILES("
#include <shared_mutex>
int main() {
std::shared_timed_mutex m;
m.lock();
m.unlock();
m.lock_shared();
m.unlock_shared();
return 0;
}
" QUICKSTEP_HAVE_CPP14_SHARED_TIMED_MUTEX)
endif()
message("Using threading implementation: cpp11")
set(FOUND_THREADS TRUE)
endif()
endif()
if(NOT FOUND_THREADS)
if(CMAKE_HAVE_PTHREAD_H)
message("Using threading implementation: posix")
set(QUICKSTEP_HAVE_POSIX_THREADS TRUE)
set(FOUND_THREADS TRUE)
endif()
endif()
if(NOT FOUND_THREADS)
CHECK_CXX_SOURCE_COMPILES("
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
int main() {
CRITICAL_SECTION cs;
InitializeCriticalSection(&cs);
EnterCriticalSection(&cs);
LeaveCriticalSection(&cs);
DeleteCriticalSection(&cs);
return 0;
}
" QUICKSTEP_HAVE_WINDOWS_THREADS)
if (QUICKSTEP_HAVE_WINDOWS_THREADS)
message("Using threading implementation: windows")
set(FOUND_THREADS TRUE)
endif()
endif()
if(NOT FOUND_THREADS)
message(FATAL_ERROR "No viable threading library found.")
endif()
# Try to find some yield function we can use.
set(FOUND_YIELD FALSE)
if (NOT FOUND_YIELD)
CHECK_CXX_SOURCE_COMPILES("
#include <thread>
int main() {
std::this_thread::yield();
return 0;
}
" QUICKSTEP_HAVE_CPP11_YIELD)
if (QUICKSTEP_HAVE_CPP11_YIELD)
set(FOUND_YIELD TRUE)
endif()
endif()
if (NOT FOUND_YIELD)
CHECK_CXX_SOURCE_COMPILES("
#include <sched.h>
int main() {
sched_yield();
return 0;
}
" QUICKSTEP_HAVE_SCHED_YIELD)
if (QUICKSTEP_HAVE_SCHED_YIELD)
set(FOUND_YIELD TRUE)
endif()
endif()
if (NOT FOUND_YIELD)
CHECK_CXX_SOURCE_COMPILES("
#include <pthread.h>
int main() {
pthread_yield();
return 0;
}
" QUICKSTEP_HAVE_PTHREAD_YIELD)
if (QUICKSTEP_HAVE_PTHREAD_YIELD)
set(FOUND_YIELD TRUE)
endif()
endif()
if (NOT FOUND_YIELD)
CHECK_CXX_SOURCE_COMPILES("
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
int main() {
SwitchToThread();
return 0;
}
" QUICKSTEP_HAVE_WIN_SWITCHTOTHREAD)
if (QUICKSTEP_HAVE_WIN_SWITCHTOTHREAD)
set(FOUND_YIELD TRUE)
endif()
endif()
if(NOT FOUND_YIELD)
message(WARNING "No yield function found. ThreadUtil::Yield() will be a no-op.")
endif()
# Try to find a thread-affinitization function that we can use. First, try the
# Linux version of pthread_setaffinity_np().
CHECK_CXX_SOURCE_COMPILES("
#ifndef _GNU_SOURCE
#define _GNU_SOURCE 1
#endif
#include <pthread.h>
#include <sched.h>
int main() {
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(0, &cpuset);
if (pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset) != 0) {
return 1;
}
return 0;
}
" QUICKSTEP_HAVE_PTHREAD_SETAFFINITY_NP_LINUX)
# Next, try the FreeBSD version of pthread_setaffinity_np(). It is almost
# identical to the Linux version, except that it is in the special header
# pthread_np.h, and the CPU set type is called cpuset_t instead of cpu_set_t.
if (NOT QUICKSTEP_HAVE_PTHREAD_SETAFFINITY_NP_LINUX)
CHECK_CXX_SOURCE_COMPILES("
#ifndef _BSD_SOURCE
#define _BSD_SOURCE 1
#endif
#include <pthread.h>
#include <pthread_np.h>
#include <sched.h>
int main() {
cpuset_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(0, &cpuset);
if (pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset) != 0) {
return 1;
}
return 0;
}
" QUICKSTEP_HAVE_PTHREAD_SETAFFINITY_NP_FREEBSD)
endif()
# Finally, try the NetBSD version of pthread_setaffinity_np(). Unlike Linux or
# FreeBSD, NetBSD's version of cpuset_t is dynamically allocated/freed on the
# heap by some special functions in sched.h.
if (NOT (QUICKSTEP_HAVE_PTHREAD_SETAFFINITY_NP_LINUX OR QUICKSTEP_HAVE_PTHREAD_SETAFFINITY_NP_FREEBSD))
CHECK_CXX_SOURCE_COMPILES("
#ifndef _BSD_SOURCE
#define _BSD_SOURCE 1
#endif
#include <pthread.h>
#include <sched.h>
int main() {
cpuset_t *cset = cpuset_create();
if (cpuset_set(0, cset) != 0) {
return 1;
}
if (pthread_setaffinity_np(pthread_self(), cpuset_size(cset), cset) != 0) {
return 1;
}
cpuset_destroy(cset);
return 0;
}
" QUICKSTEP_HAVE_PTHREAD_SETAFFINITY_NP_NETBSD)
endif()
if (NOT (QUICKSTEP_HAVE_PTHREAD_SETAFFINITY_NP_LINUX
OR QUICKSTEP_HAVE_PTHREAD_SETAFFINITY_NP_FREEBSD
OR QUICKSTEP_HAVE_PTHREAD_SETAFFINITY_NP_NETBSD))
message(WARNING "Thread pinning operation will be a no-op.")
endif()
configure_file (
"${CMAKE_CURRENT_SOURCE_DIR}/ThreadingConfig.h.in"
"${CMAKE_CURRENT_BINARY_DIR}/ThreadingConfig.h"
)
# Declare micro-libs:
if (QUICKSTEP_HAVE_CPP11_THREADS)
add_library(quickstep_threading_ConditionVariable
ConditionVariable.cpp
ConditionVariable.hpp
cpp11/ConditionVariable.hpp)
add_library(quickstep_threading_Mutex
Mutex.cpp
Mutex.hpp
cpp11/Mutex.hpp)
if (QUICKSTEP_HAVE_CPP17_SHARED_MUTEX)
add_library(quickstep_threading_SharedMutex
../empty_src.cpp
SharedMutex.hpp
cpp11/cpp17/SharedMutex.hpp)
elseif (QUICKSTEP_HAVE_CPP14_SHARED_MUTEX)
add_library(quickstep_threading_SharedMutex
../empty_src.cpp
SharedMutex.hpp
cpp11/cpp14/SharedMutex.hpp)
else()
add_library(quickstep_threading_SharedMutex
../empty_src.cpp
SharedMutex.hpp
cpp11/SharedMutex.hpp)
endif()
add_library(quickstep_threading_Thread
Thread.cpp
Thread.hpp
cpp11/Thread.hpp)
elseif (QUICKSTEP_HAVE_POSIX_THREADS)
add_library(quickstep_threading_ConditionVariable
ConditionVariable.cpp
ConditionVariable.hpp
posix/ConditionVariable.hpp)
add_library(quickstep_threading_Mutex
Mutex.cpp
Mutex.hpp
posix/Mutex.hpp)
add_library(quickstep_threading_SharedMutex
../empty_src.cpp
SharedMutex.hpp
posix/SharedMutex.hpp)
add_library(quickstep_threading_Thread
Thread.cpp
Thread.hpp
posix/Thread.hpp)
elseif (QUICKSTEP_HAVE_WINDOWS_THREADS)
add_library(quickstep_threading_ConditionVariable
ConditionVariable.cpp
ConditionVariable.hpp
windows/ConditionVariable.hpp)
add_library(quickstep_threading_Mutex
Mutex.cpp
Mutex.hpp
windows/Mutex.hpp)
add_library(quickstep_threading_SharedMutex
../empty_src.cpp
SharedMutex.hpp
windows/SharedMutex.hpp)
add_library(quickstep_threading_Thread
Thread.cpp
Thread.hpp
windows/Thread.hpp)
endif()
add_library(quickstep_threading_SpinMutex ../empty_src.cpp SpinMutex.hpp)
add_library(quickstep_threading_SpinSharedMutex ../empty_src.cpp SpinSharedMutex.hpp)
add_library(quickstep_threading_ThreadIDBasedMap ../empty_src.cpp ThreadIDBasedMap.hpp)
add_library(quickstep_threading_ThreadUtil ../empty_src.cpp ThreadUtil.hpp)
add_library(quickstep_threading_WinThreadsAPI ../empty_src.cpp WinThreadsAPI.hpp)
# Link dependencies:
target_link_libraries(quickstep_threading_ConditionVariable
glog
quickstep_utility_Macros)
target_link_libraries(quickstep_threading_Mutex
glog
quickstep_threading_ConditionVariable
quickstep_utility_Macros
quickstep_utility_PtrVector)
target_link_libraries(quickstep_threading_SpinMutex
quickstep_threading_Mutex
quickstep_utility_Macros)
target_link_libraries(quickstep_threading_SpinSharedMutex
quickstep_threading_Mutex
quickstep_threading_SharedMutex
quickstep_threading_ThreadUtil
quickstep_utility_Macros)
target_link_libraries(quickstep_threading_Thread
quickstep_utility_Macros)
target_link_libraries(quickstep_threading_ThreadIDBasedMap
glog
quickstep_storage_StorageConstants
quickstep_threading_Mutex
quickstep_threading_SharedMutex
quickstep_threading_SpinSharedMutex
quickstep_utility_Macros)
target_link_libraries(quickstep_threading_ThreadUtil
quickstep_threading_WinThreadsAPI
quickstep_utility_Macros)
if (QUICKSTEP_HAVE_CPP11_THREADS AND NOT QUICKSTEP_HAVE_CPP14_SHARED_MUTEX)
target_link_libraries(quickstep_threading_SharedMutex
glog
quickstep_threading_ConditionVariable
quickstep_threading_Mutex
quickstep_utility_Macros)
else()
target_link_libraries(quickstep_threading_SharedMutex
quickstep_threading_Mutex
quickstep_utility_Macros)
endif()
# Module all-in-one library:
add_library(quickstep_threading ../empty_src.cpp ThreadingModule.hpp)
target_link_libraries(quickstep_threading
quickstep_threading_ConditionVariable
quickstep_threading_Mutex
quickstep_threading_SharedMutex
quickstep_threading_SpinMutex
quickstep_threading_SpinSharedMutex
quickstep_threading_Thread
quickstep_threading_ThreadIDBasedMap
quickstep_threading_ThreadUtil
quickstep_threading_WinThreadsAPI)
# Tests:
add_executable(Mutex_unittest "${CMAKE_CURRENT_SOURCE_DIR}/tests/Mutex_unittest.cpp")
target_link_libraries(Mutex_unittest
${CMAKE_THREAD_LIBS_INIT}
gtest
gtest_main
quickstep_threading_Mutex
quickstep_threading_SpinMutex
quickstep_threading_Thread
quickstep_utility_Macros)
add_test(Mutex_unittest Mutex_unittest)
add_executable(SharedMutex_unittest "${CMAKE_CURRENT_SOURCE_DIR}/tests/SharedMutex_unittest.cpp")
target_link_libraries(SharedMutex_unittest
${CMAKE_THREAD_LIBS_INIT}
gtest
gtest_main
quickstep_threading_Mutex
quickstep_threading_SharedMutex
quickstep_threading_SpinSharedMutex
quickstep_threading_Thread
quickstep_utility_Macros)
add_test(SharedMutex_unittest SharedMutex_unittest)