From 87c903ff3d60d3931640a97addc72fc2a54f6c8f Mon Sep 17 00:00:00 2001 From: Stepan Fomenko Date: Mon, 13 Jul 2020 16:07:00 +0300 Subject: [PATCH] Refactor sm::block --- CMakeLists.txt | 2 +- experiments/block_choice.cpp | 62 +++-------------------------------- sm/block.h | 63 ++++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 59 deletions(-) create mode 100644 sm/block.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 4a59a04..97882d3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ else() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -fPIC") endif() -include_directories(experiments ${PIP_INCLUDES}) +include_directories(experiments ${PIP_INCLUDES} ${PROJECT_SOURCE_DIR}) if(WIN32) include_directories(can) diff --git a/experiments/block_choice.cpp b/experiments/block_choice.cpp index 2d2bea7..4576979 100644 --- a/experiments/block_choice.cpp +++ b/experiments/block_choice.cpp @@ -1,11 +1,9 @@ -#include +#include "sm/block.h" #include #include #include #include -#include -#include -#include + #define assert(_Expression) \ (void) \ @@ -20,33 +18,6 @@ void _assert (const char *_Message, const char *_File, unsigned _Line) { std::atomic_flag is_calc_barrier = ATOMIC_FLAG_INIT; PIVector is_calc_statuses; -namespace sm { - struct block { - PIVector input_blocks; - PIVector output_blocks; - std::atomic_flag barrier = ATOMIC_FLAG_INIT; - const int is_calc_idx; - const std::chrono::microseconds calc_time; - - static std::chrono::microseconds random_time() { - float val = powf(rand() % 1000 / 1000.f, 20.f) * 30.f * 1000.f; -// std::cout << int(val) << std::endl; - return std::chrono::microseconds(int(val)); - } - - explicit block(const int is_calc_idx) : is_calc_idx(is_calc_idx), calc_time(random_time()) {} - - void calc() { - std::this_thread::sleep_for(calc_time); - } - }; - - struct time_report { - double calc_time_ms; - double sync_time_ms; - }; -} - void link(sm::block* out, sm::block* in) { out->output_blocks.push_back(in); in->input_blocks.push_back(out); @@ -126,31 +97,6 @@ void scheme_clear_calc_statuses(PIVector& start_blocks) { is_calc_statuses.forEachInplace([](bool is_calced){ return false; }); } -void unlock(sm::block* block, int locks_count = -1) { - if (locks_count == -1) locks_count = block->input_blocks.size(); - for (int i = 0; i < locks_count; ++i) { - block->input_blocks[i]->barrier.clear(std::memory_order_release); - } - block->barrier.clear(std::memory_order_release); -} - -bool try_lock(sm::block* block) { - if (block->barrier.test_and_set(std::memory_order_acquire)) return false; - - int locks_count = 0; - for (auto & input_block : block->input_blocks) { - if (input_block->barrier.test_and_set(std::memory_order_acquire)) break; - locks_count++; - } - - if (locks_count == block->input_blocks.size()) { - return true; - } else { - unlock(block, locks_count); - return false; - } -} - sm::block* try_lock_next_and_post(std::atomic_flag& block_pool_flag, PIVector& block_pool, bool& is_block_pool_empty, PIVector& new_available_blocks) { while(block_pool_flag.test_and_set(std::memory_order_acquire)) { std::this_thread::yield(); @@ -164,7 +110,7 @@ sm::block* try_lock_next_and_post(std::atomic_flag& block_pool_flag, PIVectortry_lock()) { block = block_pool[i]; block_pool.remove(i); // std::cout << block->is_calc_idx << ": locked for calc" << std::endl; @@ -243,7 +189,7 @@ sm::time_report algorithm_runnable(std::atomic_flag& block_pool_flag, block->calc(); auto end = std::chrono::high_resolution_clock::now(); calc_time += std::chrono::duration_cast(end - start).count() / 1000.; - unlock(block); + block->unlock(); post_available_blocks(block, new_available_blocks); } diff --git a/sm/block.h b/sm/block.h new file mode 100644 index 0000000..8525337 --- /dev/null +++ b/sm/block.h @@ -0,0 +1,63 @@ +#ifndef MULTITHREAD_EXPERIMENTS_BLOCK_H +#define MULTITHREAD_EXPERIMENTS_BLOCK_H + +#include +#include +#include +#include + +namespace sm { + + struct block { + PIVector input_blocks; + PIVector output_blocks; + std::atomic_flag barrier = ATOMIC_FLAG_INIT; + const int is_calc_idx; + const std::chrono::microseconds calc_time; + + static std::chrono::microseconds random_time() { + float val = powf(rand() % 1000 / 1000.f, 20.f) * 30.f * 1000.f; +// std::cout << int(val) << std::endl; + return std::chrono::microseconds(int(val)); + } + + explicit block(const int is_calc_idx) : is_calc_idx(is_calc_idx), calc_time(random_time()) {} + + void calc() { + std::this_thread::sleep_for(calc_time); + } + + void unlock(int locks_count = -1) { + if (locks_count == -1) locks_count = this->input_blocks.size(); + for (int i = 0; i < locks_count; ++i) { + this->input_blocks[i]->barrier.clear(std::memory_order_release); + } + this->barrier.clear(std::memory_order_release); + } + + bool try_lock() { + if (this->barrier.test_and_set(std::memory_order_acquire)) return false; + + int locks_count = 0; + for (auto & input_block : this->input_blocks) { + if (input_block->barrier.test_and_set(std::memory_order_acquire)) break; + locks_count++; + } + + if (locks_count == this->input_blocks.size()) { + return true; + } else { + unlock(locks_count); + return false; + } + } + }; + + struct time_report { + double calc_time_ms; + double sync_time_ms; + }; + +} + +#endif //MULTITHREAD_EXPERIMENTS_BLOCK_H