diff --git a/.travis.yml b/.travis.yml index c24c308..49892d2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,7 @@ matrix: apt: sources: - ubuntu-toolchain-r-test + - boost-latest packages: - g++-5 env: COMPILER=g++-5 diff --git a/CMake/BoostTest.cmake b/CMake/BoostTest.cmake new file mode 100644 index 0000000..fda8ffb --- /dev/null +++ b/CMake/BoostTest.cmake @@ -0,0 +1,70 @@ +function(boost_test_discover_tests TARGET) + cmake_parse_arguments( + BOOST_TEST + "" + "WORKING_DIRECTORY;DISCOVERY_TIMEOUT" + "EXTRA_ARGS" + ${ARGN} + ) + if (NOT BOOST_TEST_WORKING_DIRECTORY) + set(BOOST_TEST_WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + endif() + if (NOT BOOST_TEST_DISCOVERY_TIMEOUT) + set(BOOST_TEST_DISCOVERY_TIMEOUT 10) + endif() + get_property( + has_counter + TARGET ${TARGET} + PROPERTY BOOST_TEST_DISCOVERED_TEST_COUNTER + SET + ) + if(has_counter) + get_property( + counter + TARGET ${TARGET} + PROPERTY BOOST_TEST_DISCOVERED_TEST_COUNTER + ) + math(EXPR counter "${counter} + 1") + else() + set(counter 1) + endif() + set_property( + TARGET ${TARGET} + PROPERTY BOOST_TEST_DISCOVERED_TEST_COUNTER + ${counter} + ) + + # Define rule to generate test list for aforementioned test executable + set(ctest_file_base "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_${counter}") + set(ctest_include_file "${ctest_file_base}_include.cmake") + set(ctest_tests_file "${ctest_file_base}_tests.cmake") + add_custom_command( + TARGET ${TARGET} POST_BUILD + COMMAND "${CMAKE_COMMAND}" + -D "TEST_TARGET=${TARGET}" + -D "TEST_EXECUTABLE=$" + -D "TEST_WORKING_DIR=${BOOST_TEST_WORKING_DIRECTORY}" + -D "TEST_DISCOVERY_TIMEOUT=${BOOST_TEST_DISCOVERY_TIMEOUT}" + -D "CTEST_FILE=${ctest_tests_file}" + -P "${_BOOST_TEST_DISCOVER_TEST_SCRIPTS}" + VERBATIM + ) + + file(WRITE "${ctest_include_file}" + "if(EXISTS \"${ctest_tests_file}\")\n" + " include(\"${ctest_tests_file}\")\n" + "else()\n" + " add_test(${TARGET}_NOT_BUILT ${TARGET}_NOT_BUILT)\n" + "endif()\n" + ) + + # Add discovered tests to directory TEST_INCLUDE_FILES + set_property(DIRECTORY + APPEND PROPERTY TEST_INCLUDE_FILES "${ctest_include_file}" + ) + +endfunction() + +set(_BOOST_TEST_DISCOVER_TEST_SCRIPTS + ${CMAKE_CURRENT_LIST_DIR}/BoostTestDiscoverTests.cmake +) diff --git a/CMake/BoostTestDiscoverTests.cmake b/CMake/BoostTestDiscoverTests.cmake new file mode 100644 index 0000000..b5d74bf --- /dev/null +++ b/CMake/BoostTestDiscoverTests.cmake @@ -0,0 +1,56 @@ +set(script) + +function(add_command NAME) + set(_args "") + foreach (_arg ${ARGN}) + set(_args "${_args} ${_arg}") + endforeach() + set(script "${script}${NAME}(${_args})\n" PARENT_SCOPE) +endfunction() + +# List all available tests from executable +execute_process( + COMMAND "${TEST_EXECUTABLE}" -- --list_tests + WORKING_DIRECTORY "${TEST_WORKING_DIR}" + TIMEOUT "${TEST_DISCOVERY_TIMEOUT}" + OUTPUT_VARIABLE _boost_test_output + RESULT_VARIABLE _boost_test_result +) + +if (NOT ${_boost_test_result} EQUAL 0) + message(FATAL_ERROR + "Error listing test content from executable ${TEST_EXECUTABLE}.\n" + "Result: ${_boost_test_result}\n" + "Output:\n" + " ${_boost_test_output}" + ) +endif() + +string(REPLACE "\n" ";" _boost_test_output "${_boost_test_output}") + +# Parse output +foreach(line ${_boost_test_output}) + set(test ${line}) + set(pretty_test ${test}) + string(REGEX REPLACE "^MANUAL_" "" pretty_test "${pretty_test}") + add_command(add_test + "\"${pretty_test}\"" + "${TEST_EXECUTABLE}" + "\"--run_test=${line}\"" + ) + if (line MATCHES "^MANUAL_") + add_command(set_tests_properties + "${pretty_test}" + PROPERTIES DISABLED TRUE + ) + endif() + add_command(set_tests_properties + "\"${pretty_test}\"" + PROPERTIES + WORKING_DIRECTORY "${TEST_WORKING_DIR}" + LABELS "${TEST_TARGET}" + ) +endforeach() + +# Write CTest script +file(WRITE "${CTEST_FILE}" "${script}") diff --git a/CMakeLists.txt b/CMakeLists.txt index 6a31b08..7d2b305 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,22 @@ set(DISRUPTOR_VERSION "${DISRUPTOR_VERSION_MAJOR}.${DISRUPTOR_VERSION_MINOR}.${D enable_testing() +option(DISRUPTOR_BUILD_TESTS "Enable the build of tests and samples." OFF) +option(DISRUPTOR_BUILD_STATIC "Enable the build of the disruptor static library." ON) +option(DISRUPTOR_BUILD_SHARED "Enable the build of the disruptor static library." OFF) +option(DISRUPTOR_CONAN "Try to use conan to fetch dependencies." ON) + +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/CMake) + +if (DISRUPTOR_CONAN) + if (EXISTS ${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) + include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) + conan_basic_setup(TARGETS) + set(WITH_CONAN "conan") + message(STATUS "Using conan for dependencies.") + endif() +endif() + # enable gcc specific stuff if(CMAKE_COMPILER_IS_GNUCXX) set(COMPILER_FLAGS "-std=c++14") @@ -46,8 +62,12 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMPILER_FLAGS} ${WARNING_FLAGS}") add_subdirectory(Disruptor) if(DISRUPTOR_BUILD_TESTS) - add_subdirectory(googletest-release-1.8.0) - include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR}) + message(STATUS + "Building tests and samples." + ) + if (NOT WITH_CONAN) + add_subdirectory(googletest-release-1.8.0) + endif() add_subdirectory(Disruptor.PerfTests) add_subdirectory(Disruptor.TestTools) diff --git a/Disruptor.PerfTests/CMakeLists.txt b/Disruptor.PerfTests/CMakeLists.txt index 45586eb..e2f985a 100644 --- a/Disruptor.PerfTests/CMakeLists.txt +++ b/Disruptor.PerfTests/CMakeLists.txt @@ -1,16 +1,6 @@ project(Disruptor.PerfTests) cmake_minimum_required(VERSION 2.6) - -find_package(Boost COMPONENTS system thread date_time) -if(Boost_FOUND) - include_directories(${Boost_INCLUDE_DIRS}) - link_directories(${Boost_LIBRARY_DIRS}) -endif() - -include_directories("..") - - set(DisruptorPerfTests_sources main.cpp @@ -52,9 +42,13 @@ set(DisruptorPerfTests_sources ValueMutationEventHandler.cpp ) -add_definitions(-DBOOST_TEST_DYN_LINK) - add_executable(Disruptor.PerfTests ${DisruptorPerfTests_sources}) -target_link_libraries(Disruptor.PerfTests DisruptorStatic Disruptor.TestTools ${Boost_LIBRARIES} pthread) + +target_link_libraries(Disruptor.PerfTests + PRIVATE + Disruptor + Disruptor.TestTools + pthread +) add_custom_target(performance_test ${CMAKE_CURRENT_BINARY_DIR}/Disruptor.PerfTests) diff --git a/Disruptor.TestTools/BoostTestOptions.h b/Disruptor.TestTools/BoostTestOptions.h new file mode 100644 index 0000000..d322cc7 --- /dev/null +++ b/Disruptor.TestTools/BoostTestOptions.h @@ -0,0 +1,47 @@ +#pragma once + +#include +#include + +namespace Disruptor +{ +namespace Tests +{ + + static const boost::unit_test::label Manual("MANUAL"); + + struct BoostTestsListerVisitor : boost::unit_test::test_tree_visitor + { + void visit(const boost::unit_test::test_case& test) + { + static const auto& master = boost::unit_test::framework::master_test_suite(); + static const auto& masterName = master.p_name.get(); + + auto fullName = test.full_name(); + auto pos = fullName.find(masterName); + if (pos != std::string::npos) + fullName.erase(pos, masterName.length()); + + if (test.has_label("MANUAL")) + std::cout << "MANUAL_"; + std::cout << fullName << std::endl; + } + }; + + inline void addAdditionalCommandLineOptions() + { + int argc = boost::unit_test::framework::master_test_suite().argc; + for (int i = 0; i < argc; i++) + { + std::string argument(boost::unit_test::framework::master_test_suite().argv[i]); + if (argument == "--list_tests") + { + BoostTestsListerVisitor visitor; + boost::unit_test::traverse_test_tree(boost::unit_test::framework::master_test_suite(), visitor); + exit(0); + } + } + } + +} +} diff --git a/Disruptor.TestTools/CMakeLists.txt b/Disruptor.TestTools/CMakeLists.txt index 6d8105d..9da2853 100644 --- a/Disruptor.TestTools/CMakeLists.txt +++ b/Disruptor.TestTools/CMakeLists.txt @@ -1,16 +1,6 @@ project(Disruptor.TestTools) cmake_minimum_required(VERSION 2.6) - -find_package(Boost COMPONENTS system) -if(Boost_FOUND) - include_directories(${Boost_INCLUDE_DIRS}) - link_directories(${Boost_LIBRARY_DIRS}) -endif() - -include_directories("..") - - set(DisruptorTestTools_sources CountdownEvent.cpp @@ -22,3 +12,8 @@ set(DisruptorTestTools_sources ) add_library(Disruptor.TestTools STATIC ${DisruptorTestTools_sources}) + +target_link_libraries(Disruptor.TestTools + PUBLIC + Disruptor +) diff --git a/Disruptor.Tests/CMakeLists.txt b/Disruptor.Tests/CMakeLists.txt index 5d3ec82..537cfe7 100644 --- a/Disruptor.Tests/CMakeLists.txt +++ b/Disruptor.Tests/CMakeLists.txt @@ -1,13 +1,16 @@ project(Disruptor.Tests) cmake_minimum_required(VERSION 2.6) -find_package(Boost COMPONENTS system chrono thread unit_test_framework) -if(Boost_FOUND) - include_directories(${Boost_INCLUDE_DIRS}) - link_directories(${Boost_LIBRARY_DIRS}) -endif() +include (BoostTest) -ADD_DEFINITIONS(-DBOOST_TEST_DYN_LINK) +if (WITH_CONAN) + set(GMock_LIBRARY CONAN_PKG::gtest) + set(Boost_Libraries CONAN_PKG::boost) +else() + set(GMock_LIBRARY gtest gmock) + find_package(Boost COMPONENTS unit_test_framework REQUIRED) + set(Boost_Libraries Boost::unit_test_framwork) +endif() set(DisruptorTests_sources @@ -33,7 +36,10 @@ set(DisruptorTests_sources FixedSequenceGroupTest.cpp IgnoreExceptionHandlerTests.cpp LifecycleAwareTests.cpp + LiteBlockingWaitStrategyTests.cpp + LiteTimeoutBlockingWaitStrategyTests.cpp MultiProducerSequencerTests.cpp + PhasedBackoffWaitStrategyTests.cpp RingBufferTests.cpp RingBufferTestsFixture.cpp RingBufferWithMocksTest.cpp @@ -57,10 +63,12 @@ set(DisruptorTests_sources YieldingWaitStrategyTests.cpp ) -include_directories("..") - add_executable(Disruptor.Tests ${DisruptorTests_sources}) -target_link_libraries(Disruptor.Tests DisruptorStatic Disruptor.TestTools ${Boost_LIBRARIES} gmock) - -add_test(cmake_Disruptor.Tests ${CMAKE_CURRENT_BINARY_DIR}/Disruptor.Tests --result_code=no --report_level=no) +boost_test_discover_tests(Disruptor.Tests) +target_link_libraries(Disruptor.Tests + PRIVATE + Disruptor.TestTools + ${GMock_LIBRARY} + ${Boost_LIBRARIES} +) diff --git a/Disruptor.Tests/DelayedEventHandler.cpp b/Disruptor.Tests/DelayedEventHandler.cpp index b6a71c9..f22a85d 100644 --- a/Disruptor.Tests/DelayedEventHandler.cpp +++ b/Disruptor.Tests/DelayedEventHandler.cpp @@ -56,7 +56,6 @@ namespace Tests void DelayedEventHandler::waitForAndSetFlag(std::int32_t newValue) { - // while (!_stopped && Thread.CurrentThread.IsAlive && Interlocked.Exchange(ref _readyToProcessEvent, newValue) == newValue) while (!m_stopped && std::atomic_exchange(&m_readyToProcessEvent, newValue) == newValue) { std::this_thread::yield(); diff --git a/Disruptor.Tests/DisruptorStressTest.cpp b/Disruptor.Tests/DisruptorStressTest.cpp index 5b1efae..86c6087 100644 --- a/Disruptor.Tests/DisruptorStressTest.cpp +++ b/Disruptor.Tests/DisruptorStressTest.cpp @@ -156,7 +156,7 @@ BOOST_AUTO_TEST_CASE(ShouldHandleLotsOfThreads) end->wait(); while (ringBuffer->cursor() < (iterations - 1)) { - std::this_thread::sleep_for(std::chrono::milliseconds(0)); // LockSupport.parkNanos(1); + std::this_thread::sleep_for(std::chrono::milliseconds(0)); } testDisruptor->shutdown(); diff --git a/Disruptor.Tests/LiteBlockingWaitStrategyTests.cpp b/Disruptor.Tests/LiteBlockingWaitStrategyTests.cpp new file mode 100644 index 0000000..6cf3a49 --- /dev/null +++ b/Disruptor.Tests/LiteBlockingWaitStrategyTests.cpp @@ -0,0 +1,18 @@ +#include "stdafx.h" + +#include "Disruptor/LiteBlockingWaitStrategy.h" +#include "WaitStrategyTestUtil.h" + + +using namespace Disruptor; +using namespace Disruptor::Tests; + + +BOOST_AUTO_TEST_SUITE(LiteBlockingWaitStrategyTests) + +BOOST_AUTO_TEST_CASE(ShouldWaitForValue) +{ + assertWaitForWithDelayOf(50, std::make_shared< LiteBlockingWaitStrategy >()); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/Disruptor.Tests/LiteTimeoutBlockingWaitStrategyTests.cpp b/Disruptor.Tests/LiteTimeoutBlockingWaitStrategyTests.cpp new file mode 100644 index 0000000..c7d526b --- /dev/null +++ b/Disruptor.Tests/LiteTimeoutBlockingWaitStrategyTests.cpp @@ -0,0 +1,44 @@ +#include "stdafx.h" + +#include "Disruptor/LiteTimeoutBlockingWaitStrategy.h" +#include "Disruptor/Sequence.h" +#include "Disruptor/TimeoutException.h" + +#include "SequenceBarrierMock.h" + + +using namespace Disruptor; + + +BOOST_AUTO_TEST_SUITE(LiteTimeoutBlockingWaitStrategyTest) + +BOOST_AUTO_TEST_CASE(ShouldTimeoutWaitFor) +{ + auto sequenceBarrierMock = std::make_shared< testing::NiceMock< Tests::SequenceBarrierMock > >(); + + auto theTimeout = std::chrono::milliseconds(500); + auto waitStrategy = std::make_shared< LiteTimeoutBlockingWaitStrategy >(theTimeout); + auto cursor = std::make_shared< Sequence >(5); + const auto& dependent = cursor; + + EXPECT_CALL(*sequenceBarrierMock, checkAlert()).Times(testing::AtLeast(1)); + + auto t0 = ClockConfig::Clock::now(); + + try + { + waitStrategy->waitFor(6, *cursor, *dependent, *sequenceBarrierMock); + throw std::runtime_error("TimeoutException should have been thrown"); + } + catch (TimeoutException&) + { + } + + auto t1 = ClockConfig::Clock::now(); + + auto timeWaiting = t1 - t0; + + BOOST_CHECK(timeWaiting >= theTimeout); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/Disruptor.Tests/PhasedBackoffWaitStrategyTests.cpp b/Disruptor.Tests/PhasedBackoffWaitStrategyTests.cpp new file mode 100644 index 0000000..acec31f --- /dev/null +++ b/Disruptor.Tests/PhasedBackoffWaitStrategyTests.cpp @@ -0,0 +1,41 @@ +#include "stdafx.h" + +#include "Disruptor/PhasedBackoffWaitStrategy.h" +#include "WaitStrategyTestUtil.h" + + +using namespace Disruptor; +using namespace Disruptor::Tests; + + +BOOST_AUTO_TEST_SUITE(PhasedBackoffWaitStrategyTests) + +BOOST_AUTO_TEST_CASE(ShouldHandleImmediateSequenceChange) +{ + assertWaitForWithDelayOf(0, PhasedBackoffWaitStrategy::withLock(std::chrono::milliseconds(1), std::chrono::milliseconds(1))); + assertWaitForWithDelayOf(0, PhasedBackoffWaitStrategy::withLiteLock(std::chrono::milliseconds(1), std::chrono::milliseconds(1))); + assertWaitForWithDelayOf(0, PhasedBackoffWaitStrategy::withSleep(std::chrono::milliseconds(1), std::chrono::milliseconds(1))); +} + +BOOST_AUTO_TEST_CASE(ShouldHandleSequenceChangeWithOneMillisecondDelay) +{ + assertWaitForWithDelayOf(1, PhasedBackoffWaitStrategy::withLock(std::chrono::milliseconds(1), std::chrono::milliseconds(1))); + assertWaitForWithDelayOf(1, PhasedBackoffWaitStrategy::withLiteLock(std::chrono::milliseconds(1), std::chrono::milliseconds(1))); + assertWaitForWithDelayOf(1, PhasedBackoffWaitStrategy::withSleep(std::chrono::milliseconds(1), std::chrono::milliseconds(1))); +} + +BOOST_AUTO_TEST_CASE(ShouldHandleSequenceChangeWithTwoMillisecondDelay) +{ + assertWaitForWithDelayOf(2, PhasedBackoffWaitStrategy::withLock(std::chrono::milliseconds(1), std::chrono::milliseconds(1))); + assertWaitForWithDelayOf(2, PhasedBackoffWaitStrategy::withLiteLock(std::chrono::milliseconds(1), std::chrono::milliseconds(1))); + assertWaitForWithDelayOf(2, PhasedBackoffWaitStrategy::withSleep(std::chrono::milliseconds(1), std::chrono::milliseconds(1))); +} + +BOOST_AUTO_TEST_CASE(ShouldHandleSequenceChangeWithTenMillisecondDelay) +{ + assertWaitForWithDelayOf(10, PhasedBackoffWaitStrategy::withLock(std::chrono::milliseconds(1), std::chrono::milliseconds(1))); + assertWaitForWithDelayOf(10, PhasedBackoffWaitStrategy::withLiteLock(std::chrono::milliseconds(1), std::chrono::milliseconds(1))); + assertWaitForWithDelayOf(10, PhasedBackoffWaitStrategy::withSleep(std::chrono::milliseconds(1), std::chrono::milliseconds(1))); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/Disruptor.Tests/SequencerTests.cpp b/Disruptor.Tests/SequencerTests.cpp index 8ab2c70..cf45ca0 100644 --- a/Disruptor.Tests/SequencerTests.cpp +++ b/Disruptor.Tests/SequencerTests.cpp @@ -202,6 +202,11 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(ShouldNotAllowBulkNextOfZero, TSequencer, Seque BOOST_CHECK_THROW(this->m_sequencer->next(0), ArgumentException); } +BOOST_FIXTURE_TEST_CASE_TEMPLATE(ShouldNotAllowBulkNextGreaterThanBufferSize, TSequencer, Sequencers, SequencerTestFixture< TSequencer >) +{ + BOOST_CHECK_THROW(this->m_sequencer->next(this->m_bufferSize + 1), ArgumentException); +} + BOOST_FIXTURE_TEST_CASE_TEMPLATE(ShouldNotAllowBulkTryNextLessThanZero, TSequencer, Sequencers, SequencerTestFixture< TSequencer >) { BOOST_CHECK_THROW(this->m_sequencer->tryNext(-1), ArgumentException); diff --git a/Disruptor.Tests/main.cpp b/Disruptor.Tests/main.cpp index bacc16a..ba2c312 100644 --- a/Disruptor.Tests/main.cpp +++ b/Disruptor.Tests/main.cpp @@ -6,6 +6,8 @@ #include +#include "Disruptor.TestTools/BoostTestOptions.h" + #if _MSC_VER # pragma warning (disable: 4231) // nonstandard extension used : 'extern' before template explicit instantiation #endif @@ -21,6 +23,9 @@ struct GlobalFixture testing::GTEST_FLAG(throw_on_failure) = true; testing::InitGoogleMock(&boost::unit_test::framework::master_test_suite().argc, boost::unit_test::framework::master_test_suite().argv); + + Disruptor::Tests::addAdditionalCommandLineOptions(); + } ~GlobalFixture() @@ -29,4 +34,3 @@ struct GlobalFixture }; BOOST_GLOBAL_FIXTURE(GlobalFixture); - diff --git a/Disruptor/BatchEventProcessor.h b/Disruptor/BatchEventProcessor.h index 42f0069..39903c6 100644 --- a/Disruptor/BatchEventProcessor.h +++ b/Disruptor/BatchEventProcessor.h @@ -5,11 +5,11 @@ #include "Disruptor/IDataProvider.h" #include "Disruptor/IEventHandler.h" #include "Disruptor/IEventProcessor.h" +#include "Disruptor/IEventProcessorSequenceAware.h" #include "Disruptor/IExceptionHandler.h" #include "Disruptor/ILifecycleAware.h" #include "Disruptor/InvalidOperationException.h" #include "Disruptor/ISequenceBarrier.h" -#include "Disruptor/ISequenceReportingEventHandler.h" #include "Disruptor/ITimeoutHandler.h" #include "Disruptor/Sequence.h" #include "Disruptor/TimeoutException.h" @@ -50,9 +50,9 @@ namespace Disruptor , m_sequence(std::make_shared< Sequence >()) , m_sequenceRef(*m_sequence) { - auto sequenceReportingHandler = std::dynamic_pointer_cast< ISequenceReportingEventHandler< T > >(eventHandler); - if (sequenceReportingHandler != nullptr) - sequenceReportingHandler->setSequenceCallback(m_sequence); + auto processorSequenceAware = std::dynamic_pointer_cast< IEventProcessorSequenceAware >(eventHandler); + if (processorSequenceAware != nullptr) + processorSequenceAware->setSequenceCallback(m_sequence); m_timeoutHandler = std::dynamic_pointer_cast< ITimeoutHandler >(eventHandler); } diff --git a/Disruptor/BuildConfig.h b/Disruptor/BuildConfig.h index 624967a..9e37a7a 100644 --- a/Disruptor/BuildConfig.h +++ b/Disruptor/BuildConfig.h @@ -32,7 +32,13 @@ # define DISRUPTOR_CPP_11 -# if __x86_64__ || __ppc64__ +# if __arm__ +# define DISRUPTOR_CPU_ARM +# define DISRUPTOR_CPU_ARM_32 +# elif __aarch64__ +# define DISRUPTOR_CPU_ARM +# define DISRUPTOR_CPU_ARM_64 +# elif __x86_64__ || __ppc64__ # define DISRUPTOR_CPU_64 # else # define DISRUPTOR_CPU_32 @@ -81,3 +87,8 @@ # define DBG_UNREFERENCED_PARAMETER(P) (P) # define DBG_UNREFERENCED_LOCAL_VARIABLE(V) (V) #endif + +// detect C++17 +#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L) + # define DISRUPTOR_CPP_17 +#endif diff --git a/Disruptor/CMakeLists.txt b/Disruptor/CMakeLists.txt index 6f9bc4f..a3d4d6a 100644 --- a/Disruptor/CMakeLists.txt +++ b/Disruptor/CMakeLists.txt @@ -1,21 +1,22 @@ project(Disruptor) cmake_minimum_required(VERSION 2.6) -find_package(Boost COMPONENTS system thread chrono) -if(Boost_FOUND) - include_directories(${Boost_INCLUDE_DIRS}) - link_directories(${Boost_LIBRARY_DIRS}) +if (WITH_CONAN) + set(Boost_Libraries CONAN_PKG::boost) +else() + find_package(Boost COMPONENTS system thread chrono REQUIRED) + set(Boost_Libraries Boost::boost Boost::system Boost::thread Boost::chrono) endif() -include_directories("..") - - set(Disruptor_sources BasicExecutor.cpp BlockingWaitStrategy.cpp BusySpinWaitStrategy.cpp FixedSequenceGroup.cpp + LiteBlockingWaitStrategy.cpp + LiteTimeoutBlockingWaitStrategy.cpp + PhasedBackoffWaitStrategy.cpp ProcessingSequenceBarrier.cpp ProducerType.cpp RoundRobinThreadAffinedTaskScheduler.cpp @@ -66,6 +67,7 @@ set(Disruptor_headers IEventHandler.h IEventProcessor.h IEventProcessorFactory.h + IEventProcessorSequenceAware.h IEventReleaseAware.h IEventReleaser.h IEventSequencer.h @@ -87,9 +89,12 @@ set(Disruptor_headers ITimeoutHandler.h IWaitStrategy.h IWorkHandler.h + LiteBlockingWaitStrategy.h + LiteTimeoutBlockingWaitStrategy.h MultiProducerSequencer.h NoOpEventProcessor.h NotSupportedException.h + PhasedBackoffWaitStrategy.h Pragmas.h ProcessingSequenceBarrier.h ProducerType.h @@ -114,18 +119,59 @@ set(Disruptor_headers YieldingWaitStrategy.h ) -add_library(DisruptorShared SHARED ${Disruptor_sources}) -target_link_libraries(DisruptorShared ${Boost_LIBRARIES}) -set_target_properties(DisruptorShared PROPERTIES OUTPUT_NAME Disruptor) -set_target_properties(DisruptorShared PROPERTIES VERSION ${DISRUPTOR_VERSION}) -set_target_properties(DisruptorShared PROPERTIES SOVERSION ${DISRUPTOR_VERSION_MAJOR}) +get_filename_component(PARENT_DIR ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) + +function(configure_disruptor_target DISRUPTOR_TARGET) + target_include_directories(${DISRUPTOR_TARGET} + PUBLIC + $ + $ + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ) + target_link_libraries(${DISRUPTOR_TARGET} PUBLIC ${Boost_Libraries}) +endfunction() + + +set(DISRUPTOR_TARGETS) + +if (DISRUPTOR_BUILD_SHARED) + message(STATUS + "Building Disruptor as a shared library." + ) + add_library(DisruptorShared SHARED ${Disruptor_sources}) + configure_disruptor_target(DisruptorShared) + + set_target_properties(DisruptorShared PROPERTIES OUTPUT_NAME Disruptor) + set_target_properties(DisruptorShared PROPERTIES VERSION ${DISRUPTOR_VERSION}) + set_target_properties(DisruptorShared PROPERTIES SOVERSION ${DISRUPTOR_VERSION_MAJOR}) -add_library(DisruptorStatic STATIC ${Disruptor_sources}) -set_target_properties(DisruptorStatic PROPERTIES OUTPUT_NAME Disruptor) + list(APPEND DISRUPTOR_TARGETS DisruptorShared) +endif() + +if (DISRUPTOR_BUILD_STATIC) + message(STATUS + "Building Disruptor as a static library." + ) + add_library(DisruptorStatic STATIC ${Disruptor_sources}) + configure_disruptor_target(DisruptorStatic) + + set_target_properties(DisruptorStatic PROPERTIES OUTPUT_NAME Disruptor) + + list(APPEND DISRUPTOR_TARGETS DisruptorStatic) +endif() + +if (DISRUPTOR_BUILD_SHARED AND DISRUPTOR_BUILD_STATIC) + add_library(Disruptor ALIAS DisruptorStatic) +elseif(DISRUPTOR_BUILD_SHARED) + add_library(Disruptor ALIAS DisruptorShared) +else() + add_library(Disruptor ALIAS DisruptorStatic) +endif() install(FILES ${Disruptor_headers} DESTINATION include/Disruptor) -install(TARGETS DisruptorShared DisruptorStatic +install(TARGETS ${DISRUPTOR_TARGETS} LIBRARY DESTINATION lib ARCHIVE DESTINATION lib ) diff --git a/Disruptor/EventPoller.h b/Disruptor/EventPoller.h index 8abece5..6f85ba3 100644 --- a/Disruptor/EventPoller.h +++ b/Disruptor/EventPoller.h @@ -1,7 +1,5 @@ #pragma once -#include -#include #include #include "Disruptor/FixedSequenceGroup.h" @@ -10,7 +8,6 @@ #include "Disruptor/ISequence.h" #include "Disruptor/ProducerType.h" - namespace Disruptor { @@ -36,8 +33,14 @@ namespace Disruptor , m_gatingSequence(gatingSequence) {} - PollState poll(const std::function< bool(T&, std::int64_t, bool) >& eventHandler) + template + PollState poll(TEventHandler&& eventHandler) { +#if DISRUPTOR_CPP_17 + static_assert(std::is_invocable_r::value, + "eventHandler should have the following signature: bool(T&, std::int64_t, bool)"); +#endif + auto currentSequence = m_sequence->value(); auto nextSequence = currentSequence + 1; auto availableSequence = m_sequencer->getHighestPublishedSequence(nextSequence, m_gatingSequence->value()); diff --git a/Disruptor/IEventProcessorSequenceAware.h b/Disruptor/IEventProcessorSequenceAware.h new file mode 100644 index 0000000..88c4a33 --- /dev/null +++ b/Disruptor/IEventProcessorSequenceAware.h @@ -0,0 +1,34 @@ +#pragma once + +#include + +#include "Disruptor/ISequence.h" + + +namespace Disruptor +{ + + /** + * Implement this interface in your event handler to obtain the sequence. + * + * Used by the to set a callback allowing the event handler to notify + * when it has finished consuming an event if this happens after the OnEvent call. + * + * Typically this would be used when the handler is performing some sort of batching operation such as writing to an IO + * device; after the operation has completed, the implementation should set to update the + * sequence and allow other processes that are dependent on this handler to progress. + */ + class IEventProcessorSequenceAware + { + public: + virtual ~IEventProcessorSequenceAware() = default; + + /** + * Call by the to setup the callback. + * + * \param sequenceCallback callback on which to notify the that the sequence has progressed. + */ + virtual void setSequenceCallback(const std::shared_ptr< ISequence >& sequenceCallback) = 0; + }; + +} // namespace Disruptor diff --git a/Disruptor/ISequenceReportingEventHandler.h b/Disruptor/ISequenceReportingEventHandler.h index 9817a16..fecd50c 100644 --- a/Disruptor/ISequenceReportingEventHandler.h +++ b/Disruptor/ISequenceReportingEventHandler.h @@ -1,7 +1,7 @@ #pragma once #include "Disruptor/IEventHandler.h" -#include "Disruptor/ISequence.h" +#include "Disruptor/IEventProcessorSequenceAware.h" namespace Disruptor @@ -15,17 +15,10 @@ namespace Disruptor * \tparam T event implementation storing the data for sharing during exchange or parallel coordination of an event. */ template - class ISequenceReportingEventHandler : public IEventHandler< T > + class ISequenceReportingEventHandler : public IEventHandler< T >, public IEventProcessorSequenceAware { public: virtual ~ISequenceReportingEventHandler() = default; - - /** - * Call by the BatchEventProcessor to setup the callback. - * - * \param sequenceCallback callback on which to notify the BatchEventProcessor that the sequence has progressed. - */ - virtual void setSequenceCallback(const std::shared_ptr< ISequence >& sequenceCallback) = 0; }; } // namespace Disruptor diff --git a/Disruptor/LiteBlockingWaitStrategy.cpp b/Disruptor/LiteBlockingWaitStrategy.cpp new file mode 100644 index 0000000..d25a2c0 --- /dev/null +++ b/Disruptor/LiteBlockingWaitStrategy.cpp @@ -0,0 +1,60 @@ +#include "stdafx.h" +#include "LiteBlockingWaitStrategy.h" + +#include + +#include "ISequenceBarrier.h" +#include "Sequence.h" + + +namespace Disruptor +{ + + std::int64_t LiteBlockingWaitStrategy::waitFor(std::int64_t sequence, + Sequence& cursor, + ISequence& dependentSequence, + ISequenceBarrier& barrier) + { + if (cursor.value() < sequence) + { + boost::unique_lock< decltype(m_gate) > uniqueLock(m_gate); + + do + { + m_signalNeeded.exchange(true); + + if (cursor.value() >= sequence) + break; + + barrier.checkAlert(); + + m_conditionVariable.wait(uniqueLock); + } + while (cursor.value() < sequence); + } + + std::int64_t availableSequence; + while ((availableSequence = dependentSequence.value()) < sequence) + { + barrier.checkAlert(); + } + + return availableSequence; + } + + void LiteBlockingWaitStrategy::signalAllWhenBlocking() + { + if (m_signalNeeded.exchange(false)) + { + boost::unique_lock< decltype(m_gate) > uniqueLock(m_gate); + + m_conditionVariable.notify_all(); + } + } + + void LiteBlockingWaitStrategy::writeDescriptionTo(std::ostream& stream) const + { + stream << "LiteBlockingWaitStrategy"; + } + +} // namespace Disruptor diff --git a/Disruptor/LiteBlockingWaitStrategy.h b/Disruptor/LiteBlockingWaitStrategy.h new file mode 100644 index 0000000..7552697 --- /dev/null +++ b/Disruptor/LiteBlockingWaitStrategy.h @@ -0,0 +1,42 @@ +#pragma once + +#include + +#include + +#include "Disruptor/IWaitStrategy.h" + + +namespace Disruptor +{ + + /** + * Variation of the BlockingWaitStrategy that attempts to elide conditional wake-ups when the lock is uncontended. + * Shows performance improvements on microbenchmarks. However this wait strategy should be considered experimental + * as the correctness of the lock elision code has not been fully proved. + */ + class LiteBlockingWaitStrategy : public IWaitStrategy + { + public: + /** + * \see IWaitStrategy::waitFor + */ + std::int64_t waitFor(std::int64_t sequence, + Sequence& cursor, + ISequence& dependentSequence, + ISequenceBarrier& barrier) override; + + /** + * \see IWaitStrategy::signalAllWhenBlocking + */ + void signalAllWhenBlocking() override; + + void writeDescriptionTo(std::ostream& stream) const override; + + private: + boost::recursive_mutex m_gate; + boost::condition_variable_any m_conditionVariable; + std::atomic< bool > m_signalNeeded{ false }; + }; + +} // namespace Disruptor diff --git a/Disruptor/LiteTimeoutBlockingWaitStrategy.cpp b/Disruptor/LiteTimeoutBlockingWaitStrategy.cpp new file mode 100644 index 0000000..482e260 --- /dev/null +++ b/Disruptor/LiteTimeoutBlockingWaitStrategy.cpp @@ -0,0 +1,67 @@ +#include "stdafx.h" +#include "LiteTimeoutBlockingWaitStrategy.h" + +#include + +#include + +#include "ISequenceBarrier.h" +#include "Sequence.h" +#include "TimeoutException.h" + + +namespace Disruptor +{ + + LiteTimeoutBlockingWaitStrategy::LiteTimeoutBlockingWaitStrategy(ClockConfig::Duration timeout) + : m_timeout(timeout) + { + } + + std::int64_t LiteTimeoutBlockingWaitStrategy::waitFor(std::int64_t sequence, + Sequence& cursor, + ISequence& dependentSequence, + ISequenceBarrier& barrier) + { + auto timeSpan = boost::chrono::microseconds(std::chrono::duration_cast< std::chrono::microseconds >(m_timeout).count()); + + if (cursor.value() < sequence) + { + boost::unique_lock< decltype(m_gate) > uniqueLock(m_gate); + + while (cursor.value() < sequence) + { + m_signalNeeded.exchange(true); + + barrier.checkAlert(); + + if (m_conditionVariable.wait_for(uniqueLock, timeSpan) == boost::cv_status::timeout) + DISRUPTOR_THROW_TIMEOUT_EXCEPTION(); + } + } + + std::int64_t availableSequence; + while ((availableSequence = dependentSequence.value()) < sequence) + { + barrier.checkAlert(); + } + + return availableSequence; + } + + void LiteTimeoutBlockingWaitStrategy::signalAllWhenBlocking() + { + if (m_signalNeeded.exchange(false)) + { + boost::unique_lock< decltype(m_gate) > uniqueLock(m_gate); + + m_conditionVariable.notify_all(); + } + } + + void LiteTimeoutBlockingWaitStrategy::writeDescriptionTo(std::ostream& stream) const + { + stream << "LiteTimeoutBlockingWaitStrategy"; + } + +} // namespace Disruptor diff --git a/Disruptor/LiteTimeoutBlockingWaitStrategy.h b/Disruptor/LiteTimeoutBlockingWaitStrategy.h new file mode 100644 index 0000000..524b8c6 --- /dev/null +++ b/Disruptor/LiteTimeoutBlockingWaitStrategy.h @@ -0,0 +1,45 @@ +#pragma once + +#include + +#include + +#include "Disruptor/ClockConfig.h" +#include "Disruptor/IWaitStrategy.h" + + +namespace Disruptor +{ + + /** + * Variation of the TimeoutBlockingWaitStrategy that attempts to elide conditional wake-ups + * when the lock is uncontended. + */ + class LiteTimeoutBlockingWaitStrategy : public IWaitStrategy + { + public: + explicit LiteTimeoutBlockingWaitStrategy(ClockConfig::Duration timeout); + + /** + * \see IWaitStrategy::waitFor + */ + std::int64_t waitFor(std::int64_t sequence, + Sequence& cursor, + ISequence& dependentSequence, + ISequenceBarrier& barrier) override; + + /** + * \see IWaitStrategy::signalAllWhenBlocking + */ + void signalAllWhenBlocking() override; + + void writeDescriptionTo(std::ostream& stream) const override; + + private: + ClockConfig::Duration m_timeout; + boost::recursive_mutex m_gate; + boost::condition_variable_any m_conditionVariable; + std::atomic< bool > m_signalNeeded{ false }; + }; + +} // namespace Disruptor diff --git a/Disruptor/MultiProducerSequencer.h b/Disruptor/MultiProducerSequencer.h index a0370a4..4ec4d71 100644 --- a/Disruptor/MultiProducerSequencer.h +++ b/Disruptor/MultiProducerSequencer.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include "Disruptor/InsufficientCapacityException.h" @@ -23,7 +24,7 @@ namespace Disruptor MultiProducerSequencer(std::int32_t bufferSize, const std::shared_ptr< IWaitStrategy >& waitStrategy) : Sequencer< T >(bufferSize, waitStrategy) { - m_availableBuffer = std::unique_ptr< int[] >(new int [bufferSize]); + m_availableBuffer = std::unique_ptr< std::atomic< std::int32_t >[] >(new std::atomic< std::int32_t >[bufferSize]); m_indexMask = bufferSize - 1; m_indexShift = Util::log2(bufferSize); initializeAvailableBuffer(); @@ -76,9 +77,9 @@ namespace Disruptor */ std::int64_t next(std::int32_t n) override { - if (n < 1) + if (n < 1 || n > this->m_bufferSize) { - DISRUPTOR_THROW_ARGUMENT_EXCEPTION("n must be > 0"); + DISRUPTOR_THROW_ARGUMENT_EXCEPTION("n must be > 0 and < bufferSize"); } std::int64_t current; @@ -203,7 +204,7 @@ namespace Disruptor auto index = calculateIndex(sequence); auto flag = calculateAvailabilityFlag(sequence); - return m_availableBuffer[index] == flag; + return m_availableBuffer[index].load(std::memory_order_acquire) == flag; } /** @@ -250,12 +251,14 @@ namespace Disruptor void initializeAvailableBuffer() { + // Called from the constructor before any consumer can observe the + // sequencer, so relaxed stores are sufficient here. for (std::int32_t i = this->m_bufferSize - 1; i != 0; i--) { - setAvailableBufferValue(i, -1); + m_availableBuffer[i].store(-1, std::memory_order_relaxed); } - setAvailableBufferValue(0, -1); + m_availableBuffer[0].store(-1, std::memory_order_relaxed); } void setAvailable(std::int64_t sequence) @@ -265,7 +268,10 @@ namespace Disruptor void setAvailableBufferValue(std::int32_t index, std::int32_t flag) { - m_availableBuffer[index] = flag; + // Release-store so the event payload writes that happened before + // publish() are visible to any consumer that subsequently sees + // the flag via the matching acquire-load in isAvailable(). + m_availableBuffer[index].store(flag, std::memory_order_release); } std::int32_t calculateAvailabilityFlag(std::int64_t sequence) @@ -283,7 +289,7 @@ namespace Disruptor // availableBuffer tracks the state of each ringbuffer slot // see below for more details on the approach - std::unique_ptr< std::int32_t[] > m_availableBuffer; + std::unique_ptr< std::atomic< std::int32_t >[] > m_availableBuffer; std::int32_t m_indexMask; std::int32_t m_indexShift; }; diff --git a/Disruptor/PhasedBackoffWaitStrategy.cpp b/Disruptor/PhasedBackoffWaitStrategy.cpp new file mode 100644 index 0000000..0cf13ac --- /dev/null +++ b/Disruptor/PhasedBackoffWaitStrategy.cpp @@ -0,0 +1,95 @@ +#include "stdafx.h" +#include "PhasedBackoffWaitStrategy.h" + +#include +#include + +#include "ArgumentNullException.h" +#include "BlockingWaitStrategy.h" +#include "LiteBlockingWaitStrategy.h" +#include "SleepingWaitStrategy.h" + + +namespace Disruptor +{ + + PhasedBackoffWaitStrategy::PhasedBackoffWaitStrategy(ClockConfig::Duration spinTimeout, + ClockConfig::Duration yieldTimeout, + const std::shared_ptr< IWaitStrategy >& fallbackStrategy) + : m_spinTimeout(spinTimeout) + , m_yieldTimeout(spinTimeout + yieldTimeout) + , m_fallbackStrategy(fallbackStrategy) + { + if (fallbackStrategy == nullptr) + DISRUPTOR_THROW_ARGUMENT_NULL_EXCEPTION(fallbackStrategy); + } + + std::shared_ptr< PhasedBackoffWaitStrategy > PhasedBackoffWaitStrategy::withLock(ClockConfig::Duration spinTimeout, + ClockConfig::Duration yieldTimeout) + { + return std::make_shared< PhasedBackoffWaitStrategy >(spinTimeout, yieldTimeout, std::make_shared< BlockingWaitStrategy >()); + } + + std::shared_ptr< PhasedBackoffWaitStrategy > PhasedBackoffWaitStrategy::withLiteLock(ClockConfig::Duration spinTimeout, + ClockConfig::Duration yieldTimeout) + { + return std::make_shared< PhasedBackoffWaitStrategy >(spinTimeout, yieldTimeout, std::make_shared< LiteBlockingWaitStrategy >()); + } + + std::shared_ptr< PhasedBackoffWaitStrategy > PhasedBackoffWaitStrategy::withSleep(ClockConfig::Duration spinTimeout, + ClockConfig::Duration yieldTimeout) + { + return std::make_shared< PhasedBackoffWaitStrategy >(spinTimeout, yieldTimeout, std::make_shared< SleepingWaitStrategy >(0)); + } + + std::int64_t PhasedBackoffWaitStrategy::waitFor(std::int64_t sequence, + Sequence& cursor, + ISequence& dependentSequence, + ISequenceBarrier& barrier) + { + std::int64_t availableSequence; + ClockConfig::TimePoint startTime; + auto startTimeSet = false; + auto counter = m_spinTries; + + do + { + if ((availableSequence = dependentSequence.value()) >= sequence) + return availableSequence; + + if (--counter == 0) + { + if (!startTimeSet) + { + startTime = ClockConfig::Clock::now(); + startTimeSet = true; + } + else + { + auto timeDelta = ClockConfig::Clock::now() - startTime; + if (timeDelta > m_yieldTimeout) + return m_fallbackStrategy->waitFor(sequence, cursor, dependentSequence, barrier); + + if (timeDelta > m_spinTimeout) + std::this_thread::yield(); + } + + counter = m_spinTries; + } + } + while (true); + } + + void PhasedBackoffWaitStrategy::signalAllWhenBlocking() + { + m_fallbackStrategy->signalAllWhenBlocking(); + } + + void PhasedBackoffWaitStrategy::writeDescriptionTo(std::ostream& stream) const + { + stream << "PhasedBackoffWaitStrategy (fallback: "; + m_fallbackStrategy->writeDescriptionTo(stream); + stream << ")"; + } + +} // namespace Disruptor diff --git a/Disruptor/PhasedBackoffWaitStrategy.h b/Disruptor/PhasedBackoffWaitStrategy.h new file mode 100644 index 0000000..8b71462 --- /dev/null +++ b/Disruptor/PhasedBackoffWaitStrategy.h @@ -0,0 +1,73 @@ +#pragma once + +#include + +#include "Disruptor/ClockConfig.h" +#include "Disruptor/IWaitStrategy.h" + + +namespace Disruptor +{ + + /** + * Phased wait strategy for waiting IEventProcessors on a barrier. + * Spins, then yields, then waits using the configured fallback IWaitStrategy. + * This strategy can be used when throughput and low-latency are not as important as CPU resource. + */ + class PhasedBackoffWaitStrategy : public IWaitStrategy + { + public: + PhasedBackoffWaitStrategy(ClockConfig::Duration spinTimeout, + ClockConfig::Duration yieldTimeout, + const std::shared_ptr< IWaitStrategy >& fallbackStrategy); + + /** + * Construct PhasedBackoffWaitStrategy with fallback to BlockingWaitStrategy. + * + * \param spinTimeout The maximum time in to busy spin for. + * \param yieldTimeout The maximum time in to yield for. + * \returns The constructed wait strategy. + */ + static std::shared_ptr< PhasedBackoffWaitStrategy > withLock(ClockConfig::Duration spinTimeout, ClockConfig::Duration yieldTimeout); + + /** + * Construct PhasedBackoffWaitStrategy with fallback to LiteBlockingWaitStrategy. + * + * \param spinTimeout The maximum time in to busy spin for. + * \param yieldTimeout The maximum time in to yield for. + * \returns The constructed wait strategy. + */ + static std::shared_ptr< PhasedBackoffWaitStrategy > withLiteLock(ClockConfig::Duration spinTimeout, ClockConfig::Duration yieldTimeout); + + /** + * Construct PhasedBackoffWaitStrategy with fallback to SleepingWaitStrategy. + * + * \param spinTimeout The maximum time in to busy spin for. + * \param yieldTimeout The maximum time in to yield for. + * \returns The constructed wait strategy. + */ + static std::shared_ptr< PhasedBackoffWaitStrategy > withSleep(ClockConfig::Duration spinTimeout, ClockConfig::Duration yieldTimeout); + + /** + * \see IWaitStrategy::waitFor + */ + std::int64_t waitFor(std::int64_t sequence, + Sequence& cursor, + ISequence& dependentSequence, + ISequenceBarrier& barrier) override; + + /** + * \see IWaitStrategy::signalAllWhenBlocking + */ + void signalAllWhenBlocking() override; + + void writeDescriptionTo(std::ostream& stream) const override; + + private: + const std::int32_t m_spinTries = 10000; + ClockConfig::Duration m_spinTimeout; + ClockConfig::Duration m_yieldTimeout; + std::shared_ptr< IWaitStrategy > m_fallbackStrategy; + }; + +} // namespace Disruptor diff --git a/Disruptor/Sequencer.h b/Disruptor/Sequencer.h index a103af5..967b72b 100644 --- a/Disruptor/Sequencer.h +++ b/Disruptor/Sequencer.h @@ -100,11 +100,7 @@ namespace Disruptor */ std::int64_t getMinimumSequence() override { - //auto& gatingSequences = this->m_gatingSequences; - //auto gatingSequences = std::atomic_load_explicit(&this->m_gatingSequences, std::memory_order_acquire); - return Util::getMinimumSequence(m_gatingSequences, m_cursorRef.value()); - //return Util::getMinimumSequence(*gatingSequences, m_cursor->value()); } /** diff --git a/Disruptor/SingleProducerSequencer.h b/Disruptor/SingleProducerSequencer.h index ccdfd4f..228f8b2 100644 --- a/Disruptor/SingleProducerSequencer.h +++ b/Disruptor/SingleProducerSequencer.h @@ -86,9 +86,9 @@ namespace Disruptor */ std::int64_t next(std::int32_t n) override { - if (n < 1) + if (n < 1 || n > this->m_bufferSize) { - DISRUPTOR_THROW_ARGUMENT_EXCEPTION("n must be > 0"); + DISRUPTOR_THROW_ARGUMENT_EXCEPTION("n must be > 0 and < bufferSize"); } auto nextValue = m_fields.nextValue; diff --git a/Disruptor/SpinWait.cpp b/Disruptor/SpinWait.cpp index c6289e2..f0bc267 100644 --- a/Disruptor/SpinWait.cpp +++ b/Disruptor/SpinWait.cpp @@ -112,17 +112,28 @@ namespace Disruptor void SpinWait::yieldProcessor() { -#if defined(DISRUPTOR_VC_COMPILER) +#if defined(DISRUPTOR_STD_YIELD) + + std::this_thread::yield(); + +#elif defined(DISRUPTOR_VC_COMPILER) ::YieldProcessor(); #elif defined(DISRUPTOR_GNUC_COMPILER) +#if defined(DISRUPTOR_CPU_ARM) + asm volatile + ( + "yield" + ); +#else asm volatile - ( - "rep\n" - "nop" - ); + ( + "rep\n" + "nop" + ); +#endif #else diff --git a/README.md b/README.md index 195e523..08b78ff 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,22 @@ make If [Boost](http://www.boost.org/) has been installed into a custom location you will probably need to specify **BOOST_ROOT** variable. Please refer to the [Find boost](https://cmake.org/cmake/help/v3.0/module/FindBoost.html) documentation for details. +If you want to install [Boost](http://www.boost.org/) and other dependencies through conan, run `conan install` inside your `build` directory prior to running `cmake`: + +```sh +mkdir build && cd build +conan install .. +cmake .. -DCMAKE_BUILD_TYPE=release +make +``` + +By default, Disruptor's `CMakeLists.txt` will try to use files generated by conan for CMake. If it does not exist, it will fall back to your standard boost installation. To disable conan, use the **DISRUPTOR_CONAN** +flag: + +```sh +cmake .. -DCMAKE_BUILD_TYPE=release -DDISRUPTOR_CONAN=OFF +``` + Optionally you may want to compile and run the unit tests and benchmarks. The tests compilation is activated by means of **DISRUPTOR_BUILD_TESTS** flag: ```sh diff --git a/conanfile.txt b/conanfile.txt new file mode 100644 index 0000000..6c69213 --- /dev/null +++ b/conanfile.txt @@ -0,0 +1,9 @@ +[requires] +boost/1.72.0 +gtest/1.8.0@bincrafters/stable + +[generators] +cmake + +[options] +gtest:build_gmock=True diff --git a/googletest-release-1.8.0/googlemock/msvc/2019/gmock.vcxproj b/googletest-release-1.8.0/googlemock/msvc/2019/gmock.vcxproj new file mode 100644 index 0000000..c3b9265 --- /dev/null +++ b/googletest-release-1.8.0/googlemock/msvc/2019/gmock.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {34681F0D-CE45-415D-B5F2-5C662DFE3BD5} + gmock + Win32Proj + 10.0 + + + + StaticLibrary + Unicode + false + v142 + + + StaticLibrary + Unicode + false + v142 + + + StaticLibrary + Unicode + v142 + + + StaticLibrary + Unicode + v142 + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)..\..\..\lib\$(Platform)-$(PlatformToolset)\$(Configuration)\ + $(OutDir)$(ProjectName)\ + $(SolutionDir)..\..\..\lib\$(Platform)-$(PlatformToolset)\$(Configuration)\ + $(OutDir)$(ProjectName)\ + + + $(SolutionDir)..\..\..\lib\$(Platform)-$(PlatformToolset)\$(Configuration)\ + $(ProjectName) + $(OutDir)$(ProjectName)\ + + + $(SolutionDir)..\..\..\lib\$(Platform)-$(PlatformToolset)\$(Configuration)\ + $(ProjectName) + $(OutDir)$(ProjectName)\ + + + $(ProjectName) + + + $(ProjectName) + + + + Disabled + ..\..\include;..\..;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level3 + None + + + + + Disabled + ..\..\include;..\..;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + + + Level3 + None + + + + + ..\..\include;..\..;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + MultiThreadedDLL + + + Level3 + None + Full + Speed + + + + + ..\..\include;..\..;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + MultiThreadedDLL + + + Level3 + None + Full + Speed + + + + + + $(GTestDir);%(AdditionalIncludeDirectories) + $(GTestDir);%(AdditionalIncludeDirectories) + $(GTestDir);%(AdditionalIncludeDirectories) + $(GTestDir);%(AdditionalIncludeDirectories) + + + + + + \ No newline at end of file diff --git a/googletest-release-1.8.0/googlemock/msvc/2019/gmock.vcxproj.user b/googletest-release-1.8.0/googlemock/msvc/2019/gmock.vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/googletest-release-1.8.0/googlemock/msvc/2019/gmock.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/googletest-release-1.8.0/googlemock/msvc/2019/gmock_config.props b/googletest-release-1.8.0/googlemock/msvc/2019/gmock_config.props new file mode 100644 index 0000000..77bc95b --- /dev/null +++ b/googletest-release-1.8.0/googlemock/msvc/2019/gmock_config.props @@ -0,0 +1,19 @@ + + + + ../../../googletest + + + <_ProjectFileVersion>10.0.30319.1 + + + + $(GTestDir)/include;%(AdditionalIncludeDirectories) + + + + + $(GTestDir) + + + diff --git a/msvc/2015/Disruptor.PerfTests.vcxproj b/msvc/2015/Disruptor.PerfTests.vcxproj index f5dd731..ecf3894 100644 --- a/msvc/2015/Disruptor.PerfTests.vcxproj +++ b/msvc/2015/Disruptor.PerfTests.vcxproj @@ -182,7 +182,6 @@ - @@ -195,6 +194,7 @@ + diff --git a/msvc/2015/Disruptor.PerfTests.vcxproj.filters b/msvc/2015/Disruptor.PerfTests.vcxproj.filters index 3f6afcf..c85d313 100644 --- a/msvc/2015/Disruptor.PerfTests.vcxproj.filters +++ b/msvc/2015/Disruptor.PerfTests.vcxproj.filters @@ -237,8 +237,8 @@ Sequenced - + diff --git a/msvc/2015/Disruptor.TestTools.vcxproj.filters b/msvc/2015/Disruptor.TestTools.vcxproj.filters index 7bbb445..ff6410e 100644 --- a/msvc/2015/Disruptor.TestTools.vcxproj.filters +++ b/msvc/2015/Disruptor.TestTools.vcxproj.filters @@ -11,8 +11,10 @@ - + + Precompiled Headers + @@ -23,9 +25,13 @@ - - + + Precompiled Headers + + + Precompiled Headers + diff --git a/msvc/2015/Disruptor.Tests.vcxproj b/msvc/2015/Disruptor.Tests.vcxproj index 447addd..78f75f6 100644 --- a/msvc/2015/Disruptor.Tests.vcxproj +++ b/msvc/2015/Disruptor.Tests.vcxproj @@ -163,7 +163,10 @@ + + + diff --git a/msvc/2015/Disruptor.Tests.vcxproj.filters b/msvc/2015/Disruptor.Tests.vcxproj.filters index bbd2291..afb1bba 100644 --- a/msvc/2015/Disruptor.Tests.vcxproj.filters +++ b/msvc/2015/Disruptor.Tests.vcxproj.filters @@ -214,6 +214,15 @@ Tests + + Tests + + + Tests + + + Tests + Tests\Dsl\Stubs diff --git a/msvc/2015/Disruptor.vcxproj b/msvc/2015/Disruptor.vcxproj index ddb7261..946f09c 100644 --- a/msvc/2015/Disruptor.vcxproj +++ b/msvc/2015/Disruptor.vcxproj @@ -118,6 +118,7 @@ + @@ -139,9 +140,12 @@ + + + @@ -172,6 +176,9 @@ + + + diff --git a/msvc/2015/Disruptor.vcxproj.filters b/msvc/2015/Disruptor.vcxproj.filters index 9a7fd09..58906e2 100644 --- a/msvc/2015/Disruptor.vcxproj.filters +++ b/msvc/2015/Disruptor.vcxproj.filters @@ -154,6 +154,9 @@ + + + @@ -163,6 +166,7 @@ Util + @@ -180,6 +184,9 @@ + + + diff --git a/msvc/2017/Disruptor.PerfTests.vcxproj b/msvc/2017/Disruptor.PerfTests.vcxproj index 6c1f322..d86f5fa 100644 --- a/msvc/2017/Disruptor.PerfTests.vcxproj +++ b/msvc/2017/Disruptor.PerfTests.vcxproj @@ -182,7 +182,6 @@ - @@ -195,6 +194,7 @@ + diff --git a/msvc/2017/Disruptor.PerfTests.vcxproj.filters b/msvc/2017/Disruptor.PerfTests.vcxproj.filters index 3f6afcf..c85d313 100644 --- a/msvc/2017/Disruptor.PerfTests.vcxproj.filters +++ b/msvc/2017/Disruptor.PerfTests.vcxproj.filters @@ -237,8 +237,8 @@ Sequenced - + diff --git a/msvc/2017/Disruptor.TestTools.vcxproj.filters b/msvc/2017/Disruptor.TestTools.vcxproj.filters index 7bbb445..ff6410e 100644 --- a/msvc/2017/Disruptor.TestTools.vcxproj.filters +++ b/msvc/2017/Disruptor.TestTools.vcxproj.filters @@ -11,8 +11,10 @@ - + + Precompiled Headers + @@ -23,9 +25,13 @@ - - + + Precompiled Headers + + + Precompiled Headers + diff --git a/msvc/2017/Disruptor.Tests.vcxproj b/msvc/2017/Disruptor.Tests.vcxproj index db916f3..0b0e9f0 100644 --- a/msvc/2017/Disruptor.Tests.vcxproj +++ b/msvc/2017/Disruptor.Tests.vcxproj @@ -163,7 +163,10 @@ + + + diff --git a/msvc/2017/Disruptor.Tests.vcxproj.filters b/msvc/2017/Disruptor.Tests.vcxproj.filters index bbd2291..afb1bba 100644 --- a/msvc/2017/Disruptor.Tests.vcxproj.filters +++ b/msvc/2017/Disruptor.Tests.vcxproj.filters @@ -214,6 +214,15 @@ Tests + + Tests + + + Tests + + + Tests + Tests\Dsl\Stubs diff --git a/msvc/2017/Disruptor.vcxproj b/msvc/2017/Disruptor.vcxproj index 09b2f63..b05f161 100644 --- a/msvc/2017/Disruptor.vcxproj +++ b/msvc/2017/Disruptor.vcxproj @@ -118,6 +118,7 @@ + @@ -139,9 +140,12 @@ + + + @@ -172,6 +176,9 @@ + + + diff --git a/msvc/2017/Disruptor.vcxproj.filters b/msvc/2017/Disruptor.vcxproj.filters index 9a7fd09..58906e2 100644 --- a/msvc/2017/Disruptor.vcxproj.filters +++ b/msvc/2017/Disruptor.vcxproj.filters @@ -154,6 +154,9 @@ + + + @@ -163,6 +166,7 @@ Util + @@ -180,6 +184,9 @@ + + + diff --git a/msvc/2019/Disruptor-all.sln b/msvc/2019/Disruptor-all.sln new file mode 100644 index 0000000..ce5a402 --- /dev/null +++ b/msvc/2019/Disruptor-all.sln @@ -0,0 +1,75 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31229.75 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Disruptor", "Disruptor.vcxproj", "{0A1FF4F2-CD19-4B2B-944A-F14B849A2588}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Disruptor.Tests", "Disruptor.Tests.vcxproj", "{31883900-84FA-4EA0-B33A-0FDE44979F13}" + ProjectSection(ProjectDependencies) = postProject + {0A1FF4F2-CD19-4B2B-944A-F14B849A2588} = {0A1FF4F2-CD19-4B2B-944A-F14B849A2588} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Disruptor.PerfTests", "Disruptor.PerfTests.vcxproj", "{E580C3C4-C69D-4F84-B023-68DB76080186}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{0222BD82-4B1B-4D6F-8A35-8805B1087033}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Disruptor.TestTools", "Disruptor.TestTools.vcxproj", "{636795CA-A154-4C4B-B054-658F333F27E7}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gtest", "gtest", "{7A7E72D1-DD84-4E74-A6D6-E1845F94911A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gmock", "..\..\googletest-release-1.8.0\googlemock\msvc\2019\gmock.vcxproj", "{34681F0D-CE45-415D-B5F2-5C662DFE3BD5}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0A1FF4F2-CD19-4B2B-944A-F14B849A2588}.Debug|x64.ActiveCfg = Debug|x64 + {0A1FF4F2-CD19-4B2B-944A-F14B849A2588}.Debug|x64.Build.0 = Debug|x64 + {0A1FF4F2-CD19-4B2B-944A-F14B849A2588}.Debug|x86.ActiveCfg = Debug|x64 + {0A1FF4F2-CD19-4B2B-944A-F14B849A2588}.Release|x64.ActiveCfg = Release|x64 + {0A1FF4F2-CD19-4B2B-944A-F14B849A2588}.Release|x64.Build.0 = Release|x64 + {0A1FF4F2-CD19-4B2B-944A-F14B849A2588}.Release|x86.ActiveCfg = Release|x64 + {31883900-84FA-4EA0-B33A-0FDE44979F13}.Debug|x64.ActiveCfg = Debug|x64 + {31883900-84FA-4EA0-B33A-0FDE44979F13}.Debug|x64.Build.0 = Debug|x64 + {31883900-84FA-4EA0-B33A-0FDE44979F13}.Debug|x86.ActiveCfg = Debug|x64 + {31883900-84FA-4EA0-B33A-0FDE44979F13}.Release|x64.ActiveCfg = Release|x64 + {31883900-84FA-4EA0-B33A-0FDE44979F13}.Release|x64.Build.0 = Release|x64 + {31883900-84FA-4EA0-B33A-0FDE44979F13}.Release|x86.ActiveCfg = Release|x64 + {E580C3C4-C69D-4F84-B023-68DB76080186}.Debug|x64.ActiveCfg = Debug|x64 + {E580C3C4-C69D-4F84-B023-68DB76080186}.Debug|x64.Build.0 = Debug|x64 + {E580C3C4-C69D-4F84-B023-68DB76080186}.Debug|x86.ActiveCfg = Debug|x64 + {E580C3C4-C69D-4F84-B023-68DB76080186}.Release|x64.ActiveCfg = Release|x64 + {E580C3C4-C69D-4F84-B023-68DB76080186}.Release|x64.Build.0 = Release|x64 + {E580C3C4-C69D-4F84-B023-68DB76080186}.Release|x86.ActiveCfg = Release|x64 + {636795CA-A154-4C4B-B054-658F333F27E7}.Debug|x64.ActiveCfg = Debug|x64 + {636795CA-A154-4C4B-B054-658F333F27E7}.Debug|x64.Build.0 = Debug|x64 + {636795CA-A154-4C4B-B054-658F333F27E7}.Debug|x86.ActiveCfg = Debug|x64 + {636795CA-A154-4C4B-B054-658F333F27E7}.Release|x64.ActiveCfg = Release|x64 + {636795CA-A154-4C4B-B054-658F333F27E7}.Release|x64.Build.0 = Release|x64 + {636795CA-A154-4C4B-B054-658F333F27E7}.Release|x86.ActiveCfg = Release|x64 + {34681F0D-CE45-415D-B5F2-5C662DFE3BD5}.Debug|x64.ActiveCfg = Debug|x64 + {34681F0D-CE45-415D-B5F2-5C662DFE3BD5}.Debug|x64.Build.0 = Debug|x64 + {34681F0D-CE45-415D-B5F2-5C662DFE3BD5}.Debug|x86.ActiveCfg = Debug|Win32 + {34681F0D-CE45-415D-B5F2-5C662DFE3BD5}.Debug|x86.Build.0 = Debug|Win32 + {34681F0D-CE45-415D-B5F2-5C662DFE3BD5}.Release|x64.ActiveCfg = Release|x64 + {34681F0D-CE45-415D-B5F2-5C662DFE3BD5}.Release|x64.Build.0 = Release|x64 + {34681F0D-CE45-415D-B5F2-5C662DFE3BD5}.Release|x86.ActiveCfg = Release|Win32 + {34681F0D-CE45-415D-B5F2-5C662DFE3BD5}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {31883900-84FA-4EA0-B33A-0FDE44979F13} = {0222BD82-4B1B-4D6F-8A35-8805B1087033} + {E580C3C4-C69D-4F84-B023-68DB76080186} = {0222BD82-4B1B-4D6F-8A35-8805B1087033} + {636795CA-A154-4C4B-B054-658F333F27E7} = {0222BD82-4B1B-4D6F-8A35-8805B1087033} + {34681F0D-CE45-415D-B5F2-5C662DFE3BD5} = {7A7E72D1-DD84-4E74-A6D6-E1845F94911A} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {4EB2C634-95E1-4607-92B0-C32E261F5297} + EndGlobalSection +EndGlobal diff --git a/msvc/2019/Disruptor-all.sln.DotSettings.user b/msvc/2019/Disruptor-all.sln.DotSettings.user new file mode 100644 index 0000000..62e2ea1 --- /dev/null +++ b/msvc/2019/Disruptor-all.sln.DotSettings.user @@ -0,0 +1,4 @@ + + <SessionState ContinuousTestingMode="0" IsActive="True" Name="All tests from &lt;Tests&gt;\&lt;Disruptor.Tests&gt;" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> + <Project Location="C:\Dev\Disruptor-cpp\msvc\2019" Presentation="&lt;Tests&gt;\&lt;Disruptor.Tests&gt;" /> +</SessionState> \ No newline at end of file diff --git a/msvc/2019/Disruptor-lib.sln b/msvc/2019/Disruptor-lib.sln new file mode 100644 index 0000000..afea99c --- /dev/null +++ b/msvc/2019/Disruptor-lib.sln @@ -0,0 +1,24 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27004.2006 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Disruptor", "Disruptor.vcxproj", "{0A1FF4F2-CD19-4B2B-944A-F14B849A2588}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0A1FF4F2-CD19-4B2B-944A-F14B849A2588}.Debug|x64.ActiveCfg = Debug|x64 + {0A1FF4F2-CD19-4B2B-944A-F14B849A2588}.Debug|x64.Build.0 = Debug|x64 + {0A1FF4F2-CD19-4B2B-944A-F14B849A2588}.Release|x64.ActiveCfg = Release|x64 + {0A1FF4F2-CD19-4B2B-944A-F14B849A2588}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {6BE09E8D-A408-4BC1-97CD-D761CC2E301E} + EndGlobalSection +EndGlobal diff --git a/msvc/2019/Disruptor.PerfTests.vcxproj b/msvc/2019/Disruptor.PerfTests.vcxproj new file mode 100644 index 0000000..c3d7f2a --- /dev/null +++ b/msvc/2019/Disruptor.PerfTests.vcxproj @@ -0,0 +1,213 @@ + + + + + Debug + x64 + + + Release + x64 + + + + {E580C3C4-C69D-4F84-B023-68DB76080186} + Win32Proj + Disruptor.PerfTests + 8.1 + + + + Application + true + MultiByte + v142 + + + Application + false + true + MultiByte + v142 + + + + + + + + + + + + + true + ..\bin\$(Configuration)_$(Platform)_$(PlatformToolset)\$(ProjectName)\ + ..\obj\$(Configuration)_$(Platform)_$(PlatformToolset)\$(ProjectName)\ + + + false + ..\bin\$(Configuration)_$(Platform)_$(PlatformToolset)\$(ProjectName)\ + ..\obj\$(Configuration)_$(Platform)_$(PlatformToolset)\$(ProjectName)\ + + + + Use + Level4 + Disabled + WIN32;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../..;%(AdditionalIncludeDirectories) + Async + true + false + + + Console + true + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + %(AdditionalLibraryDirectories) + + + + + + + + + + + + + Level4 + Use + Full + true + true + WIN32;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;NOMINMAX;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + AnySuitable + Speed + ../..;%(AdditionalIncludeDirectories) + Async + true + + + Console + true + true + true + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + %(AdditionalLibraryDirectories) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create + Create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {636795ca-a154-4c4b-b054-658f333f27e7} + + + {0a1ff4f2-cd19-4b2b-944a-f14b849a2588} + + + + + + \ No newline at end of file diff --git a/msvc/2019/Disruptor.PerfTests.vcxproj.filters b/msvc/2019/Disruptor.PerfTests.vcxproj.filters new file mode 100644 index 0000000..c85d313 --- /dev/null +++ b/msvc/2019/Disruptor.PerfTests.vcxproj.filters @@ -0,0 +1,246 @@ + + + + + {0221edb6-70ca-4a20-9c5b-03bb73331cfe} + + + {8a04e59a-40f5-4566-aaa2-e15f9c2efda4} + + + {5e0d3237-6a0c-4657-816f-bfe119d6ca29} + + + {159a3785-dc26-480c-9605-a0f356bc0945} + + + {7fd7a2d7-9ecc-4d01-986f-1f9309073eaa} + + + {a5e40b8b-91ee-4357-b503-07f44c60cbed} + + + + + Precompiled Headers + + + + + WorkHandler + + + + + Sequenced + + + Raw + + + Raw + + + Sequenced + + + Translator + + + + WorkHandler + + + WorkHandler + + + Sequenced + + + Sequenced + + + Sequenced + + + Sequenced + + + Sequenced + + + Sequenced + + + Sequenced + + + Sequenced + + + Support + + + Support + + + Support + + + Support + + + Support + + + Support + + + Support + + + Support + + + Support + + + Support + + + Support + + + Support + + + Sequenced + + + + + + + Precompiled Headers + + + Precompiled Headers + + + + Raw + + + Raw + + + Sequenced + + + + + + + WorkHandler + + + Support + + + Support + + + Support + + + Support + + + Sequenced + + + Support + + + Support + + + Support + + + Translator + + + Support + + + + WorkHandler + + + Support + + + Support + + + WorkHandler + + + Sequenced + + + Sequenced + + + Sequenced + + + Sequenced + + + Sequenced + + + Sequenced + + + Sequenced + + + Sequenced + + + Support + + + Support + + + Support + + + Support + + + Support + + + Support + + + Support + + + Support + + + Sequenced + + + + + + + + \ No newline at end of file diff --git a/msvc/2019/Disruptor.PerfTests.vcxproj.user b/msvc/2019/Disruptor.PerfTests.vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/msvc/2019/Disruptor.PerfTests.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/msvc/2019/Disruptor.TestTools.vcxproj b/msvc/2019/Disruptor.TestTools.vcxproj new file mode 100644 index 0000000..1ae672c --- /dev/null +++ b/msvc/2019/Disruptor.TestTools.vcxproj @@ -0,0 +1,141 @@ + + + + + Debug + x64 + + + Release + x64 + + + + {636795CA-A154-4C4B-B054-658F333F27E7} + Win32Proj + Disruptor.TestTools + 8.1 + + + + StaticLibrary + true + MultiByte + v142 + + + StaticLibrary + false + true + MultiByte + v142 + + + + + + + + + + + + + true + ..\lib\$(Configuration)_$(Platform)_$(PlatformToolset)\$(ProjectName)\ + ..\obj\$(Configuration)_$(Platform)_$(PlatformToolset)\$(ProjectName)\ + + + false + ..\lib\$(Configuration)_$(Platform)_$(PlatformToolset)\$(ProjectName)\ + ..\obj\$(Configuration)_$(Platform)_$(PlatformToolset)\$(ProjectName)\ + + + + Use + Level4 + Disabled + WIN32;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../..;%(AdditionalIncludeDirectories) + Async + true + false + + + Console + true + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + %(AdditionalLibraryDirectories) + + + + + + + + Level4 + Use + Full + true + true + WIN32;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;NOMINMAX;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + AnySuitable + Speed + ../..;%(AdditionalIncludeDirectories) + Async + true + + + Console + true + true + true + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + %(AdditionalLibraryDirectories) + + + + + + + + + + + + + + + + + + Create + Create + + + + + + + + + + + + + + + + + + + {0a1ff4f2-cd19-4b2b-944a-f14b849a2588} + + + + + + + + + \ No newline at end of file diff --git a/msvc/2019/Disruptor.TestTools.vcxproj.filters b/msvc/2019/Disruptor.TestTools.vcxproj.filters new file mode 100644 index 0000000..ff6410e --- /dev/null +++ b/msvc/2019/Disruptor.TestTools.vcxproj.filters @@ -0,0 +1,39 @@ + + + + + {0221edb6-70ca-4a20-9c5b-03bb73331cfe} + + + + + + + + + + + Precompiled Headers + + + + + + + + + + + + + + Precompiled Headers + + + Precompiled Headers + + + + + + \ No newline at end of file diff --git a/msvc/2019/Disruptor.TestTools.vcxproj.user b/msvc/2019/Disruptor.TestTools.vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/msvc/2019/Disruptor.TestTools.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/msvc/2019/Disruptor.Tests.vcxproj b/msvc/2019/Disruptor.Tests.vcxproj new file mode 100644 index 0000000..ee45a97 --- /dev/null +++ b/msvc/2019/Disruptor.Tests.vcxproj @@ -0,0 +1,218 @@ + + + + + Debug + x64 + + + Release + x64 + + + + {31883900-84FA-4EA0-B33A-0FDE44979F13} + Win32Proj + Disruptor.Tests + 8.1 + + + + Application + true + MultiByte + v142 + + + Application + false + true + MultiByte + v142 + + + + + + + + + + + + + true + ..\bin\$(Configuration)_$(Platform)_$(PlatformToolset)\$(ProjectName)\ + ..\obj\$(Configuration)_$(Platform)_$(PlatformToolset)\$(ProjectName)\ + + + false + ..\bin\$(Configuration)_$(Platform)_$(PlatformToolset)\$(ProjectName)\ + ..\obj\$(Configuration)_$(Platform)_$(PlatformToolset)\$(ProjectName)\ + + + + Use + Level4 + Disabled + WIN32;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../googletest-release-1.8.0/googletest/include;../../googletest-release-1.8.0/googlemock/include;../..;%(AdditionalIncludeDirectories) + Async + true + false + + + Console + true + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + %(AdditionalLibraryDirectories);..\lib\$(Configuration)_$(Platform)_$(PlatformToolset)\gmock + + + call ../../Disruptor.Tests/postbuild.bat $(OutDir) $(Configuration) $(Platform) $(PlatformToolsetVersion) +%(Command) + + + + + + + + + Level4 + Use + Full + true + true + WIN32;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;NOMINMAX;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + AnySuitable + Speed + ../../googletest-release-1.8.0/googletest/include;../../googletest-release-1.8.0/googlemock/include;../..;%(AdditionalIncludeDirectories) + Async + true + + + Console + true + true + true + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + %(AdditionalLibraryDirectories);..\lib\$(Configuration)_$(Platform)_$(PlatformToolset)\gmock + + + call ../../Disruptor.Tests/postbuild.bat $(OutDir) $(Configuration) $(Platform) $(PlatformToolsetVersion) +%(Command) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NotUsing + NotUsing + + + + + + + Create + Create + + + + + + + + + + + + + + + + + + + {34681f0d-ce45-415d-b5f2-5c662dfe3bd5} + + + {636795ca-a154-4c4b-b054-658f333f27e7} + + + {0a1ff4f2-cd19-4b2b-944a-f14b849a2588} + + + + + + \ No newline at end of file diff --git a/msvc/2019/Disruptor.Tests.vcxproj.filters b/msvc/2019/Disruptor.Tests.vcxproj.filters new file mode 100644 index 0000000..afb1bba --- /dev/null +++ b/msvc/2019/Disruptor.Tests.vcxproj.filters @@ -0,0 +1,273 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {2be8e1d6-0486-493e-8387-b812b75b07a2} + + + {cfd2abca-087d-4dc4-abd2-d0699cd44db3} + + + {4c9451d3-f856-4a32-8604-5bc2c72c8b91} + + + {21d43697-4356-47be-9a5b-c60a6c766d9b} + + + {ad2c0162-aff0-4c60-a6d8-c74bb13f25ba} + + + {ce496d97-e1fa-43a0-a7fb-10acfd8f7577} + + + + + Precompiled Headers + + + Precompiled Headers + + + Tests\Support + + + Tests\Support + + + Tests\Support + + + Tests\Dsl\Stubs + + + Tests\Dsl\Stubs + + + Tests\Dsl\Stubs + + + Tests\Dsl\Stubs + + + Tests\Dsl\Stubs + + + Tests\Dsl\Stubs + + + Tests\Dsl\Stubs + + + Tests\Dsl\Stubs + + + Tests\Support + + + Tests\Support + + + Tests\Mocks + + + Tests\Mocks + + + Tests\Mocks + + + Tests\Fixtures + + + Tests\Mocks + + + Tests\Fixtures + + + Tests\Fixtures + + + Tests\Fixtures + + + Tests\Fixtures + + + Tests\Mocks + + + Tests\Mocks + + + Tests\Fixtures + + + Tests\Mocks + + + Tests\Support + + + Tests\Support + + + Tests\Support + + + Tests\Mocks + + + Tests\Fixtures + + + + + + Precompiled Headers + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests\Dsl + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests\Support + + + Tests\Support + + + Tests\Support + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests\Dsl\Stubs + + + Tests\Dsl\Stubs + + + Tests\Dsl\Stubs + + + Tests\Dsl\Stubs + + + Tests\Dsl\Stubs + + + Tests\Dsl\Stubs + + + Tests\Fixtures + + + Tests\Fixtures + + + Tests\Fixtures + + + Tests\Fixtures + + + Tests\Fixtures + + + Tests\Fixtures + + + Tests\Support + + + Tests\Support + + + + + + + \ No newline at end of file diff --git a/msvc/2019/Disruptor.Tests.vcxproj.user b/msvc/2019/Disruptor.Tests.vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/msvc/2019/Disruptor.Tests.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/msvc/2019/Disruptor.vcxproj b/msvc/2019/Disruptor.vcxproj new file mode 100644 index 0000000..590f626 --- /dev/null +++ b/msvc/2019/Disruptor.vcxproj @@ -0,0 +1,208 @@ + + + + + Debug + x64 + + + Release + x64 + + + + {0A1FF4F2-CD19-4B2B-944A-F14B849A2588} + Win32Proj + 8.1 + + + + StaticLibrary + true + MultiByte + v142 + + + StaticLibrary + false + true + MultiByte + v142 + + + + + + + + + + + + + ..\lib\$(Configuration)_$(Platform)_$(PlatformToolset)\$(ProjectName)\ + ..\obj\$(Configuration)_$(Platform)_$(PlatformToolset)\$(ProjectName)\ + + + ..\lib\$(Configuration)_$(Platform)_$(PlatformToolset)\$(ProjectName)\ + ..\obj\$(Configuration)_$(Platform)_$(PlatformToolset)\$(ProjectName)\ + + + + Use + Level4 + Disabled + WIN32;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_DEBUG;_LIB;%(PreprocessorDefinitions) + ../..;%(AdditionalIncludeDirectories) + true + false + + + Windows + true + + + MachineX64 + + + + + Level4 + Use + Full + true + true + WIN32;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;NOMINMAX;NDEBUG;_LIB;%(PreprocessorDefinitions) + AnySuitable + Speed + ../..;%(AdditionalIncludeDirectories) + true + + + Windows + true + true + true + + + MachineX64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create + Create + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/msvc/2019/Disruptor.vcxproj.filters b/msvc/2019/Disruptor.vcxproj.filters new file mode 100644 index 0000000..58906e2 --- /dev/null +++ b/msvc/2019/Disruptor.vcxproj.filters @@ -0,0 +1,219 @@ + + + + + {6644d11a-c49a-4ddf-b6c8-d9b4538c6a59} + + + {4b4f6684-f5e4-40f6-a133-b43237a35a91} + + + {cfdb7ab7-15dc-40ea-a003-28da004d30ed} + + + {2adee549-12dd-4aaa-94a5-f3a2e8b97687} + + + {14911d56-7ab2-4c7e-a258-bcdf55a2979c} + + + + + Precompiled Headers + + + Precompiled Headers + + + + + + + + + + + + + + + + + Exceptions + + + Config + + + Config + + + Exceptions + + + + Dsl + + + Exceptions + + + + + Exceptions + + + + + + Exceptions + + + Util + + + Util + + + + Exceptions + + + Exceptions + + + + + + + + + + + + + Exceptions + + + + Exceptions + + + Dsl + + + Dsl + + + Dsl + + + Util + + + Util + + + Dsl + + + + + Dsl + + + Dsl + + + Dsl + + + Dsl + + + + + Dsl + + + Config + + + Dsl + + + Util + + + Dsl + + + + Exceptions + + + + + + + + + + + Util + + + Util + + + + + + + Precompiled Headers + + + Util + + + + Dsl + + + Util + + + + + + + + + + + + Util + + + Dsl + + + + + + Util + + + Util + + + Util + + + Util + + + + + + \ No newline at end of file diff --git a/msvc/2019/Disruptor.vcxproj.user b/msvc/2019/Disruptor.vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/msvc/2019/Disruptor.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/msvc/boost.props b/msvc/boost.props index 4c32bbf..aedccd6 100644 --- a/msvc/boost.props +++ b/msvc/boost.props @@ -6,7 +6,7 @@ $(BOOST_HOME)/ $(BoostRoot) $(BoostRoot)lib\ - $(BoostRoot)lib\vc141-x64\ + $(BoostRoot)lib\msvc$(PlatformToolsetVersion)-x64\ $(BOOST_LIB_PATH)