diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d2533d..44d118d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,8 +11,8 @@ file(GLOB prj_src src/*) target_sources(${PROJECT_NAME} PRIVATE ${prj_src}) -target_compile_options(${PROJECT_NAME} PRIVATE -fsanitize=thread) -target_link_options(${PROJECT_NAME} PRIVATE -fsanitize=thread) +# target_compile_options(${PROJECT_NAME} PRIVATE -fsanitize=thread) +# target_link_options(${PROJECT_NAME} PRIVATE -fsanitize=thread) add_subdirectory(bench) add_subdirectory(tests) \ No newline at end of file diff --git a/bench/CMakeLists.txt b/bench/CMakeLists.txt index 2d3a969..d389f97 100644 --- a/bench/CMakeLists.txt +++ b/bench/CMakeLists.txt @@ -12,5 +12,5 @@ target_link_libraries(${NAME} PRIVATE ${PROJECT_NAME} ) -target_compile_options(${NAME} PRIVATE -fsanitize=thread) -target_link_options(${NAME} PRIVATE -fsanitize=thread) \ No newline at end of file +# target_compile_options(${NAME} PRIVATE -fsanitize=thread) +# target_link_options(${NAME} PRIVATE -fsanitize=thread) \ No newline at end of file diff --git a/include/logger.hh b/include/logger.hh index 91a542e..cb38195 100644 --- a/include/logger.hh +++ b/include/logger.hh @@ -36,12 +36,15 @@ class Logger { template >> void add(const std::string& field, Metric metric) { - std::shared_ptr locked = active.load(std::memory_order_acquire); + refs.fetch_add(1, std::memory_order_release); + map_type* locked = active.load(std::memory_order_acquire); auto it = locked->find(field); if (it == locked->end()) { + refs.fetch_sub(1, std::memory_order_release); throw configErrorMsg; // additional 30ns on bench ? } it->second = metric; + refs.fetch_sub(1, std::memory_order_release); } bool isConfigured() { return configured == CONFIGURED; } @@ -51,10 +54,10 @@ class Logger { enum Configuration { NOT_CONFIGURED, CONFIG_IN_PROGRESS, CONFIGURED }; std::atomic configured{NOT_CONFIGURED}; std::unique_ptr worker; - std::shared_ptr m1, m2; - std::atomic> active; // impl may use mutex! - // std::shared_ptr active; // data race without atomic on swap - // operation + std::unique_ptr m1, m2; + std::atomic active; // impl may use mutex! + std::atomic refs{0}; // degradation on worker side (waiting for no + // one to be in refs section) }; } // namespace vptyp \ No newline at end of file diff --git a/src/logger.cc b/src/logger.cc index c8c0a0b..c606400 100644 --- a/src/logger.cc +++ b/src/logger.cc @@ -15,18 +15,18 @@ bool Logger::configure(const std::vector& d) { m1_ref[key] = 0; } m2_ref = m1_ref; - active = m1; + active.store(m1.get()); configured.store(CONFIGURED); return true; } Logger::Logger() - : m1(std::make_shared()), m2(std::make_shared()) { + : m1(std::make_unique()), m2(std::make_unique()) { worker = std::make_unique(*this, std::cout); } Logger::Logger(std::ostream& out) - : m1(std::make_shared()), m2(std::make_shared()) { + : m1(std::make_unique()), m2(std::make_unique()) { worker = std::make_unique(*this, out); } @@ -68,26 +68,24 @@ void Logger::Worker::unroll() { if (!parent.isConfigured()) return; - auto tmp = parent.active.load(std::memory_order_relaxed); - auto toBeActive = tmp == parent.m1 ? parent.m2 : parent.m1; + auto tmp = parent.active.load(std::memory_order_acquire); + auto toBeActive = tmp == parent.m1.get() ? parent.m2.get() : parent.m1.get(); parent.active.store(toBeActive, std::memory_order_release); - // hmm, seems that we can receive situation here there use_count is less or - // equal 2 but in reality we still have instance how? store and load is - // tighted, so we have guarantee that this check will be happens before - while (tmp.use_count() > 2) { + // so we setting up happens before relation with counters + while (parent.refs.load(std::memory_order_acquire) > 0) { std::this_thread::yield(); } - // it's needed thread fence to guarantee use count change - // __tsan_acquire(tmp.use_count()); - std::atomic_thread_fence(std::memory_order_acquire); + // // it's needed thread fence to guarantee use count change + // // __tsan_acquire(tmp.use_count()); + // std::atomic_thread_fence(std::memory_order_acquire); // at this place we are guarantee that tmp is only ours or not? std::string output; bool haveToPush{false}; - for (auto& element : *tmp.get()) { + for (auto& element : *tmp) { if (!std::visit([](auto&& i) -> bool { return i; }, element.second)) continue; std::string value = diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 53d7714..4d806a7 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -12,5 +12,5 @@ target_link_libraries(${NAME} PRIVATE ${PROJECT_NAME} ) -target_compile_options(${NAME} PRIVATE -fsanitize=thread) -target_link_options(${NAME} PRIVATE -fsanitize=thread) \ No newline at end of file +# target_compile_options(${NAME} PRIVATE -fsanitize=thread) +# target_link_options(${NAME} PRIVATE -fsanitize=thread) \ No newline at end of file