diff --git a/CMakeLists.txt b/CMakeLists.txt index 277cb1693..f405c2636 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,15 @@ set_property(TARGET boost PROPERTY set_property(TARGET boost PROPERTY INTERFACE_LINK_LIBRARIES ${Boost_LIBRARIES}) +# Include Folly as an imported target +find_package(Folly REQUIRED) +add_library(folly INTERFACE IMPORTED) +set_property(TARGET folly PROPERTY + INTERFACE_INCLUDE_DIRECTORIES ${FOLLY_INCLUDE_DIR}) +set(FOLLY_LINK_FLAGS "-lglog -lcrypto -lssl") +set_property(TARGET folly PROPERTY + INTERFACE_LINK_LIBRARIES ${FOLLY_LINK_FLAGS} ${FOLLY_LIBRARY}) + # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -Wextra -Werror -Wno-deprecated-declarations -Wno-unsupported-friend") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -Wextra -Wno-deprecated-declarations") if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") diff --git a/ClipperLibBaseDockerfile b/ClipperLibBaseDockerfile new file mode 100644 index 000000000..9401c82a2 --- /dev/null +++ b/ClipperLibBaseDockerfile @@ -0,0 +1,40 @@ +FROM frolvlad/alpine-gxx + +RUN echo "@testing http://nl.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories + +RUN apk add --no-cache git bash make boost-dev cmake libev-dev hiredis-dev zeromq-dev \ + libtool automake autoconf-archive@testing lz4-dev xz-dev snappy-dev zlib-dev \ + glog-dev@testing scons openssl-dev libevent-dev + +# Set up Folly + +## Install DoubleConversion +RUN git clone https://github.com/google/double-conversion \ + && cd double-conversion \ + && git checkout tags/v3.0.0 \ + && cmake -DBUILD_SHARED_LIBS=ON . \ + && make \ + && make install \ + && ln -s src double-conversion + +ENV DOUBLE_CONVERSION_HOME=/double-conversion/double-conversion/ + +ENV LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$DOUBLE_CONVERSION_HOME + +## Install GFLags +RUN git clone https://github.com/gflags/gflags \ + && cd gflags \ + && git checkout tags/v2.2.1 \ + && mkdir build \ + && cd build \ + && cmake -DBUILD_SHARED_LIBS=ON .. \ + && make install + +## Install Folly +RUN git clone https://github.com/facebook/folly \ + && cd folly/folly \ + && git checkout tags/v2017.08.14.00 \ + && autoreconf -ivf \ + && ./configure LDFLAGS=-L$DOUBLE_CONVERSION_HOME/ CPPFLAGS=-I$DOUBLE_CONVERSION_HOME \ + && make \ + && make install diff --git a/ManagementFrontendDockerfile b/ManagementFrontendDockerfile index 6bd72ec0b..5c5ea2406 100644 --- a/ManagementFrontendDockerfile +++ b/ManagementFrontendDockerfile @@ -1,4 +1,5 @@ -FROM frolvlad/alpine-gxx +ARG CODE_VERSION=0.2-rc1 +FROM clipper/lib_base:${CODE_VERSION} COPY ./ /clipper diff --git a/QueryFrontendDockerfile b/QueryFrontendDockerfile index 390302112..9a4df79cb 100644 --- a/QueryFrontendDockerfile +++ b/QueryFrontendDockerfile @@ -1,9 +1,11 @@ -FROM frolvlad/alpine-gxx +ARG CODE_VERSION=0.2-rc1 +FROM clipper/lib_base:${CODE_VERSION} + +# Build Clipper COPY ./ /clipper -RUN apk add --no-cache git bash make boost-dev cmake libev-dev hiredis-dev zeromq-dev \ - && cd /clipper/src/libs/spdlog \ +RUN cd /clipper/src/libs/spdlog \ && git apply ../patches/make_spdlog_compile_linux.patch \ && cd /clipper \ && ./configure --cleanup-quiet \ diff --git a/bin/build_docker_images.sh b/bin/build_docker_images.sh index c3cb3c630..89649e7b2 100755 --- a/bin/build_docker_images.sh +++ b/bin/build_docker_images.sh @@ -17,8 +17,9 @@ cd $DIR/.. tag=$( -# Copyright 2007 Wengo -# Copyright 2007 Mike Jackson -# Copyright 2008 Andreas Pakulat -# Copyright 2008-2012 Philip Lowman -# -# Distributed under the OSI-approved BSD License (the "License"); -# see accompanying file Copyright.txt for details. -# -# This software is distributed WITHOUT ANY WARRANTY; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the License for more information. -#============================================================================= -# (To distribute this file outside of CMake, substitute the full -# License text for the above reference.) - +# Save project's policies +cmake_policy(PUSH) +cmake_policy(SET CMP0057 NEW) # if IN_LIST #------------------------------------------------------------------------------- # Before we go searching, check whether boost-cmake is available, unless the @@ -253,6 +244,8 @@ if (NOT Boost_NO_BOOST_CMAKE) message("Found Boost components:") message(" ${Boost_FIND_COMPONENTS}") endif() + # Restore project's policies + cmake_policy(POP) return() endif() endif() @@ -442,24 +435,28 @@ function(_Boost_GUESS_COMPILER_PREFIX _ret) endif() elseif (GHSMULTI) set(_boost_COMPILER "-ghs") - elseif (MSVC14) - set(_boost_COMPILER "-vc140") - elseif (MSVC12) - set(_boost_COMPILER "-vc120") - elseif (MSVC11) - set(_boost_COMPILER "-vc110") - elseif (MSVC10) - set(_boost_COMPILER "-vc100") - elseif (MSVC90) - set(_boost_COMPILER "-vc90") - elseif (MSVC80) - set(_boost_COMPILER "-vc80") - elseif (MSVC71) - set(_boost_COMPILER "-vc71") - elseif (MSVC70) # Good luck! - set(_boost_COMPILER "-vc7") # yes, this is correct - elseif (MSVC60) # Good luck! - set(_boost_COMPILER "-vc6") # yes, this is correct + elseif("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC") + if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.10) + set(_boost_COMPILER "-vc141;-vc140") + elseif (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19) + set(_boost_COMPILER "-vc140") + elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 18) + set(_boost_COMPILER "-vc120") + elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 17) + set(_boost_COMPILER "-vc110") + elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16) + set(_boost_COMPILER "-vc100") + elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 15) + set(_boost_COMPILER "-vc90") + elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 14) + set(_boost_COMPILER "-vc80") + elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13.10) + set(_boost_COMPILER "-vc71") + elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13) # Good luck! + set(_boost_COMPILER "-vc7") # yes, this is correct + else() # VS 6.0 Good luck! + set(_boost_COMPILER "-vc6") # yes, this is correct + endif() elseif (BORLAND) set(_boost_COMPILER "-bcb") elseif(CMAKE_CXX_COMPILER_ID STREQUAL "SunPro") @@ -743,6 +740,23 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret) set(_Boost_CHRONO_DEPENDENCIES system) set(_Boost_CONTEXT_DEPENDENCIES thread chrono system date_time) set(_Boost_COROUTINE_DEPENDENCIES context system) + set(_Boost_FIBER_DEPENDENCIES context thread chrono system date_time) + set(_Boost_FILESYSTEM_DEPENDENCIES system) + set(_Boost_IOSTREAMS_DEPENDENCIES regex) + set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic) + set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) + set(_Boost_MPI_DEPENDENCIES serialization) + set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization) + set(_Boost_RANDOM_DEPENDENCIES system) + set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) + set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) + set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) + elseif(NOT Boost_VERSION VERSION_LESS 106300 AND Boost_VERSION VERSION_LESS 106500) + set(_Boost_CHRONO_DEPENDENCIES system) + set(_Boost_CONTEXT_DEPENDENCIES thread chrono system date_time) + set(_Boost_COROUTINE_DEPENDENCIES context system) + set(_Boost_COROUTINE2_DEPENDENCIES context fiber thread chrono system date_time) + set(_Boost_FIBER_DEPENDENCIES context thread chrono system date_time) set(_Boost_FILESYSTEM_DEPENDENCIES system) set(_Boost_IOSTREAMS_DEPENDENCIES regex) set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic) @@ -788,6 +802,7 @@ function(_Boost_COMPONENT_HEADERS component _hdrs) set(_Boost_COROUTINE_HEADERS "boost/coroutine/all.hpp") set(_Boost_EXCEPTION_HEADERS "boost/exception/exception.hpp") set(_Boost_DATE_TIME_HEADERS "boost/date_time/date.hpp") + set(_Boost_FIBER_HEADERS "boost/fiber/all.hpp") set(_Boost_FILESYSTEM_HEADERS "boost/filesystem/path.hpp") set(_Boost_GRAPH_HEADERS "boost/graph/adjacency_list.hpp") set(_Boost_GRAPH_PARALLEL_HEADERS "boost/graph/adjacency_list.hpp") @@ -819,6 +834,10 @@ function(_Boost_COMPONENT_HEADERS component _hdrs) set(_Boost_UNIT_TEST_FRAMEWORK_HEADERS "boost/test/framework.hpp") set(_Boost_WAVE_HEADERS "boost/wave.hpp") set(_Boost_WSERIALIZATION_HEADERS "boost/archive/text_wiarchive.hpp") + if(WIN32) + set(_Boost_BZIP2_HEADERS "boost/iostreams/filter/bzip2.hpp") + set(_Boost_ZLIB_HEADERS "boost/iostreams/filter/zlib.hpp") + endif() string(TOUPPER ${component} uppercomponent) set(${_hdrs} ${_Boost_${uppercomponent}_HEADERS} PARENT_SCOPE) @@ -852,14 +871,12 @@ function(_Boost_MISSING_DEPENDENCIES componentvar extravar) list(APPEND _boost_processed_components ${_boost_unprocessed_components}) foreach(component ${_boost_unprocessed_components}) string(TOUPPER ${component} uppercomponent) - set(${_ret} ${_Boost_${uppercomponent}_DEPENDENCIES} PARENT_SCOPE) + set(${_ret} ${_Boost_${uppercomponent}_DEPENDENCIES} PARENT_SCOPE) _Boost_COMPONENT_DEPENDENCIES("${component}" _Boost_${uppercomponent}_DEPENDENCIES) set(_Boost_${uppercomponent}_DEPENDENCIES ${_Boost_${uppercomponent}_DEPENDENCIES} PARENT_SCOPE) set(_Boost_IMPORTED_TARGETS ${_Boost_IMPORTED_TARGETS} PARENT_SCOPE) foreach(componentdep ${_Boost_${uppercomponent}_DEPENDENCIES}) - list(FIND _boost_processed_components "${componentdep}" _boost_component_found) - list(FIND _boost_new_components "${componentdep}" _boost_component_new) - if (_boost_component_found EQUAL -1 AND _boost_component_new EQUAL -1) + if (NOT ("${componentdep}" IN_LIST _boost_processed_components OR "${componentdep}" IN_LIST _boost_new_components)) list(APPEND _boost_new_components ${componentdep}) endif() endforeach() @@ -875,6 +892,68 @@ function(_Boost_MISSING_DEPENDENCIES componentvar extravar) set(${extravar} ${_boost_extra_components} PARENT_SCOPE) endfunction() +# +# Some boost libraries may require particular set of compler features. +# The very first one was `boost::fiber` introduced in Boost 1.62. +# One can check required compiler features of it in +# `${Boost_ROOT}/libs/fiber/build/Jamfile.v2`. +# +function(_Boost_COMPILER_FEATURES component _ret) + # Boost >= 1.62 and < 1.65 + if(NOT Boost_VERSION VERSION_LESS 106200 AND Boost_VERSION VERSION_LESS 106500) + set(_Boost_FIBER_COMPILER_FEATURES + cxx_alias_templates + cxx_auto_type + cxx_constexpr + cxx_defaulted_functions + cxx_final + cxx_lambdas + cxx_noexcept + cxx_nullptr + cxx_rvalue_references + cxx_thread_local + cxx_variadic_templates + ) + endif() + string(TOUPPER ${component} uppercomponent) + set(${_ret} ${_Boost_${uppercomponent}_COMPILER_FEATURES} PARENT_SCOPE) +endfunction() + +# +# Update library search directory hint variable with paths used by prebuilt boost binaries. +# +# Prebuilt windows binaries (https://sourceforge.net/projects/boost/files/boost-binaries/) +# have library directories named using MSVC compiler version and architecture. +# This function would append corresponding directories if MSVC is a current compiler, +# so having `BOOST_ROOT` would be enough to specify to find everything. +# +function(_Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS componentlibvar basedir) + if("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC") + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(_arch_suffix 64) + else() + set(_arch_suffix 32) + endif() + if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.10) + list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-14.1) + list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-14.0) + elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19) + list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-14.0) + elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 18) + list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-12.0) + elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 17) + list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-11.0) + elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16) + list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-10.0) + elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 15) + list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-9.0) + elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 14) + list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-8.0) + endif() + set(${componentlibvar} ${${componentlibvar}} PARENT_SCOPE) + endif() +endfunction() + # # End functions/macros # @@ -921,7 +1000,7 @@ else() # _Boost_COMPONENT_HEADERS. See the instructions at the top of # _Boost_COMPONENT_DEPENDENCIES. set(_Boost_KNOWN_VERSIONS ${Boost_ADDITIONAL_VERSIONS} - "1.61.0" "1.61" "1.60.0" "1.60" + "1.64.0" "1.64" "1.63.0" "1.63" "1.62.0" "1.62" "1.61.0" "1.61" "1.60.0" "1.60" "1.59.0" "1.59" "1.58.0" "1.58" "1.57.0" "1.57" "1.56.0" "1.56" "1.55.0" "1.55" "1.54.0" "1.54" "1.53.0" "1.53" "1.52.0" "1.52" "1.51.0" "1.51" "1.50.0" "1.50" "1.49.0" "1.49" "1.48.0" "1.48" "1.47.0" "1.47" "1.46.1" @@ -1076,6 +1155,12 @@ if(NOT Boost_INCLUDE_DIR) if( Boost_NO_SYSTEM_PATHS) list(APPEND _boost_INCLUDE_SEARCH_DIRS NO_CMAKE_SYSTEM_PATH NO_SYSTEM_ENVIRONMENT_PATH) else() + if("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC") + foreach(ver ${_Boost_KNOWN_VERSIONS}) + string(REPLACE "." "_" ver "${ver}") + list(APPEND _boost_INCLUDE_SEARCH_DIRS PATHS "C:/local/boost_${ver}") + endforeach() + endif() list(APPEND _boost_INCLUDE_SEARCH_DIRS PATHS C:/boost/include C:/boost @@ -1157,8 +1242,8 @@ if(Boost_INCLUDE_DIR) math(EXPR Boost_MINOR_VERSION "${Boost_VERSION} / 100 % 1000") math(EXPR Boost_SUBMINOR_VERSION "${Boost_VERSION} % 100") - set(Boost_ERROR_REASON - "${Boost_ERROR_REASON}Boost version: ${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}\nBoost include path: ${Boost_INCLUDE_DIR}") + string(APPEND Boost_ERROR_REASON + "Boost version: ${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}\nBoost include path: ${Boost_INCLUDE_DIR}") if(Boost_DEBUG) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " "version.hpp reveals boost " @@ -1180,16 +1265,16 @@ if(Boost_INCLUDE_DIR) endif() if(NOT Boost_FOUND) # State that we found a version of Boost that is too new or too old. - set(Boost_ERROR_REASON - "${Boost_ERROR_REASON}\nDetected version of Boost is too ${_Boost_VERSION_AGE}. Requested version was ${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}") + string(APPEND Boost_ERROR_REASON + "\nDetected version of Boost is too ${_Boost_VERSION_AGE}. Requested version was ${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}") if (Boost_FIND_VERSION_PATCH) - set(Boost_ERROR_REASON - "${Boost_ERROR_REASON}.${Boost_FIND_VERSION_PATCH}") + string(APPEND Boost_ERROR_REASON + ".${Boost_FIND_VERSION_PATCH}") endif () if (NOT Boost_FIND_VERSION_EXACT) - set(Boost_ERROR_REASON "${Boost_ERROR_REASON} (or newer)") + string(APPEND Boost_ERROR_REASON " (or newer)") endif () - set(Boost_ERROR_REASON "${Boost_ERROR_REASON}.") + string(APPEND Boost_ERROR_REASON ".") endif () else() # Caller will accept any Boost version. @@ -1197,8 +1282,8 @@ if(Boost_INCLUDE_DIR) endif() else() set(Boost_FOUND 0) - set(Boost_ERROR_REASON - "${Boost_ERROR_REASON}Unable to find the Boost header files. Please set BOOST_ROOT to the root directory containing Boost or BOOST_INCLUDEDIR to the directory containing Boost's headers.") + string(APPEND Boost_ERROR_REASON + "Unable to find the Boost header files. Please set BOOST_ROOT to the root directory containing Boost or BOOST_INCLUDEDIR to the directory containing Boost's headers.") endif() # ------------------------------------------------------------------------ @@ -1275,27 +1360,28 @@ endif() # g using debug versions of the standard and runtime # support libraries if(WIN32 AND Boost_USE_DEBUG_RUNTIME) - if(MSVC OR "${CMAKE_CXX_COMPILER}" MATCHES "icl" + if("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC" + OR "${CMAKE_CXX_COMPILER}" MATCHES "icl" OR "${CMAKE_CXX_COMPILER}" MATCHES "icpc") - set(_boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}g") + string(APPEND _boost_DEBUG_ABI_TAG "g") endif() endif() # y using special debug build of python if(Boost_USE_DEBUG_PYTHON) - set(_boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}y") + string(APPEND _boost_DEBUG_ABI_TAG "y") endif() # d using a debug version of your code -set(_boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}d") +string(APPEND _boost_DEBUG_ABI_TAG "d") # p using the STLport standard library rather than the # default one supplied with your compiler if(Boost_USE_STLPORT) - set( _boost_RELEASE_ABI_TAG "${_boost_RELEASE_ABI_TAG}p") - set( _boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}p") + string(APPEND _boost_RELEASE_ABI_TAG "p") + string(APPEND _boost_DEBUG_ABI_TAG "p") endif() # n using the STLport deprecated "native iostreams" feature if(Boost_USE_STLPORT_DEPRECATED_NATIVE_IOSTREAMS) - set( _boost_RELEASE_ABI_TAG "${_boost_RELEASE_ABI_TAG}n") - set( _boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}n") + string(APPEND _boost_RELEASE_ABI_TAG "n") + string(APPEND _boost_DEBUG_ABI_TAG "n") endif() if(Boost_DEBUG) @@ -1333,8 +1419,10 @@ foreach(c DEBUG RELEASE) if(BOOST_ROOT) list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} ${BOOST_ROOT}/lib ${BOOST_ROOT}/stage/lib) + _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "${BOOST_ROOT}") elseif(_ENV_BOOST_ROOT) list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} ${_ENV_BOOST_ROOT}/lib ${_ENV_BOOST_ROOT}/stage/lib) + _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "${_ENV_BOOST_ROOT}") endif() list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} @@ -1342,9 +1430,15 @@ foreach(c DEBUG RELEASE) ${Boost_INCLUDE_DIR}/../lib ${Boost_INCLUDE_DIR}/stage/lib ) + _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "${Boost_INCLUDE_DIR}/..") if( Boost_NO_SYSTEM_PATHS ) list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} NO_CMAKE_SYSTEM_PATH NO_SYSTEM_ENVIRONMENT_PATH) else() + foreach(ver ${_Boost_KNOWN_VERSIONS}) + string(REPLACE "." "_" ver "${ver}") + _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "C:/local/boost_${ver}") + endforeach() + _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "C:/boost") list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} PATHS C:/boost/lib C:/boost @@ -1364,9 +1458,9 @@ endif() if( Boost_USE_STATIC_LIBS ) set( _boost_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) if(WIN32) - set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) + list(INSERT CMAKE_FIND_LIBRARY_SUFFIXES 0 .lib .a) else() - set(CMAKE_FIND_LIBRARY_SUFFIXES .a ) + set(CMAKE_FIND_LIBRARY_SUFFIXES .a) endif() endif() @@ -1392,7 +1486,7 @@ endif() set(_boost_STATIC_RUNTIME_WORKAROUND false) if(WIN32 AND Boost_USE_STATIC_LIBS) if(NOT DEFINED Boost_USE_STATIC_RUNTIME) - set(_boost_STATIC_RUNTIME_WORKAROUND true) + set(_boost_STATIC_RUNTIME_WORKAROUND TRUE) endif() endif() @@ -1409,14 +1503,13 @@ endif() _Boost_MISSING_DEPENDENCIES(Boost_FIND_COMPONENTS _Boost_EXTRA_FIND_COMPONENTS) # If thread is required, get the thread libs as a dependency -list(FIND Boost_FIND_COMPONENTS thread _Boost_THREAD_DEPENDENCY_LIBS) -if(NOT _Boost_THREAD_DEPENDENCY_LIBS EQUAL -1) +if("thread" IN_LIST Boost_FIND_COMPONENTS) include(CMakeFindDependencyMacro) find_dependency(Threads) endif() # If the user changed any of our control inputs flush previous results. -if(_Boost_CHANGE_LIBDIR OR _Boost_CHANGE_LIBNAME) +if(_Boost_CHANGE_LIBDIR_DEBUG OR _Boost_CHANGE_LIBDIR_RELEASE OR _Boost_CHANGE_LIBNAME) foreach(COMPONENT ${_Boost_COMPONENTS_SEARCHED}) string(TOUPPER ${COMPONENT} UPPERCOMPONENT) foreach(c DEBUG RELEASE) @@ -1476,17 +1569,24 @@ foreach(COMPONENT ${Boost_FIND_COMPONENTS}) # # Find RELEASE libraries # - set(_boost_RELEASE_NAMES - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG} + unset(_boost_RELEASE_NAMES) + foreach(compiler IN LISTS _boost_COMPILER) + list(APPEND _boost_RELEASE_NAMES + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${compiler}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}-${Boost_LIB_VERSION} + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${compiler}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG} ) + endforeach() + list(APPEND _boost_RELEASE_NAMES ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}-${Boost_LIB_VERSION} ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG} ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT} ) if(_boost_STATIC_RUNTIME_WORKAROUND) set(_boost_RELEASE_STATIC_ABI_TAG "-s${_boost_RELEASE_ABI_TAG}") + foreach(compiler IN LISTS _boost_COMPILER) + list(APPEND _boost_RELEASE_NAMES + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${compiler}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}-${Boost_LIB_VERSION} + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${compiler}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG} ) + endforeach() list(APPEND _boost_RELEASE_NAMES - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG} ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}-${Boost_LIB_VERSION} ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG} ) endif() @@ -1517,18 +1617,25 @@ foreach(COMPONENT ${Boost_FIND_COMPONENTS}) # # Find DEBUG libraries # - set(_boost_DEBUG_NAMES - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG} + unset(_boost_DEBUG_NAMES) + foreach(compiler IN LISTS _boost_COMPILER) + list(APPEND _boost_DEBUG_NAMES + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${compiler}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}-${Boost_LIB_VERSION} + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${compiler}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG} ) + endforeach() + list(APPEND _boost_DEBUG_NAMES ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}-${Boost_LIB_VERSION} ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG} ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED} ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT} ) if(_boost_STATIC_RUNTIME_WORKAROUND) set(_boost_DEBUG_STATIC_ABI_TAG "-s${_boost_DEBUG_ABI_TAG}") + foreach(compiler IN LISTS _boost_COMPILER) + list(APPEND _boost_DEBUG_NAMES + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${compiler}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}-${Boost_LIB_VERSION} + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${compiler}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG} ) + endforeach() list(APPEND _boost_DEBUG_NAMES - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG} ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}-${Boost_LIB_VERSION} ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG} ) endif() @@ -1563,6 +1670,9 @@ foreach(COMPONENT ${Boost_FIND_COMPONENTS}) _Boost_ADJUST_LIB_VARS(${UPPERCOMPONENT}) + # Check if component requires some compiler features + _Boost_COMPILER_FEATURES(${COMPONENT} _Boost_${UPPERCOMPONENT}_COMPILER_FEATURES) + endforeach() # Restore the original find library ordering @@ -1613,26 +1723,26 @@ if(Boost_FOUND) set(Boost_FOUND 0) # We were unable to find some libraries, so generate a sensible # error message that lists the libraries we were unable to find. - set(Boost_ERROR_REASON - "${Boost_ERROR_REASON}\nCould not find the following") + string(APPEND Boost_ERROR_REASON + "\nCould not find the following") if(Boost_USE_STATIC_LIBS) - set(Boost_ERROR_REASON "${Boost_ERROR_REASON} static") + string(APPEND Boost_ERROR_REASON " static") endif() - set(Boost_ERROR_REASON - "${Boost_ERROR_REASON} Boost libraries:\n") + string(APPEND Boost_ERROR_REASON + " Boost libraries:\n") foreach(COMPONENT ${_Boost_MISSING_COMPONENTS}) - set(Boost_ERROR_REASON - "${Boost_ERROR_REASON} ${Boost_NAMESPACE}_${COMPONENT}\n") + string(APPEND Boost_ERROR_REASON + " ${Boost_NAMESPACE}_${COMPONENT}\n") endforeach() list(LENGTH Boost_FIND_COMPONENTS Boost_NUM_COMPONENTS_WANTED) list(LENGTH _Boost_MISSING_COMPONENTS Boost_NUM_MISSING_COMPONENTS) if (${Boost_NUM_COMPONENTS_WANTED} EQUAL ${Boost_NUM_MISSING_COMPONENTS}) - set(Boost_ERROR_REASON - "${Boost_ERROR_REASON}No Boost libraries were found. You may need to set BOOST_LIBRARYDIR to the directory containing Boost libraries or BOOST_ROOT to the location of Boost.") + string(APPEND Boost_ERROR_REASON + "No Boost libraries were found. You may need to set BOOST_LIBRARYDIR to the directory containing Boost libraries or BOOST_ROOT to the location of Boost.") else () - set(Boost_ERROR_REASON - "${Boost_ERROR_REASON}Some (but not all) of the required Boost libraries were found. You may need to install these additional Boost libraries. Alternatively, set BOOST_LIBRARYDIR to the directory containing Boost libraries or BOOST_ROOT to the location of Boost.") + string(APPEND Boost_ERROR_REASON + "Some (but not all) of the required Boost libraries were found. You may need to install these additional Boost libraries. Alternatively, set BOOST_LIBRARYDIR to the directory containing Boost libraries or BOOST_ROOT to the location of Boost.") endif () endif () @@ -1655,13 +1765,11 @@ if(Boost_FOUND) endif() if(EXISTS "${_boost_LIB_DIR}/lib") - set(_boost_LIB_DIR ${_boost_LIB_DIR}/lib) + string(APPEND _boost_LIB_DIR /lib) + elseif(EXISTS "${_boost_LIB_DIR}/stage/lib") + string(APPEND _boost_LIB_DIR "/stage/lib") else() - if(EXISTS "${_boost_LIB_DIR}/stage/lib") - set(_boost_LIB_DIR ${_boost_LIB_DIR}/stage/lib) - else() - set(_boost_LIB_DIR "") - endif() + set(_boost_LIB_DIR "") endif() if(_boost_LIB_DIR AND EXISTS "${_boost_LIB_DIR}") @@ -1711,13 +1819,6 @@ if(Boost_FOUND) IMPORTED_LINK_INTERFACE_LANGUAGES "CXX" IMPORTED_LOCATION "${Boost_${UPPERCOMPONENT}_LIBRARY}") endif() - if(EXISTS "${Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG}") - set_property(TARGET Boost::${COMPONENT} APPEND PROPERTY - IMPORTED_CONFIGURATIONS DEBUG) - set_target_properties(Boost::${COMPONENT} PROPERTIES - IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "CXX" - IMPORTED_LOCATION_DEBUG "${Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG}") - endif() if(EXISTS "${Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE}") set_property(TARGET Boost::${COMPONENT} APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) @@ -1725,6 +1826,13 @@ if(Boost_FOUND) IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "CXX" IMPORTED_LOCATION_RELEASE "${Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE}") endif() + if(EXISTS "${Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG}") + set_property(TARGET Boost::${COMPONENT} APPEND PROPERTY + IMPORTED_CONFIGURATIONS DEBUG) + set_target_properties(Boost::${COMPONENT} PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "CXX" + IMPORTED_LOCATION_DEBUG "${Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG}") + endif() if(_Boost_${UPPERCOMPONENT}_DEPENDENCIES) unset(_Boost_${UPPERCOMPONENT}_TARGET_DEPENDENCIES) foreach(dep ${_Boost_${UPPERCOMPONENT}_DEPENDENCIES}) @@ -1736,6 +1844,10 @@ if(Boost_FOUND) set_target_properties(Boost::${COMPONENT} PROPERTIES INTERFACE_LINK_LIBRARIES "${_Boost_${UPPERCOMPONENT}_TARGET_DEPENDENCIES}") endif() + if(_Boost_${UPPERCOMPONENT}_COMPILER_FEATURES) + set_target_properties(Boost::${COMPONENT} PROPERTIES + INTERFACE_COMPILE_FEATURES "${_Boost_${UPPERCOMPONENT}_COMPILER_FEATURES}") + endif() endif() endif() endforeach() @@ -1816,3 +1928,6 @@ list(REMOVE_DUPLICATES _Boost_COMPONENTS_SEARCHED) list(SORT _Boost_COMPONENTS_SEARCHED) set(_Boost_COMPONENTS_SEARCHED "${_Boost_COMPONENTS_SEARCHED}" CACHE INTERNAL "Components requested for this build tree.") + +# Restore project's policies +cmake_policy(POP) diff --git a/cmake/FindFolly.cmake b/cmake/FindFolly.cmake new file mode 100644 index 000000000..dbe07ab9f --- /dev/null +++ b/cmake/FindFolly.cmake @@ -0,0 +1,24 @@ +# Copyright (c) 2014, Facebook, Inc. +# All rights reserved. +# +# This source code is licensed under the BSD-style license found in the +# LICENSE file in the root directory of this source tree. An additional grant +# of patent rights can be found in the PATENTS file in the same directory. +# +# - Try to find folly +# This will define +# FOLLY_FOUND +# FOLLY_INCLUDE_DIR +# FOLLY_LIBRARIES + +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.7 FATAL_ERROR) + +INCLUDE(FindPackageHandleStandardArgs) + +FIND_LIBRARY(FOLLY_LIBRARY folly PATHS $ENV{FOLLY_ROOT}/lib $ENV{PATH}) +FIND_PATH(FOLLY_INCLUDE_DIR "folly/String.h" HINTS $ENV{FOLLY_ROOT}/include) + +SET(FOLLY_LIBRARIES ${FOLLY_LIBRARY}) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Folly + REQUIRED_ARGS FOLLY_INCLUDE_DIR FOLLY_LIBRARIES) diff --git a/src/benchmarks/src/end_to_end_bench.cpp b/src/benchmarks/src/end_to_end_bench.cpp index 5562e0050..bba825824 100644 --- a/src/benchmarks/src/end_to_end_bench.cpp +++ b/src/benchmarks/src/end_to_end_bench.cpp @@ -4,12 +4,11 @@ #include #include -#include +#include #include #include #include -#include #include #include #include @@ -85,12 +84,10 @@ void send_predictions(std::unordered_map &config, clipper::DefaultOutputSelectionPolicy::get_name(), {VersionedModelId(model_name, model_version)}}; - boost::future prediction = qp.predict(q); + folly::Future prediction = qp.predict(q); bench_metrics.request_throughput_->mark(1); - prediction.then([bench_metrics](boost::future f) { - Response r = f.get(); - + prediction.then([bench_metrics](Response r) { // Update metrics if (r.output_is_default_) { bench_metrics.default_pred_ratio_->increment(1, 1); diff --git a/src/frontends/src/query_frontend.hpp b/src/frontends/src/query_frontend.hpp index 1ceac660c..0ab35327e 100644 --- a/src/frontends/src/query_frontend.hpp +++ b/src/frontends/src/query_frontend.hpp @@ -7,6 +7,8 @@ #include +#include + #include #include #include @@ -316,37 +318,32 @@ class RequestHandler { } } - auto prediction = decode_and_handle_predict( + folly::Future prediction = decode_and_handle_predict( request->content.string(), name, versioned_models, policy, latency_slo_micros, input_type); - prediction.then([response, app_metrics](boost::future f) { - if (f.has_exception()) { - try { - boost::rethrow_exception(f.get_exception_ptr()); - } catch (std::exception& e) { + + prediction + .then([response, app_metrics](Response r) { + // Update metrics + if (r.output_is_default_) { + app_metrics.default_pred_ratio_->increment(1, 1); + } else { + app_metrics.default_pred_ratio_->increment(0, 1); + } + app_metrics.latency_->insert(r.duration_micros_); + app_metrics.num_predictions_->increment(1); + app_metrics.throughput_->mark(1); + + std::string content = get_prediction_response_content(r); + respond_http(content, "200 OK", response); + + }) + .onError([response](const std::exception& e) { clipper::log_error_formatted(clipper::LOGGING_TAG_CLIPPER, "Unexpected error: {}", e.what()); - } - respond_http("An unexpected error occurred!", - "500 Internal Server Error", response); - return; - } - - Response r = f.get(); - - // Update metrics - if (r.output_is_default_) { - app_metrics.default_pred_ratio_->increment(1, 1); - } else { - app_metrics.default_pred_ratio_->increment(0, 1); - } - app_metrics.latency_->insert(r.duration_micros_); - app_metrics.num_predictions_->increment(1); - app_metrics.throughput_->mark(1); - - std::string content = get_prediction_response_content(r); - respond_http(content, "200 OK", response); - }); + respond_http("An unexpected error occurred!", + "500 Internal Server Error", response); + }); } catch (const json_parse_error& e) { std::string error_msg = json_error_msg(e.what(), PREDICTION_JSON_SCHEMA); @@ -391,11 +388,10 @@ class RequestHandler { } } } - auto update = + folly::Future update = decode_and_handle_update(request->content.string(), name, versioned_models, policy, input_type); - update.then([response](boost::future f) { - FeedbackAck ack = f.get(); + update.then([response](FeedbackAck ack) { std::stringstream ss; ss << "Feedback received? " << ack; std::string content = ss.str(); @@ -485,7 +481,7 @@ class RequestHandler { * "input" := [double] | [int] | [string] | [byte] | [float] * } */ - boost::future decode_and_handle_predict( + folly::Future decode_and_handle_predict( std::string json_content, std::string name, std::vector models, std::string policy, long latency_slo_micros, InputType input_type) { @@ -509,7 +505,7 @@ class RequestHandler { * "label" := double * } */ - boost::future decode_and_handle_update( + folly::Future decode_and_handle_update( std::string json_content, std::string name, std::vector models, std::string policy, InputType input_type) { diff --git a/src/frontends/src/query_frontend_tests.cpp b/src/frontends/src/query_frontend_tests.cpp index 4e97dd7c8..a965980ca 100644 --- a/src/frontends/src/query_frontend_tests.cpp +++ b/src/frontends/src/query_frontend_tests.cpp @@ -3,6 +3,8 @@ #include +#include + #include #include #include @@ -18,13 +20,13 @@ namespace { class MockQueryProcessor { public: MockQueryProcessor() = default; - boost::future predict(Query query) { + folly::Future predict(Query query) { Response response(query, 3, 5, Output("-1.0", {VersionedModelId("m", "1")}), false, boost::optional{}); - return boost::make_ready_future(response); + return folly::makeFuture(response); } - boost::future update(FeedbackQuery /*feedback*/) { - return boost::make_ready_future(true); + folly::Future update(FeedbackQuery /*feedback*/) { + return folly::makeFuture(true); } std::shared_ptr get_state_table() const { diff --git a/src/libclipper/CMakeLists.txt b/src/libclipper/CMakeLists.txt index 9b30bdcf0..fdc6766d7 100644 --- a/src/libclipper/CMakeLists.txt +++ b/src/libclipper/CMakeLists.txt @@ -28,7 +28,7 @@ target_include_directories(clipper PUBLIC PRIVATE src) -target_link_libraries(clipper boost zmqcpp redox pthread rapidjson spdlog base64) +target_link_libraries(clipper boost folly zmqcpp redox pthread rapidjson spdlog base64) # This makes the project importable from the build directory export(TARGETS clipper FILE ClipperConfig.cmake) @@ -49,7 +49,6 @@ add_executable(libclippertests EXCLUDE_FROM_ALL test/selection_policies_test.cpp test/json_util_test.cpp test/logging_test.cpp - test/future_test.cpp test/task_executor_test.cpp test/config_test.cpp test/base64_test.cpp) diff --git a/src/libclipper/include/clipper/containers.hpp b/src/libclipper/include/clipper/containers.hpp index 7946ea7a9..a2053723f 100644 --- a/src/libclipper/include/clipper/containers.hpp +++ b/src/libclipper/include/clipper/containers.hpp @@ -6,7 +6,6 @@ #include #include -#include #include #include diff --git a/src/libclipper/include/clipper/datatypes.hpp b/src/libclipper/include/clipper/datatypes.hpp index 6fd69af7b..11a18f96e 100644 --- a/src/libclipper/include/clipper/datatypes.hpp +++ b/src/libclipper/include/clipper/datatypes.hpp @@ -8,7 +8,6 @@ #include #include -#include namespace clipper { diff --git a/src/libclipper/include/clipper/future.hpp b/src/libclipper/include/clipper/future.hpp deleted file mode 100644 index 68542c670..000000000 --- a/src/libclipper/include/clipper/future.hpp +++ /dev/null @@ -1,148 +0,0 @@ -#ifndef CLIPPER_LIB_FUTURE_HPP -#define CLIPPER_LIB_FUTURE_HPP - -#include -#include -#include -#include -#include - -#include "boost/thread.hpp" - -namespace clipper { - -namespace future { - -/* - * The first element in the pair is a future that will complete when - * all the futures provided have completed. The second element is a vector - * of futures that have the same values and will complete at the same time - * as the futures passed in as argument. - * - * \param futures A list of futures to compose - * \param num_completed A counter indicating the number of futures that - * have completed so far. The reason this is an argument to the function - * instead of internal state is that the caller of `when_all` must make sure - * that the counter stays in scope for the lifetime of all the futures. -*/ -template -std::pair, std::vector>> when_all( - std::vector> futures, - std::shared_ptr> num_completed) { - if (futures.size() == 0) { - return std::make_pair(boost::make_ready_future(), - std::vector>{}); - } - int num_futures = futures.size(); - auto completion_promise = std::make_shared>(); - std::vector> wrapped_futures; - for (auto f = futures.begin(); f != futures.end(); ++f) { - wrapped_futures.push_back(f->then( - [num_futures, completion_promise, num_completed](auto result) mutable { - if (num_completed->fetch_add(1) + 1 == num_futures) { - completion_promise->set_value(); - assert(*num_completed == num_futures); - } - return result.get(); - })); - } - - return std::make_pair, std::vector>>( - completion_promise->get_future(), std::move(wrapped_futures)); -} - -template -boost::future wrap_when_both( - boost::future future, std::shared_ptr> num_completed, - std::shared_ptr> completion_promise) { - return future.then([completion_promise, num_completed](auto result) mutable { - - int num_already_completed = num_completed->fetch_add(1); - // means the other future has already finished - if (num_already_completed == 1) { - completion_promise->set_value(); - } - return result.get(); - }); -} - -/** - * A function for waiting until both of a pair of futures has completed. - * - * - * \param num_completed A counter indicating the number of futures that - * have completed so far. The reason this is an argument to the function - * instead of internal state is that the caller of `when_both` must make sure - * that the counter stays in scope for the lifetime of all the futures. - * - * \return A tuple of three futures. The first is the composed future that will - * complete when both of the two futures provided as argument completes. The - * second two elements in the tuple are futures that will complete at the same - * time and with the same value as the futures passed in as arguments. - */ -template -std::tuple, boost::future, boost::future> when_both( - boost::future f0, boost::future f1, - std::shared_ptr> num_completed) { - auto completion_promise = std::make_shared>(); - auto wrapped_f0 = - wrap_when_both(std::move(f0), num_completed, completion_promise); - auto wrapped_f1 = - wrap_when_both(std::move(f1), num_completed, completion_promise); - - return std::make_tuple, boost::future, - boost::future>(completion_promise->get_future(), - std::move(wrapped_f0), - std::move(wrapped_f1)); -} - -template -boost::future wrap_when_either( - boost::future future, std::shared_ptr completed_flag, - std::shared_ptr> completion_promise) { - return future.then([completion_promise, completed_flag](auto result) mutable { - - // Only set completed to true if the original value was false. This ensures - // that we only set the value once, and therefore only complete the promise - // once. - bool flag_already_set = completed_flag->test_and_set(); - if (!flag_already_set) { - completion_promise->set_value(); - } - return result.get(); - }); -} - -/** - * A function for waiting until either of a pair of futures has completed. - * - * \param completed_flag A flag indicating whether any futures have completed - * so far. The reason this is an argument to the function - * instead of internal state is that the caller of `when_either` must make sure - * that the counter stays in scope for the lifetime of all the futures. - * - * \return A tuple of three futures. The first is the composed future that will - * complete when either of the two futures provided as argument completes. The - * second two elements in the tuple are futures that will complete at the same - * time and with the same value as the futures passed in as arguments. - */ -template -std::tuple, boost::future, boost::future> -when_either(boost::future f0, boost::future f1, - std::shared_ptr completed_flag) { - auto completion_promise = std::make_shared>(); - auto wrapped_f0 = - wrap_when_either(std::move(f0), completed_flag, completion_promise); - auto wrapped_f1 = - wrap_when_either(std::move(f1), completed_flag, completion_promise); - - return std::make_tuple, boost::future, - boost::future>(completion_promise->get_future(), - std::move(wrapped_f0), - std::move(wrapped_f1)); -} - -} // namespace future -} // namespace clipper - -#endif // define CLIPPER_LIB_FUTURE_HPP diff --git a/src/libclipper/include/clipper/query_processor.hpp b/src/libclipper/include/clipper/query_processor.hpp index 41586398e..03b8e0503 100644 --- a/src/libclipper/include/clipper/query_processor.hpp +++ b/src/libclipper/include/clipper/query_processor.hpp @@ -6,7 +6,7 @@ #include #include -#include +#include #include "datatypes.hpp" #include "metrics.hpp" @@ -34,8 +34,8 @@ class QueryProcessor { QueryProcessor(QueryProcessor&& other) = default; QueryProcessor& operator=(QueryProcessor&& other) = default; - boost::future predict(Query query); - boost::future update(FeedbackQuery feedback); + folly::Future predict(Query query); + folly::Future update(FeedbackQuery feedback); std::shared_ptr get_state_table() const; diff --git a/src/libclipper/include/clipper/task_executor.hpp b/src/libclipper/include/clipper/task_executor.hpp index 0131e22c6..698ab55b3 100644 --- a/src/libclipper/include/clipper/task_executor.hpp +++ b/src/libclipper/include/clipper/task_executor.hpp @@ -8,9 +8,11 @@ #include #include -#include + #include +#include + #include #include #include @@ -69,13 +71,13 @@ class CacheEntry { bool completed_ = false; Output value_; - std::vector> value_promises_; + std::vector> value_promises_; }; class PredictionCache { public: PredictionCache(); - boost::future fetch(const VersionedModelId &model, + folly::Future fetch(const VersionedModelId &model, const std::shared_ptr &input); void put(const VersionedModelId &model, const std::shared_ptr &input, @@ -294,17 +296,17 @@ class TaskExecutor { TaskExecutor(TaskExecutor &&other) = default; TaskExecutor &operator=(TaskExecutor &&other) = default; - std::vector> schedule_predictions( + std::vector> schedule_predictions( std::vector tasks) { predictions_counter_->increment(tasks.size()); - std::vector> output_futures; + std::vector> output_futures; for (auto t : tasks) { // add each task to the queue corresponding to its associated model boost::shared_lock lock(model_queues_mutex_); auto model_queue_entry = model_queues_.find(t.model_); if (model_queue_entry != model_queues_.end()) { output_futures.push_back(cache_.fetch(t.model_, t.input_)); - if (!output_futures.back().is_ready()) { + if (!output_futures.back().isReady()) { t.recv_time_ = std::chrono::system_clock::now(); model_queue_entry->second->add_task(t); log_info_formatted(LOGGING_TAG_TASK_EXECUTOR, @@ -335,7 +337,7 @@ class TaskExecutor { return output_futures; } - std::vector> schedule_feedback( + std::vector> schedule_feedback( const std::vector tasks) { UNUSED(tasks); // TODO Implement diff --git a/src/libclipper/include/clipper/timers.hpp b/src/libclipper/include/clipper/timers.hpp index ac6e788e1..86b515fe5 100644 --- a/src/libclipper/include/clipper/timers.hpp +++ b/src/libclipper/include/clipper/timers.hpp @@ -9,7 +9,8 @@ #include #include -#include +#include +#include #include @@ -64,7 +65,7 @@ class Timer { public: Timer() = delete; Timer(std::chrono::time_point deadline, - boost::promise completion_promise); + folly::Promise completion_promise); ~Timer() = default; // Disallow copy @@ -85,7 +86,7 @@ class Timer { std::chrono::time_point deadline_; private: - boost::promise completion_promise_; + folly::Promise completion_promise_; }; struct TimerCompare { @@ -154,12 +155,11 @@ class TimerSystem { manager_thread_.join(); } - boost::future set_timer(long duration_micros) { + folly::Future set_timer(long duration_micros) { assert(initialized_); - boost::promise promise; - auto f = promise.get_future(); + folly::Promise promise; + auto f = promise.getFuture(); auto tp = clock_.now() + std::chrono::microseconds(duration_micros); - // Timer timer{tp, promise}; std::unique_lock l(queue_mutex_); queue_.emplace(std::make_shared(tp, std::move(promise))); queue_not_empty_condition_.notify_all(); diff --git a/src/libclipper/src/containers.cpp b/src/libclipper/src/containers.cpp index 706471ebd..ea7114b2f 100644 --- a/src/libclipper/src/containers.cpp +++ b/src/libclipper/src/containers.cpp @@ -14,7 +14,6 @@ #include #include -#include namespace clipper { diff --git a/src/libclipper/src/datatypes.cpp b/src/libclipper/src/datatypes.cpp index 19173a260..ba9134a3e 100644 --- a/src/libclipper/src/datatypes.cpp +++ b/src/libclipper/src/datatypes.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include namespace clipper { @@ -220,6 +221,7 @@ void rpc::PredictionRequest::validate_input_type( << get_readable_input_type(input->type()) << " to a prediction request with input type " << get_readable_input_type(input_type_); + log_error(LOGGING_TAG_CLIPPER, ss.str()); throw std::invalid_argument(ss.str()); } } diff --git a/src/libclipper/src/metrics.cpp b/src/libclipper/src/metrics.cpp index 18c0d9fa3..de4c9bc25 100644 --- a/src/libclipper/src/metrics.cpp +++ b/src/libclipper/src/metrics.cpp @@ -13,7 +13,7 @@ #include #include -#include + #include #include diff --git a/src/libclipper/src/persistent_state.cpp b/src/libclipper/src/persistent_state.cpp index e8ee24154..b62d15c1c 100644 --- a/src/libclipper/src/persistent_state.cpp +++ b/src/libclipper/src/persistent_state.cpp @@ -6,7 +6,6 @@ #include #include -#include #include #include #include diff --git a/src/libclipper/src/query_processor.cpp b/src/libclipper/src/query_processor.cpp index 2990ee8f2..7bc75bff5 100644 --- a/src/libclipper/src/query_processor.cpp +++ b/src/libclipper/src/query_processor.cpp @@ -9,13 +9,15 @@ #define PROVIDES_EXECUTORS #include #include -#include + #include +#include +#include + #include #include #include -#include #include #include #include @@ -40,7 +42,7 @@ std::shared_ptr QueryProcessor::get_state_table() const { return state_db_; } -boost::future QueryProcessor::predict(Query query) { +folly::Future QueryProcessor::predict(Query query) { long query_id = query_counter_.fetch_add(1); auto current_policy_iter = selection_policies_.find(query.selection_policy_); if (current_policy_iter == selection_policies_.end()) { @@ -72,7 +74,7 @@ boost::future QueryProcessor::predict(Query query) { log_info_formatted(LOGGING_TAG_QUERY_PROCESSOR, "Found {} tasks", tasks.size()); - vector> task_futures = + vector> task_futures = task_executor_.schedule_predictions(tasks); if (task_futures.empty()) { default_explanation = "No connected models found for query"; @@ -80,62 +82,61 @@ boost::future QueryProcessor::predict(Query query) { "No connected models found for query with id: {}", query_id); } - boost::future timer_future = - timer_system_.set_timer(query.latency_budget_micros_); - - boost::future all_tasks_completed; - auto num_completed = std::make_shared>(0); - std::tie(all_tasks_completed, task_futures) = - future::when_all(std::move(task_futures), num_completed); - - auto completed_flag = std::make_shared(); - // Due to some complexities of initializing the atomic_flag in a shared_ptr, - // we explicitly set the value of the flag to false after initialization. - completed_flag->clear(); - boost::future response_ready_future; - std::tie(response_ready_future, all_tasks_completed, timer_future) = - future::when_either(std::move(all_tasks_completed), - std::move(timer_future), completed_flag); + size_t num_tasks = task_futures.size(); - boost::promise response_promise; - auto response_future = response_promise.get_future(); + folly::Future timer_future = + timer_system_.set_timer(query.latency_budget_micros_); - // NOTE: We capture the num_completed, completed_flag, and default_explanation - // variables - // so that they outlive the composed_futures. - response_ready_future.then([ - this, query, query_id, response_promise = std::move(response_promise), - selection_state, current_policy, task_futures = std::move(task_futures), - num_completed, completed_flag, default_explanation - ](auto) mutable { - - vector outputs; - vector used_models; - bool all_tasks_timed_out = true; - for (auto r = task_futures.begin(); r != task_futures.end(); ++r) { - if ((*r).has_exception()) { - try { - boost::rethrow_exception((*r).get_exception_ptr()); - } catch (std::exception& e) { + std::shared_ptr outputs_mutex = std::make_shared(); + std::vector outputs; + outputs.reserve(task_futures.size()); + std::shared_ptr> outputs_ptr = + std::make_shared>(std::move(outputs)); + + std::vector> wrapped_task_futures; + for (auto it = task_futures.begin(); it < task_futures.end(); it++) { + wrapped_task_futures.push_back( + it->then([outputs_mutex, outputs_ptr](Output output) { + std::lock_guard lock(*outputs_mutex); + outputs_ptr->push_back(output); + }).onError([](const std::exception& e) { log_error_formatted( LOGGING_TAG_QUERY_PROCESSOR, "Unexpected error while executing prediction tasks: {}", e.what()); - } - } else if ((*r).is_ready()) { - outputs.push_back((*r).get()); - all_tasks_timed_out = false; - } - } - if (all_tasks_timed_out && !task_futures.empty() && !default_explanation) { + })); + } + + folly::Future all_tasks_completed_future = + folly::collect(wrapped_task_futures) + .then([](std::vector /* outputs */) {}); + + std::vector> when_either_futures; + when_either_futures.push_back(std::move(all_tasks_completed_future)); + when_either_futures.push_back(std::move(timer_future)); + + folly::Future>> + response_ready_future = folly::collectAny(when_either_futures); + + folly::Promise response_promise; + folly::Future response_future = response_promise.getFuture(); + + response_ready_future.then([ + outputs_ptr, outputs_mutex, num_tasks, query, query_id, selection_state, + current_policy, response_promise = std::move(response_promise), + default_explanation + ](const std::pair>& /* completed_future */) mutable { + std::lock_guard outputs_lock(*outputs_mutex); + if (outputs_ptr->empty() && num_tasks > 0 && !default_explanation) { default_explanation = "Failed to retrieve a prediction response within the specified " "latency SLO"; } - std::pair final_output = - current_policy->combine_predictions(selection_state, query, outputs); + std::pair final_output = current_policy->combine_predictions( + selection_state, query, *outputs_ptr); std::chrono::time_point end = std::chrono::high_resolution_clock::now(); @@ -150,17 +151,17 @@ boost::future QueryProcessor::predict(Query query) { final_output.first, final_output.second, default_explanation}; - response_promise.set_value(response); + response_promise.setValue(response); }); return response_future; } -boost::future QueryProcessor::update(FeedbackQuery feedback) { +folly::Future QueryProcessor::update(FeedbackQuery feedback) { log_info(LOGGING_TAG_QUERY_PROCESSOR, "Received feedback for user {}", feedback.user_id_); long query_id = query_counter_.fetch_add(1); - boost::future error_response = boost::make_ready_future(false); + folly::Future error_response = folly::makeFuture(false); auto current_policy_iter = selection_policies_.find(feedback.selection_policy_); @@ -200,68 +201,52 @@ boost::future QueryProcessor::update(FeedbackQuery feedback) { // 3) Complete select_policy_update_promise // 4) Wait for all feedback_tasks to complete (feedback_processed future) - vector> predict_task_futures = + vector> predict_task_futures = task_executor_.schedule_predictions({predict_tasks}); - vector> feedback_task_futures = + vector> feedback_task_futures = task_executor_.schedule_feedback(std::move(feedback_tasks)); - boost::future all_preds_completed; - auto num_preds_completed = std::make_shared>(0); - std::tie(all_preds_completed, predict_task_futures) = - future::when_all(std::move(predict_task_futures), num_preds_completed); + folly::Future> all_preds_completed = + folly::collect(predict_task_futures); - boost::future all_feedback_completed; - auto num_feedback_completed = std::make_shared>(0); - std::tie(all_feedback_completed, feedback_task_futures) = future::when_all( - std::move(feedback_task_futures), num_feedback_completed); + folly::Future> all_feedback_completed = + folly::collect(feedback_task_futures); // This promise gets completed after selection policy state update has // finished. - boost::promise select_policy_update_promise; + folly::Promise select_policy_update_promise; + folly::Future select_policy_updated = + select_policy_update_promise.getFuture(); auto state_table = get_state_table(); - auto select_policy_updated = select_policy_update_promise.get_future(); + all_preds_completed.then([ moved_promise = std::move(select_policy_update_promise), selection_state, - current_policy, state_table, feedback, query_id, state_key, - predict_task_futures = std::move(predict_task_futures) - ](auto) mutable { - - std::vector preds; - // collect actual predictions from their futures - for (auto& r : predict_task_futures) { - preds.push_back(r.get()); - } + current_policy, state_table, feedback, query_id, state_key + ](std::vector preds) mutable { auto new_selection_state = current_policy->process_feedback( selection_state, feedback.feedback_, preds); state_table->put(state_key, current_policy->serialize(new_selection_state)); - moved_promise.set_value(true); + moved_promise.setValue(true); }); - boost::future feedback_ack_ready_future; - auto num_futures_completed = std::make_shared>(0); - std::tie(feedback_ack_ready_future, all_feedback_completed, - select_policy_updated) = - future::when_both(std::move(all_feedback_completed), - std::move(select_policy_updated), - num_futures_completed); - - boost::future final_feedback_future = - feedback_ack_ready_future.then([ - select_policy_updated = std::move(select_policy_updated), - feedback_task_futures = std::move(feedback_task_futures) - ](auto) mutable { - auto select_policy_update_result = select_policy_updated.get(); - if (!select_policy_update_result) { - return false; - } - for (auto& r : feedback_task_futures) { - if (!r.get()) { - return false; - } - } - return true; - }); + auto feedback_ack_ready_future = + folly::collect(all_feedback_completed, select_policy_updated); + + folly::Future final_feedback_future = + feedback_ack_ready_future.then( + [](std::tuple, FeedbackAck> results) { + bool select_policy_update_result = std::get<1>(results); + if (!select_policy_update_result) { + return false; + } + for (FeedbackAck task_feedback : std::get<0>(results)) { + if (!task_feedback) { + return false; + } + } + return true; + }); return final_feedback_future; } diff --git a/src/libclipper/src/rpc_service.cpp b/src/libclipper/src/rpc_service.cpp index df72bd40b..7cfc4673e 100644 --- a/src/libclipper/src/rpc_service.cpp +++ b/src/libclipper/src/rpc_service.cpp @@ -1,6 +1,6 @@ #include #include -#include + #include #include diff --git a/src/libclipper/src/task_executor.cpp b/src/libclipper/src/task_executor.cpp index 7afb26d63..13086cbaa 100644 --- a/src/libclipper/src/task_executor.cpp +++ b/src/libclipper/src/task_executor.cpp @@ -8,8 +8,6 @@ #include #include -#include - namespace clipper { CacheEntry::CacheEntry() {} @@ -21,7 +19,7 @@ PredictionCache::PredictionCache() { "internal:prediction_cache_hit_ratio"); } -boost::future PredictionCache::fetch( +folly::Future PredictionCache::fetch( const VersionedModelId &model, const std::shared_ptr &input) { std::unique_lock l(m_); auto key = hash(model, input->hash()); @@ -32,11 +30,15 @@ boost::future PredictionCache::fetch( if (search->second.completed_) { // value already in cache hit_ratio_->increment(1, 1); - return boost::make_ready_future(search->second.value_); + // `makeFuture` takes an rvalue reference, so moving/forwarding + // the cache value directly would destroy it. Therefore, we use + // copy assignment to `value` and move the copied object instead + Output value = search->second.value_; + return folly::makeFuture(std::move(value)); } else { // value not in cache yet - boost::promise new_promise; - boost::future new_future = new_promise.get_future(); + folly::Promise new_promise; + folly::Future new_future = new_promise.getFuture(); search->second.value_promises_.push_back(std::move(new_promise)); hit_ratio_->increment(0, 1); return new_future; @@ -45,8 +47,8 @@ boost::future PredictionCache::fetch( // cache entry doesn't exist yet, so create entry CacheEntry new_entry; // create promise/future pair for this request - boost::promise new_promise; - boost::future new_future = new_promise.get_future(); + folly::Promise new_promise; + folly::Future new_future = new_promise.getFuture(); new_entry.value_promises_.push_back(std::move(new_promise)); cache_.insert(std::make_pair(key, std::move(new_entry))); hit_ratio_->increment(0, 1); @@ -64,7 +66,7 @@ void PredictionCache::put(const VersionedModelId &model, if (!search->second.completed_) { // Complete the outstanding promises for (auto &p : search->second.value_promises_) { - p.set_value(output); + p.setValue(std::move(output)); } search->second.completed_ = true; search->second.value_ = output; diff --git a/src/libclipper/src/timers.cpp b/src/libclipper/src/timers.cpp index 88d6c2b54..5f48ec86a 100644 --- a/src/libclipper/src/timers.cpp +++ b/src/libclipper/src/timers.cpp @@ -4,7 +4,6 @@ #include #include -#include #include #include @@ -15,7 +14,7 @@ namespace clipper { Timer::Timer( std::chrono::time_point deadline, - boost::promise completion_promise) + folly::Promise completion_promise) : deadline_(deadline), completion_promise_(std::move(completion_promise)) {} bool Timer::operator<(const Timer &rhs) const { @@ -34,6 +33,6 @@ bool Timer::operator>=(const Timer &rhs) const { return deadline_ >= rhs.deadline_; } -void Timer::expire() { completion_promise_.set_value(); } +void Timer::expire() { completion_promise_.setValue(); } } // namespace clipper diff --git a/src/libclipper/test/future_test.cpp b/src/libclipper/test/future_test.cpp deleted file mode 100644 index 48dfedaaa..000000000 --- a/src/libclipper/test/future_test.cpp +++ /dev/null @@ -1,202 +0,0 @@ - -#include -#include -#include -#include -#include - -#include -#include - -using namespace clipper; -using namespace std::chrono_literals; - -namespace { - -TEST(WhenAllTests, DontCompleteEarly) { - boost::promise p1; - boost::promise p2; - boost::promise p3; - - auto num_completed = std::make_shared>(0); - std::vector> v; - v.push_back(p1.get_future()); - v.push_back(p2.get_future()); - v.push_back(p3.get_future()); - - boost::future completion_future; - std::vector> v_copy; - std::tie(completion_future, v_copy) = - future::when_all(std::move(v), num_completed); - - ASSERT_FALSE(completion_future.is_ready()); - p1.set_value(); - std::this_thread::sleep_for(500us); - ASSERT_FALSE(completion_future.is_ready()); - p2.set_value(); - std::this_thread::sleep_for(500us); - ASSERT_FALSE(completion_future.is_ready()); - // p3.set_value(); - // std::this_thread::sleep_for(500us); - // ASSERT_TRUE(completion_future.is_ready()); -} - -TEST(WhenAllTests, CompleteCorrectly) { - boost::promise p1; - boost::promise p2; - boost::promise p3; - - auto num_completed = std::make_shared>(0); - std::vector> v; - v.push_back(p1.get_future()); - v.push_back(p2.get_future()); - v.push_back(p3.get_future()); - - boost::future completion_future; - std::vector> v_copy; - std::tie(completion_future, v_copy) = - future::when_all(std::move(v), num_completed); - - ASSERT_FALSE(completion_future.is_ready()); - p1.set_value(); - std::this_thread::sleep_for(500us); - ASSERT_FALSE(completion_future.is_ready()); - p2.set_value(); - std::this_thread::sleep_for(500us); - ASSERT_FALSE(completion_future.is_ready()); - p3.set_value(); - std::this_thread::sleep_for(500us); - ASSERT_TRUE(completion_future.is_ready()); -} - -TEST(WhenAllTests, SomeFuturesAlreadyComplete) { - boost::promise p1; - boost::future f1 = p1.get_future(); - p1.set_value(); - boost::promise p2; - boost::promise p3; - - auto num_completed = std::make_shared>(0); - std::vector> v; - v.push_back(std::move(f1)); - v.push_back(p2.get_future()); - v.push_back(p3.get_future()); - - boost::future completion_future; - std::vector> v_copy; - std::tie(completion_future, v_copy) = - future::when_all(std::move(v), num_completed); - - ASSERT_FALSE(completion_future.is_ready()); - p2.set_value(); - std::this_thread::sleep_for(500us); - ASSERT_FALSE(completion_future.is_ready()); - p3.set_value(); - std::this_thread::sleep_for(500us); - ASSERT_TRUE(completion_future.is_ready()); -} - -TEST(WhenBothTests, CompleteFirstEntryFirst) { - boost::promise p1; - boost::promise p2; - boost::future f1 = p1.get_future(); - boost::future f2 = p2.get_future(); - - auto num_completed = std::make_shared>(0); - boost::future completion_future; - std::tie(completion_future, f1, f2) = - future::when_both(std::move(f1), std::move(f2), num_completed); - - ASSERT_FALSE(completion_future.is_ready()); - p1.set_value(); - std::this_thread::sleep_for(500us); - ASSERT_FALSE(completion_future.is_ready()); - p2.set_value(); - std::this_thread::sleep_for(500us); - ASSERT_TRUE(completion_future.is_ready()); -} - -TEST(WhenBothTests, CompleteSecondEntryFirst) { - boost::promise p1; - boost::promise p2; - boost::future f1 = p1.get_future(); - boost::future f2 = p2.get_future(); - - auto num_completed = std::make_shared>(0); - boost::future completion_future; - std::tie(completion_future, f1, f2) = - future::when_both(std::move(f1), std::move(f2), num_completed); - - ASSERT_FALSE(completion_future.is_ready()); - p2.set_value(); - std::this_thread::sleep_for(500us); - ASSERT_FALSE(completion_future.is_ready()); - p1.set_value(); - std::this_thread::sleep_for(500us); - ASSERT_TRUE(completion_future.is_ready()); -} - -TEST(WhenBothTests, EntriesAlreadyComplete) { - boost::future f1 = boost::make_ready_future(); - boost::future f2 = boost::make_ready_future(); - - auto num_completed = std::make_shared>(0); - boost::future completion_future; - std::tie(completion_future, f1, f2) = - future::when_both(std::move(f1), std::move(f2), num_completed); - - std::this_thread::sleep_for(500us); - ASSERT_TRUE(completion_future.is_ready()); -} - -TEST(WhenEitherTests, CompleteFirstEntry) { - boost::promise p1; - boost::promise p2; - boost::future f1 = p1.get_future(); - boost::future f2 = p2.get_future(); - - auto num_completed = std::make_shared(); - num_completed->clear(); - boost::future completion_future; - std::tie(completion_future, f1, f2) = - future::when_either(std::move(f1), std::move(f2), num_completed); - - ASSERT_FALSE(completion_future.is_ready()); - p1.set_value(); - std::this_thread::sleep_for(500us); - ASSERT_TRUE(completion_future.is_ready()); -} - -TEST(WhenEitherTests, CompleteSecondEntry) { - boost::promise p1; - boost::promise p2; - boost::future f1 = p1.get_future(); - boost::future f2 = p2.get_future(); - - auto num_completed = std::make_shared(); - num_completed->clear(); - boost::future completion_future; - std::tie(completion_future, f1, f2) = - future::when_either(std::move(f1), std::move(f2), num_completed); - - ASSERT_FALSE(completion_future.is_ready()); - p2.set_value(); - std::this_thread::sleep_for(500us); - ASSERT_TRUE(completion_future.is_ready()); -} - -TEST(WhenEitherTests, EntryAlreadyComplete) { - boost::promise p2; - boost::future f1 = boost::make_ready_future(); - boost::future f2 = p2.get_future(); - - auto num_completed = std::make_shared(); - num_completed->clear(); - boost::future completion_future; - std::tie(completion_future, f1, f2) = - future::when_either(std::move(f1), std::move(f2), num_completed); - - std::this_thread::sleep_for(500us); - ASSERT_TRUE(completion_future.is_ready()); -} -} diff --git a/src/libclipper/test/timers_test.cpp b/src/libclipper/test/timers_test.cpp index 7d1d0804d..760f7689c 100644 --- a/src/libclipper/test/timers_test.cpp +++ b/src/libclipper/test/timers_test.cpp @@ -4,7 +4,6 @@ #include #include -#include #include using namespace clipper; @@ -20,30 +19,30 @@ class TimerSystemTests : public ::testing::Test { TEST_F(TimerSystemTests, SingleTimerExpire) { ASSERT_EQ(ts_.num_outstanding_timers(), (size_t)0); auto timer_future = ts_.set_timer(20000); - ASSERT_FALSE(timer_future.is_ready()); + ASSERT_FALSE(timer_future.isReady()); ASSERT_EQ(ts_.num_outstanding_timers(), (size_t)1); ts_.clock_.increment(10000); - ASSERT_FALSE(timer_future.is_ready()); + ASSERT_FALSE(timer_future.isReady()); ts_.clock_.increment(11000); // Let the timer system detect this std::this_thread::sleep_for(500us); - ASSERT_TRUE(timer_future.is_ready()) << "Uh oh"; + ASSERT_TRUE(timer_future.isReady()) << "Uh oh"; } TEST_F(TimerSystemTests, TwoTimerExpire) { auto t20 = ts_.set_timer(20000); auto t10 = ts_.set_timer(10000); ASSERT_EQ(ts_.num_outstanding_timers(), (size_t)2); - ASSERT_FALSE(t20.is_ready()); - ASSERT_FALSE(t10.is_ready()); + ASSERT_FALSE(t20.isReady()); + ASSERT_FALSE(t10.isReady()); ts_.clock_.increment(10000); std::this_thread::sleep_for(500us); - ASSERT_FALSE(t20.is_ready()); - ASSERT_TRUE(t10.is_ready()); + ASSERT_FALSE(t20.isReady()); + ASSERT_TRUE(t10.isReady()); ts_.clock_.increment(10000); std::this_thread::sleep_for(500us); - ASSERT_TRUE(t20.is_ready()); - ASSERT_TRUE(t10.is_ready()); + ASSERT_TRUE(t20.isReady()); + ASSERT_TRUE(t10.isReady()); } TEST_F(TimerSystemTests, OutOfOrderTimerExpire) { @@ -52,32 +51,32 @@ TEST_F(TimerSystemTests, OutOfOrderTimerExpire) { ASSERT_EQ(ts_.num_outstanding_timers(), (size_t)2); ts_.clock_.increment(5000); auto t3 = ts_.set_timer(10000); - ASSERT_FALSE(t1.is_ready()); - ASSERT_FALSE(t2.is_ready()); - ASSERT_FALSE(t3.is_ready()); + ASSERT_FALSE(t1.isReady()); + ASSERT_FALSE(t2.isReady()); + ASSERT_FALSE(t3.isReady()); ASSERT_EQ(ts_.num_outstanding_timers(), (size_t)3); ts_.clock_.increment(5000); std::this_thread::sleep_for(500us); - ASSERT_FALSE(t1.is_ready()); - ASSERT_TRUE(t2.is_ready()); - ASSERT_FALSE(t3.is_ready()); + ASSERT_FALSE(t1.isReady()); + ASSERT_TRUE(t2.isReady()); + ASSERT_FALSE(t3.isReady()); ASSERT_EQ(ts_.num_outstanding_timers(), (size_t)2); ts_.clock_.increment(5000); std::this_thread::sleep_for(500us); - ASSERT_FALSE(t1.is_ready()); - ASSERT_TRUE(t2.is_ready()); - ASSERT_TRUE(t3.is_ready()); + ASSERT_FALSE(t1.isReady()); + ASSERT_TRUE(t2.isReady()); + ASSERT_TRUE(t3.isReady()); ASSERT_EQ(ts_.num_outstanding_timers(), (size_t)1); ts_.clock_.increment(5000); std::this_thread::sleep_for(500us); - ASSERT_TRUE(t1.is_ready()); - ASSERT_TRUE(t2.is_ready()); - ASSERT_TRUE(t3.is_ready()); + ASSERT_TRUE(t1.isReady()); + ASSERT_TRUE(t2.isReady()); + ASSERT_TRUE(t3.isReady()); ASSERT_EQ(ts_.num_outstanding_timers(), (size_t)0); } TEST_F(TimerSystemTests, ManyTimers) { - std::unordered_map> created_timers; + std::unordered_map> created_timers; int max_time = 100000; std::random_device rd; std::mt19937 generator(rd()); @@ -93,7 +92,7 @@ TEST_F(TimerSystemTests, ManyTimers) { std::this_thread::sleep_for(100us); for (auto t = created_timers.begin(); t != created_timers.end();) { if (t->first <= cur_time) { - ASSERT_TRUE(t->second.is_ready()); + ASSERT_TRUE(t->second.isReady()); t = created_timers.erase(t); } else { ++t; diff --git a/src/libs/CMakeLists.txt b/src/libs/CMakeLists.txt index 32952f07c..47111dec6 100644 --- a/src/libs/CMakeLists.txt +++ b/src/libs/CMakeLists.txt @@ -60,4 +60,4 @@ export(TARGETS base64 FILE Base64Config.cmake) add_subdirectory(redox) -add_subdirectory(rapidjson) +add_subdirectory(rapidjson) \ No newline at end of file diff --git a/src/management/src/management_frontend.hpp b/src/management/src/management_frontend.hpp index 18454c1a3..4e5ec4cbe 100644 --- a/src/management/src/management_frontend.hpp +++ b/src/management/src/management_frontend.hpp @@ -7,8 +7,6 @@ #include #include -#include - #include #include diff --git a/src/management/src/management_frontend_tests.cpp b/src/management/src/management_frontend_tests.cpp index 1ad96c5bb..cec3ab346 100644 --- a/src/management/src/management_frontend_tests.cpp +++ b/src/management/src/management_frontend_tests.cpp @@ -1,8 +1,6 @@ #include #include -#include - #include #include #include