diff --git a/src/all_cases/all_cases.cc b/src/all_cases/all_cases.cc index 1b8e779..0ee0b07 100644 --- a/src/all_cases/all_cases.cc +++ b/src/all_cases/all_cases.cc @@ -1,47 +1,51 @@ #include "common.h" #include "all_cases.h" -std::mutex AllCases::all_cases_building; -bool AllCases::all_cases_available = false; -std::vector AllCases::all_cases[]; +std::mutex AllCases::building; +bool AllCases::available = false; +std::vector AllCases::data[]; AllCases::Status AllCases::status() { // get all cases status - if (all_cases_available) { + if (AllCases::available) { return AVAILABLE; // all cases already built } - if (!all_cases_building.try_lock()) { // fail to lock mutex -> another thread working - return BUILDING; + if (!AllCases::building.try_lock()) { // fail to lock mutex + return BUILDING; // another thread working } - all_cases_building.unlock(); // release mutex + AllCases::building.unlock(); // release mutex return NO_INIT; } -const std::vector (*AllCases::fetch())[16] { // get const ptr of all cases - if (status() != AllCases::AVAILABLE) { +const std::vector (*AllCases::fetch())[16] { // get all cases content + if (status() != AVAILABLE) { AllCases::build(); // all cases initialize } - return &all_cases; // return ptr + return &AllCases::data; // return const ptr } -void AllCases::build() { // build all cases - if (AllCases::all_cases_available) { - return; // all cases already built +void AllCases::build() { // ensure that all cases available + if (!AllCases::available) { + if (AllCases::building.try_lock()) { // mutex lock success + build_data(); // start build process + AllCases::available = true; // set available flag + } else { + AllCases::building.lock(); // blocking waiting + } + AllCases::building.unlock(); } - if (AllCases::all_cases_building.try_lock()) { // lock success -> start building +} + +void AllCases::build_data() { // find all cases + for (uint32_t head = 0; head < 16; ++head) { // address of 2x2 block + if ((head & 0b11) == 0b11) { + continue; // invalid 2x2 address + } /// head -> 0/1/2 / 4/5/6 / 8/9/10 / 12/13/14 - for (uint32_t head = 0; head < 16; ++head) { // address of 2x2 block - if ((head & 0b11) == 0b11) { - continue; // invalid 2x2 address - } - for (uint32_t const &range : *BasicRanges::fetch()) { // check base on 2x2 address and range - if (Common::check_case(head, range)) { - all_cases[head].emplace_back(Common::range_reverse(range)); // found valid case - } + data[head].reserve(ALL_CASES_SIZE[head]); // memory pre-allocated + for (auto const &range : *BasicRanges::fetch()) { // check base on 2x2 address and range + if (Common::check_case(head, range)) { + data[head].emplace_back(Common::range_reverse(range)); // found valid case } } - AllCases::all_cases_available = true; // set available flag - } else { // another thread building - AllCases::all_cases_building.lock(); // blocking waiting } - AllCases::all_cases_building.unlock(); } diff --git a/src/all_cases/all_cases.h b/src/all_cases/all_cases.h index db42833..d8b6b19 100644 --- a/src/all_cases/all_cases.h +++ b/src/all_cases/all_cases.h @@ -5,6 +5,13 @@ #include #include "basic_ranges.h" +const uint32_t ALL_CASES_SIZE[16] = { + 2942906, 2260392, 2942906, 0, + 2322050, 1876945, 2322050, 0, + 2322050, 1876945, 2322050, 0, + 2942906, 2260392, 2942906, 0, +}; + class AllCases : public BasicRanges { public: static void build(); @@ -12,7 +19,9 @@ public: static const std::vector (*fetch())[16]; private: - static bool all_cases_available; - static std::mutex all_cases_building; - static std::vector all_cases[16]; + static bool available; + static std::mutex building; + static std::vector data[16]; + + static void build_data(); }; diff --git a/src/all_cases/basic_ranges.cc b/src/all_cases/basic_ranges.cc index 6d1ab7c..9e22677 100644 --- a/src/all_cases/basic_ranges.cc +++ b/src/all_cases/basic_ranges.cc @@ -26,7 +26,7 @@ BasicRanges::Status BasicRanges::status() { // get basic ranges status return NO_INIT; } -const std::vector* BasicRanges::fetch() { // get const ptr of basic ranges +const std::vector* BasicRanges::fetch() { // get basic ranges content if (status() != AVAILABLE) { BasicRanges::build(); // basic ranges initialize } @@ -46,7 +46,7 @@ void BasicRanges::build() { // ensure that basic ranges available } void BasicRanges::build_data() { // build basic ranges - BasicRanges::data.reserve(DATA_SIZE); // pre-allocated memory + BasicRanges::data.reserve(BASIC_RANGES_SIZE); // memory pre-allocated 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) diff --git a/src/all_cases/basic_ranges.h b/src/all_cases/basic_ranges.h index d00248f..9ed202b 100644 --- a/src/all_cases/basic_ranges.h +++ b/src/all_cases/basic_ranges.h @@ -4,6 +4,8 @@ #include #include +const uint32_t BASIC_RANGES_SIZE = 7311921; + class BasicRanges { public: enum Status { @@ -19,7 +21,6 @@ private: 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 8873791..59884eb 100644 --- a/src/main.cc +++ b/src/main.cc @@ -209,10 +209,19 @@ int main() { // } - BasicRanges::build(); +// BasicRanges::build(); // for (auto const &range : *BasicRanges::fetch()) { // printf("%08X\n", range); +// } + + AllCases::build(); + +// for (uint32_t head = 0; head < 16; ++head) { +// uint64_t prefix = (uint64_t)head << 32; +// for (auto const &range : (*AllCases::fetch())[head]) { +// printf("%09lX\n", prefix | range); +// } // } std::cout << (clock() - start_time) * 1000 / CLOCKS_PER_SEC << "ms" << std::endl;