# This file should only be included when using Pthreads

INCLUDE (CheckFunctionExists)
INCLUDE (CheckLibraryExists)
INCLUDE (CheckSymbolExists)
INCLUDE (CheckCXXSourceCompiles)

SET(LIB_NAME OpenThreads)
SET(LIB_PUBLIC_HEADERS ${OpenThreads_PUBLIC_HEADERS})

ADD_LIBRARY(${LIB_NAME}
    ${OPENTHREADS_USER_DEFINED_DYNAMIC_OR_STATIC}
    ${LIB_PUBLIC_HEADERS}
    PThread.c++
    PThreadBarrier.c++
    PThreadBarrierPrivateData.h
    PThreadCondition.c++
    PThreadConditionPrivateData.h
    PThreadMutex.c++
    PThreadMutexPrivateData.h
    PThreadPrivateData.h
    ../common/Version.cpp
    ../common/Atomic.cpp
)

IF(OPENTHREADS_SONAMES)
  SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES VERSION ${OPENTHREADS_VERSION} SOVERSION ${OPENTHREADS_SOVERSION})
ENDIF(OPENTHREADS_SONAMES)

SET(CMAKE_REQUIRED_LIBRARIES_SAFE "${CMAKE_REQUIRED_LIBRARIES}")
SET(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})


CHECK_FUNCTION_EXISTS(pthread_yield HAVE_PTHREAD_YIELD)
IF(HAVE_PTHREAD_YIELD)
  ADD_DEFINITIONS(-DHAVE_PTHREAD_YIELD)
ELSE(HAVE_PTHREAD_YIELD)
  # sched_yield appears not in libc, pthreads or whatever on some systems
  CHECK_FUNCTION_EXISTS(sched_yield HAVE_SCHED_YIELD)
  IF(NOT HAVE_SCHED_YIELD)
    CHECK_LIBRARY_EXISTS(rt sched_yield "" HAVE_SCHED_YIELD)
    IF(HAVE_SCHED_YIELD)
      SET(CMAKE_THREAD_LIBS_INIT "${CMAKE_THREAD_LIBS_INIT} -lrt")
    ENDIF(HAVE_SCHED_YIELD)
  ENDIF(NOT HAVE_SCHED_YIELD)
  IF(HAVE_SCHED_YIELD)
    ADD_DEFINITIONS(-DHAVE_SCHED_YIELD)
  ENDIF(HAVE_SCHED_YIELD)
ENDIF(HAVE_PTHREAD_YIELD)

IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
  # need to have that for pthread_setaffinity_np on linux
  ADD_DEFINITIONS(-D_GNU_SOURCE)
  SET(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_GNU_SOURCE")
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")

CHECK_FUNCTION_EXISTS(pthread_setconcurrency HAVE_PTHREAD_SETCONCURRENCY)
IF(HAVE_PTHREAD_SETCONCURRENCY)
  ADD_DEFINITIONS(-DHAVE_PTHREAD_SETCONCURRENCY)
ENDIF(HAVE_PTHREAD_SETCONCURRENCY)

CHECK_FUNCTION_EXISTS(pthread_getconcurrency HAVE_PTHREAD_GETCONCURRENCY)
IF(HAVE_PTHREAD_GETCONCURRENCY)
  ADD_DEFINITIONS(-DHAVE_PTHREAD_GETCONCURRENCY)
ENDIF(HAVE_PTHREAD_GETCONCURRENCY)

CHECK_FUNCTION_EXISTS(pthread_setaffinity_np HAVE_PTHREAD_SETAFFINITY_NP)
IF(HAVE_PTHREAD_SETAFFINITY_NP)
  # double check that pthread_setaffinity_np is available as FreeBSD header doesn't contain required function
  CHECK_CXX_SOURCE_COMPILES("
        #include <pthread.h>
        int main() {
        cpu_set_t cpumask;
        CPU_ZERO( &cpumask );
        CPU_SET( 0, &cpumask );
        pthread_setaffinity_np( pthread_self(), sizeof(cpumask), &cpumask);
        return 0;
        }" COMPILES_PTHREAD_SETAFFINITY_NP)

    IF (NOT COMPILES_PTHREAD_SETAFFINITY_NP)
        SET(HAVE_PTHREAD_SETAFFINITY_NP OFF)
    ENDIF()
ENDIF()

IF(HAVE_PTHREAD_SETAFFINITY_NP)
  ADD_DEFINITIONS(-DHAVE_PTHREAD_SETAFFINITY_NP)
ELSE(HAVE_PTHREAD_SETAFFINITY_NP)
  CHECK_CXX_SOURCE_COMPILES("
        #include <sched.h>
        int main() {
        cpu_set_t cpumask;
        sched_setaffinity( 0, sizeof(cpumask), &cpumask );
        return 0;
        }" HAVE_THREE_PARAM_SCHED_SETAFFINITY)
  IF(HAVE_THREE_PARAM_SCHED_SETAFFINITY)
    ADD_DEFINITIONS(-DHAVE_THREE_PARAM_SCHED_SETAFFINITY)
  ELSE(HAVE_THREE_PARAM_SCHED_SETAFFINITY)
    CHECK_CXX_SOURCE_COMPILES("
#include <sched.h>
int main() {
  cpu_set_t cpumask;
  sched_setaffinity( 0, &cpumask );
  return 0;
}" HAVE_TWO_PARAM_SCHED_SETAFFINITY)
    IF(HAVE_TWO_PARAM_SCHED_SETAFFINITY)
      ADD_DEFINITIONS(-DHAVE_TWO_PARAM_SCHED_SETAFFINITY)
    ENDIF(HAVE_TWO_PARAM_SCHED_SETAFFINITY)
  ENDIF(HAVE_THREE_PARAM_SCHED_SETAFFINITY)
ENDIF(HAVE_PTHREAD_SETAFFINITY_NP)

SET(CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES_SAFE}")

TARGET_LINK_LIBRARIES(${LIB_NAME}
    ${CMAKE_THREAD_LIBS_INIT}
)

# Since we're building different platforms binaries in 
# their respective directories, we need to set the 
# link directory so it can find this location.
LINK_DIRECTORIES(
    ${CMAKE_CURRENT_BINARY_DIR}
)

INSTALL(
    TARGETS OpenThreads
    ARCHIVE DESTINATION lib${LIB_POSTFIX} COMPONENT libopenthreads-dev
    LIBRARY DESTINATION lib${LIB_POSTFIX} COMPONENT libopenthreads
    RUNTIME DESTINATION bin COMPONENT libopenthreads
)
INSTALL(
    FILES ${OpenThreads_PUBLIC_HEADERS}
    DESTINATION include/OpenThreads
    COMPONENT libopenthreads-dev
)

#commented out# INCLUDE(ModuleInstall OPTIONAL)
