diff --git a/src/all_cases/basic_ranges.cc b/src/all_cases/basic_ranges.cc index cca1948..6d1ab7c 100644 --- a/src/all_cases/basic_ranges.cc +++ b/src/all_cases/basic_ranges.cc @@ -2,9 +2,9 @@ #include "common.h" #include "basic_ranges.h" -std::mutex BasicRanges::basic_ranges_building; -std::vector BasicRanges::basic_ranges; -bool BasicRanges::basic_ranges_available = false; +std::mutex BasicRanges::building; +bool BasicRanges::available = false; +std::vector BasicRanges::data; inline uint32_t binary_count(uint32_t bin) { // get number of non-zero bits bin -= (bin >> 1) & 0x55555555; @@ -16,50 +16,54 @@ inline uint32_t binary_count(uint32_t bin) { // get number of non-zero bits } BasicRanges::Status BasicRanges::status() { // get basic ranges status - if (basic_ranges_available) { + if (BasicRanges::available) { return AVAILABLE; // basic ranges already built } - if (!basic_ranges_building.try_lock()) { // fail to lock mutex -> another thread working - return BUILDING; + if (!BasicRanges::building.try_lock()) { // fail to lock mutex + return BUILDING; // another thread working } - basic_ranges_building.unlock(); // release mutex + BasicRanges::building.unlock(); // release mutex return NO_INIT; } const std::vector* BasicRanges::fetch() { // get const ptr of basic ranges - if (status() != BasicRanges::AVAILABLE) { + if (status() != AVAILABLE) { BasicRanges::build(); // basic ranges initialize } - return &basic_ranges; // return ptr + return &BasicRanges::data; // return const ptr } -void BasicRanges::build() { // build basic ranges - if (basic_ranges_available) { - return; // basic ranges already built +void BasicRanges::build() { // ensure that basic ranges available + if (!BasicRanges::available) { + if (BasicRanges::building.try_lock()) { // mutex lock success + build_data(); // start build process + BasicRanges::available = true; // set available flag + } else { + BasicRanges::building.lock(); // blocking waiting + } + BasicRanges::building.unlock(); // release mutex } - if (basic_ranges_building.try_lock()) { // lock success -> start building - /// 0x0 -> 00 | 1x2 -> 01 | 2x1 -> 10 | 1x1 -> 11 - for (int n = 0; n <= 7; ++n) { // number of 1x2 and 2x1 block -> 0 ~ 7 - for (int n_2x1 = 0; n_2x1 <= n; ++n_2x1) { // number of 2x1 block -> 0 ~ n - for (int n_1x1 = 0; n_1x1 <= (14 - n * 2); ++n_1x1) { // number of 1x1 block -> 0 ~ (14 - 2n) - int n_1x2 = n - n_2x1; - int n_space = 16 - n * 2 - n_1x1; - generate_ranges(n_space, n_1x2, n_2x1, n_1x1); // generate target ranges - } +} + +void BasicRanges::build_data() { // build basic ranges + BasicRanges::data.reserve(DATA_SIZE); // pre-allocated memory + for (int n = 0; n <= 7; ++n) { // number of 1x2 and 2x1 block -> 0 ~ 7 + for (int n_2x1 = 0; n_2x1 <= n; ++n_2x1) { // number of 2x1 block -> 0 ~ n + for (int n_1x1 = 0; n_1x1 <= (14 - n * 2); ++n_1x1) { // number of 1x1 block -> 0 ~ (14 - 2n) + int n_1x2 = n - n_2x1; + int n_space = 16 - n * 2 - n_1x1; + generate(n_space, n_1x2, n_2x1, n_1x1); // generate target ranges + /// 0x0 -> 00 | 1x2 -> 01 | 2x1 -> 10 | 1x1 -> 11 } } - std::sort(basic_ranges.begin(), basic_ranges.end()); // sort basic ranges - for (uint32_t &range : basic_ranges) { - range = Common::range_reverse(range); // basic ranges reverse - } - basic_ranges_available = true; // set available flag - } else { // another thread building - basic_ranges_building.lock(); // blocking waiting } - basic_ranges_building.unlock(); + std::sort(BasicRanges::data.begin(), BasicRanges::data.end()); // sort basic ranges + for (auto &range : BasicRanges::data) { + range = Common::range_reverse(range); // basic ranges reverse + } } -void BasicRanges::generate_ranges(int n1, int n2, int n3, int n4) { // generate specific basic ranges +void BasicRanges::generate(int n1, int n2, int n3, int n4) { // generate specific basic ranges int len, limit; constexpr uint32_t MASK_01 = 0b01 << 30; constexpr uint32_t MASK_10 = 0b10 << 30; @@ -118,7 +122,7 @@ void BasicRanges::generate_ranges(int n1, int n2, int n3, int n4) { // generate (range >>= 2) |= base & MASK_11; base <<= 2; } - basic_ranges.emplace_back(range); // insert into release + BasicRanges::data.emplace_back(range); // insert into release data } } } diff --git a/src/all_cases/basic_ranges.h b/src/all_cases/basic_ranges.h index c81d755..d00248f 100644 --- a/src/all_cases/basic_ranges.h +++ b/src/all_cases/basic_ranges.h @@ -16,8 +16,11 @@ public: static const std::vector* fetch(); private: - static bool basic_ranges_available; - static std::mutex basic_ranges_building; - static std::vector basic_ranges; - static void generate_ranges(int n1, int n2, int n3, int n4); + static bool available; + static std::mutex building; + static std::vector data; + static const uint32_t DATA_SIZE = 7311921; + + static void build_data(); + static void generate(int n1, int n2, int n3, int n4); }; diff --git a/src/main.cc b/src/main.cc index 5e294bc..8873791 100644 --- a/src/main.cc +++ b/src/main.cc @@ -193,8 +193,8 @@ int main() { // } // } - auto raw_code = CommonCode("1a9bf0c").to_raw_code().unwrap(); - std::cout << fast_cal(raw_code) << std::endl; +// auto raw_code = CommonCode("1a9bf0c").to_raw_code().unwrap(); +// std::cout << fast_cal(raw_code) << std::endl; // int sum = 0; // for (auto const &raw_code : all_cases_raw) { @@ -209,8 +209,17 @@ int main() { // } - std::cout << (clock() - start_time) * 1000000 / CLOCKS_PER_SEC << "us" << std::endl; + BasicRanges::build(); + +// for (auto const &range : *BasicRanges::fetch()) { +// printf("%08X\n", range); +// } + + std::cout << (clock() - start_time) * 1000 / CLOCKS_PER_SEC << "ms" << std::endl; +// std::cout << (clock() - start_time) * 1000000 / CLOCKS_PER_SEC << "us" << std::endl; // std::cout << "complete benchmark" << std::endl; +// while(1); + return 0; }