Browse Source

update: adjust coding style for AllCases

master
Dnomd343 9 months ago
parent
commit
f09c8b2c2f
  1. 53
      src/core/all_cases/all_cases.cc
  2. 76
      src/core/all_cases/all_cases.h
  3. 29
      src/core/all_cases/basic_ranges.cc
  4. 22
      src/core/ffi/all_cases.cc
  5. 4
      src/core/short_code/convert.cc
  6. 11
      src/core_test/CMakeLists.txt
  7. 97
      src/core_test/cases/all_cases.cc
  8. 86
      src/core_test/ffi/all_cases.cc

53
src/core/all_cases/all_cases.cc

@ -5,7 +5,7 @@ namespace klotski {
namespace cases {
/// Calculate all possible klotski heads.
static consteval std::array<int, 12> case_heads() {
consteval static std::array<int, 12> case_heads() {
std::array<int, 12> heads = {};
for (int i = 0, head = 0; head < 15; ++head) {
if (head % 4 != 3) {
@ -17,12 +17,12 @@ static consteval std::array<int, 12> case_heads() {
/// Check whether the combination of head and range is valid.
static int check_range(int head, uint32_t range) noexcept {
constexpr uint32_t MASK_1x1 = 0b00000001;
constexpr uint32_t MASK_1x2 = 0b00000011;
constexpr uint32_t MASK_2x1 = 0b00010001;
constexpr uint32_t MASK_2x2 = 0b00110011;
constexpr uint32_t M_1x1 = 0b00000001;
constexpr uint32_t M_1x2 = 0b00000011;
constexpr uint32_t M_2x1 = 0b00010001;
constexpr uint32_t M_2x2 = 0b00110011;
uint32_t flags = MASK_2x2 << head; // fill 2x2 block
uint32_t flags = M_2x2 << head; // fill 2x2 block
for (int addr = 0, offset = 1; range; range >>= 2, ++offset) { // traverse every 2-bit
auto num = low_zero_num(~flags);
addr += num; // next unfilled block
@ -30,19 +30,19 @@ static int check_range(int head, uint32_t range) noexcept {
switch (range & 0b11) {
case 0b00: // space
case 0b11: // 1x1 block
flags |= MASK_1x1;
flags |= M_1x1;
continue;
case 0b10: // 2x1 block
if ((flags >> 4) & 0b1 || addr > 15) { // invalid case
return offset; // broken offset
}
flags |= MASK_2x1;
flags |= M_2x1;
continue;
case 0b01: // 1x2 block
if ((flags >> 1) & 0b1 || (addr & 0b11) == 0b11) { // invalid case
return offset; // broken offset
}
flags |= MASK_1x2;
flags |= M_1x2;
continue;
}
}
@ -50,10 +50,10 @@ static int check_range(int head, uint32_t range) noexcept {
}
/// Build all valid ranges of the specified head.
void AllCases::BuildCases(int head, Ranges &release) noexcept {
void AllCases::build_cases(int head, Ranges &release) noexcept {
release.clear();
release.reserve(ALL_CASES_NUM[head]);
auto &basic_ranges = BasicRanges::Instance().Fetch();
auto &basic_ranges = BasicRanges::instance().fetch();
for (uint32_t index = 0; index < basic_ranges.size(); ++index) {
auto offset = check_range(head, basic_ranges[index]);
if (offset) { // invalid case
@ -71,14 +71,14 @@ void AllCases::BuildCases(int head, Ranges &release) noexcept {
}
/// Execute the build process and ensure thread safety.
void AllCases::Build() noexcept {
BuildParallel([](auto &&func) {
void AllCases::build() noexcept {
build_parallel([](auto &&func) {
func();
});
}
/// Execute the build process with parallel support and ensure thread safety.
void AllCases::BuildParallel(Executor &&executor) noexcept {
void AllCases::build_parallel(Executor &&executor) noexcept {
if (available_) {
return; // reduce consumption of mutex
}
@ -93,7 +93,7 @@ void AllCases::BuildParallel(Executor &&executor) noexcept {
auto promise = std::make_shared<std::promise<void>>();
futures.emplace_back(promise->get_future());
executor([head, promise = std::move(promise)]() {
BuildCases(head, GetCases()[head]);
build_cases(head, get_cases()[head]);
promise->set_value(); // subtask completed notification
});
}
@ -104,7 +104,7 @@ void AllCases::BuildParallel(Executor &&executor) noexcept {
}
/// Execute the build process in parallel without blocking.
void AllCases::BuildParallelAsync(Executor &&executor, Notifier &&callback) noexcept {
void AllCases::build_parallel_async(Executor &&executor, Notifier &&callback) noexcept {
if (available_) {
callback();
return; // reduce consumption of mutex
@ -119,7 +119,7 @@ void AllCases::BuildParallelAsync(Executor &&executor, Notifier &&callback) noex
auto all_done = std::make_shared<Notifier>(std::move(callback));
for (auto head : case_heads()) {
executor([this, head, counter, all_done]() {
BuildCases(head, GetCases()[head]);
build_cases(head, get_cases()[head]);
if (counter->fetch_add(1) == case_heads().size() - 1) { // all tasks done
available_ = true;
building_.unlock(); // release building mutex
@ -129,24 +129,5 @@ void AllCases::BuildParallelAsync(Executor &&executor, Notifier &&callback) noex
}
}
RangesUnion& AllCases::GetCases() noexcept {
static RangesUnion cases;
return cases;
}
AllCases& AllCases::Instance() noexcept {
static AllCases instance;
return instance;
}
const RangesUnion& AllCases::Fetch() noexcept {
this->Build();
return GetCases();
}
bool AllCases::IsAvailable() const noexcept {
return available_;
}
} // namespace cases
} // namespace klotski

76
src/core/all_cases/all_cases.h

@ -53,6 +53,8 @@ typedef std::array<Ranges, 16> RangesUnion;
typedef std::function<void()> Notifier;
typedef std::function<void(std::function<void()>&&)> Executor;
// ----------------------------------------------------------------------------------------- //
constexpr auto BASIC_RANGES_NUM = 7311921;
constexpr std::array<int, 16> ALL_CASES_NUM {
@ -66,45 +68,89 @@ constexpr auto ALL_CASES_NUM_ = std::accumulate(
ALL_CASES_NUM.begin(), ALL_CASES_NUM.end(), 0
);
// ----------------------------------------------------------------------------------------- //
class BasicRanges {
public:
void Build() noexcept;
const Ranges& Fetch() noexcept;
[[nodiscard]] bool IsAvailable() const noexcept;
void build() noexcept;
const Ranges& fetch() noexcept;
[[nodiscard]] bool is_available() const noexcept;
DISALLOW_COPY_AND_ASSIGN(BasicRanges);
static BasicRanges& Instance() noexcept;
static BasicRanges& instance() noexcept;
private:
std::mutex building_;
bool available_ = false;
BasicRanges() = default;
static Ranges& GetRanges() noexcept;
static void BuildRanges(Ranges &ranges) noexcept;
static void SpawnRanges(Ranges &ranges, int, int, int, int) noexcept;
static Ranges& get_ranges() noexcept;
static void build_ranges(Ranges &ranges) noexcept;
static void spawn_ranges(Ranges &ranges, int, int, int, int) noexcept;
};
inline BasicRanges& BasicRanges::instance() noexcept {
static BasicRanges instance;
return instance;
}
inline Ranges& BasicRanges::get_ranges() noexcept {
static Ranges ranges;
return ranges;
}
inline const Ranges& BasicRanges::fetch() noexcept {
this->build();
return get_ranges();
}
inline bool BasicRanges::is_available() const noexcept {
return available_; // no mutex required in one-way state
}
// ----------------------------------------------------------------------------------------- //
class AllCases {
public:
void Build() noexcept;
void BuildParallel(Executor &&executor) noexcept;
void BuildParallelAsync(Executor &&executor, Notifier &&callback) noexcept;
void build() noexcept;
void build_parallel(Executor &&executor) noexcept;
void build_parallel_async(Executor &&executor, Notifier &&callback) noexcept;
const RangesUnion& Fetch() noexcept;
[[nodiscard]] bool IsAvailable() const noexcept;
const RangesUnion& fetch() noexcept;
[[nodiscard]] bool is_available() const noexcept;
DISALLOW_COPY_AND_ASSIGN(AllCases);
static AllCases& Instance() noexcept;
static AllCases& instance() noexcept;
private:
std::mutex building_;
bool available_ = false;
AllCases() = default;
static RangesUnion& GetCases() noexcept;
static void BuildCases(int head, Ranges &release) noexcept;
static RangesUnion& get_cases() noexcept;
static void build_cases(int head, Ranges &release) noexcept;
};
inline AllCases& AllCases::instance() noexcept {
static AllCases instance;
return instance;
}
inline RangesUnion& AllCases::get_cases() noexcept {
static RangesUnion cases;
return cases;
}
inline const RangesUnion& AllCases::fetch() noexcept {
this->build();
return get_cases();
}
inline bool AllCases::is_available() const noexcept {
return available_; // no mutex required in one-way state
}
// ----------------------------------------------------------------------------------------- //
} // namespace cases
} // namespace klotski

29
src/core/all_cases/basic_ranges.cc

@ -39,7 +39,7 @@ static void combine_sort(RangeIter begin, RangeIter mid, RangeIter end) noexcept
}
/// Spawn all ranges of specified conditions.
void BasicRanges::SpawnRanges(Ranges &ranges, int n1, int n2, int n3, int n4) noexcept {
void BasicRanges::spawn_ranges(Ranges &ranges, int n1, int n2, int n3, int n4) noexcept {
auto num = n1 + n2 + n3 + n4;
auto offset = (16 - num) << 1; // offset of low bits
@ -59,13 +59,13 @@ void BasicRanges::SpawnRanges(Ranges &ranges, int n1, int n2, int n3, int n4) no
}
/// Search and sort all possible basic-ranges permutations.
void BasicRanges::BuildRanges(Ranges &ranges) noexcept {
void BasicRanges::build_ranges(Ranges &ranges) noexcept {
ranges.clear();
ranges.reserve(BASIC_RANGES_NUM);
std::list<RangeIter> flags {ranges.begin()}; // mark ordered interval
for (auto &t : range_types()) {
SpawnRanges(ranges, std::get<0>(t), std::get<1>(t), std::get<2>(t), std::get<3>(t));
spawn_ranges(ranges, std::get<0>(t), std::get<1>(t), std::get<2>(t), std::get<3>(t));
flags.emplace_back(ranges.end());
}
do {
@ -83,7 +83,7 @@ void BasicRanges::BuildRanges(Ranges &ranges) noexcept {
}
/// Execute the build process and ensure thread safety.
void BasicRanges::Build() noexcept {
void BasicRanges::build() noexcept {
if (available_) {
return; // reduce consumption of mutex
}
@ -91,28 +91,9 @@ void BasicRanges::Build() noexcept {
if (available_) {
return; // data is already available
}
BuildRanges(GetRanges());
build_ranges(get_ranges());
available_ = true;
}
Ranges& BasicRanges::GetRanges() noexcept {
static Ranges ranges;
return ranges;
}
BasicRanges& BasicRanges::Instance() noexcept {
static BasicRanges instance;
return instance;
}
const Ranges& BasicRanges::Fetch() noexcept {
this->Build();
return GetRanges();
}
bool BasicRanges::IsAvailable() const noexcept {
return available_; // no mutex required in one-way state
}
} // namespace cases
} // namespace klotski

22
src/core/ffi/all_cases.cc

@ -6,7 +6,7 @@ using klotski::cases::BasicRanges;
using klotski::cases::ALL_CASES_NUM;
void all_cases_prebuild() {
BasicRanges::Instance().Build();
BasicRanges::instance().build();
}
void all_cases_prebuild_async(executor_t executor, notifier_t callback) {
@ -17,15 +17,11 @@ void all_cases_prebuild_async(executor_t executor, notifier_t callback) {
}
int all_cases_prebuild_available() {
if (BasicRanges::Instance().IsAvailable()) {
return KLOTSKI_TRUE;
} else {
return KLOTSKI_FALSE;
}
return BasicRanges::instance().is_available() ? KLOTSKI_TRUE : KLOTSKI_FALSE;
}
void all_cases_build() {
AllCases::Instance().Build();
AllCases::instance().build();
}
void all_cases_build_async(executor_t executor, notifier_t callback) {
@ -37,7 +33,7 @@ void all_cases_build_async(executor_t executor, notifier_t callback) {
void all_cases_build_parallel(executor_t executor) {
typedef std::function<void()> Runner;
AllCases::Instance().BuildParallel([executor](Runner &&runner) {
AllCases::instance().build_parallel([executor](Runner &&runner) {
executor([](void *fn) {
(*(Runner*)fn)();
delete (Runner*)fn;
@ -50,7 +46,7 @@ void all_cases_build_parallel_async(executor_t executor, notifier_t callback) {
auto all_done = [callback]() {
callback();
};
AllCases::Instance().BuildParallelAsync([executor](Runner &&runner) {
AllCases::instance().build_parallel_async([executor](Runner &&runner) {
executor([](void *fn) {
(*(Runner*)fn)();
delete (Runner*)fn;
@ -59,11 +55,7 @@ void all_cases_build_parallel_async(executor_t executor, notifier_t callback) {
}
int all_cases_available() {
if (AllCases::Instance().IsAvailable()) {
return KLOTSKI_TRUE;
} else {
return KLOTSKI_FALSE;
}
return AllCases::instance().is_available() ? KLOTSKI_TRUE : KLOTSKI_FALSE;
}
int all_cases_num(int head) {
@ -77,5 +69,5 @@ const klotski_u32* all_cases_export(int head) {
if (all_cases_num(head) < 0) {
return nullptr;
}
return AllCases::Instance().Fetch()[head].data();
return AllCases::instance().fetch()[head].data();
}

4
src/core/short_code/convert.cc

@ -59,7 +59,7 @@ ShortCode ShortCode::from_common_code(CommonCode common_code) noexcept {
/// NOTE: ensure that input common code is valid!
uint32_t ShortCode::fast_encode(uint64_t common_code) noexcept { // common code --> short code
auto head = common_code >> 32; // head index
const auto &ranges = AllCases::Instance().Fetch()[head]; // available ranges
const auto &ranges = AllCases::instance().fetch()[head]; // available ranges
auto offset = std::lower_bound(ranges.begin(), ranges.end(), (uint32_t)common_code) - ranges.begin();
return ALL_CASES_OFFSET[head] + offset; // release short code
}
@ -70,7 +70,7 @@ uint64_t ShortCode::fast_decode(uint32_t short_code) noexcept { // short code --
ALL_CASES_OFFSET, ALL_CASES_OFFSET + 16, short_code
) - 1;
uint64_t head = offset - ALL_CASES_OFFSET; // head index
return (head << 32) | AllCases::Instance().Fetch()[head][short_code - *offset]; // release common code
return (head << 32) | AllCases::instance().fetch()[head][short_code - *offset]; // release common code
}
/// NOTE: ensure that input common code is valid!

11
src/core_test/CMakeLists.txt

@ -11,6 +11,7 @@ include_directories(utils)
include_directories(${KLOTSKI_ROOT}/src/core/ffi)
include_directories(${KLOTSKI_ROOT}/src/core/utils)
include_directories(${KLOTSKI_ROOT}/src/core/all_cases)
include_directories(${KLOTSKI_ROOT}/src/core/common_code)
###############################################################################################
@ -33,3 +34,13 @@ target_link_libraries(test_klotski_ffi PRIVATE ${KLOTSKI_TEST_DEPS})
add_test(NAME klotski_ffi COMMAND test_klotski_ffi)
###############################################################################################
set(KLOTSKI_TEST_CODEC_SRC
codec/common_code.cc
)
add_executable(test_klotski_codec ${KLOTSKI_TEST_CODEC_SRC})
target_link_libraries(test_klotski_codec PRIVATE ${KLOTSKI_TEST_DEPS})
add_test(NAME klotski_codec COMMAND test_klotski_codec)
###############################################################################################

97
src/core_test/cases/all_cases.cc

@ -27,24 +27,24 @@ PRIVATE_ACCESS(BasicRanges, available_, bool)
/// Reset basic ranges build state, note it is thread-unsafe.
void basic_ranges_reset() {
access_BasicRanges_available_(BasicRanges::Instance()) = false;
access_BasicRanges_available_(BasicRanges::instance()) = false;
}
/// Reset all cases build state, note it is thread-unsafe.
void all_cases_reset() {
access_AllCases_available_(AllCases::Instance()) = false;
access_AllCases_available_(AllCases::instance()) = false;
}
/// Verify that whether basic ranges data is correct.
void basic_ranges_verify() {
auto &basic_ranges = BasicRanges::Instance().Fetch();
auto &basic_ranges = BasicRanges::instance().fetch();
EXPECT_EQ(basic_ranges.size(), BASIC_RANGES_NUM); // verify basic ranges size
EXPECT_EQ(xxhsum(basic_ranges), BASIC_RANGES_XXHASH); // verify basic ranges checksum
}
/// Verify that whether all cases data is correct.
void all_cases_verify() {
auto &all_cases = AllCases::Instance().Fetch();
auto &all_cases = AllCases::instance().fetch();
for (int head = 0; head < 16; ++head) {
EXPECT_EQ(all_cases[head].size(), ALL_CASES_NUM[head]); // verify all cases size
}
@ -57,18 +57,18 @@ void all_cases_verify() {
std::string all_cases_xxh;
for (uint64_t head = 0; head < 16; ++head) {
all_cases_xxh += xxhsum(AllCases::Instance().Fetch()[head]);
all_cases_xxh += xxhsum(AllCases::instance().fetch()[head]);
}
EXPECT_EQ(xxhsum(all_cases_xxh), ALL_CASES_XXHASH); // verify all cases checksum
}
TEST(Cases, basic_ranges) {
basic_ranges_reset();
EXPECT_FALSE(BasicRanges::Instance().IsAvailable());
BasicRanges::Instance().Build();
EXPECT_TRUE(BasicRanges::Instance().IsAvailable());
BasicRanges::Instance().Build();
EXPECT_TRUE(BasicRanges::Instance().IsAvailable());
EXPECT_FALSE(BasicRanges::instance().is_available());
BasicRanges::instance().build();
EXPECT_TRUE(BasicRanges::instance().is_available());
BasicRanges::instance().build();
EXPECT_TRUE(BasicRanges::instance().is_available());
basic_ranges_verify();
}
@ -77,21 +77,21 @@ TEST(Cases, basic_ranges_mutex) {
BS::thread_pool pool(TEST_THREAD_NUM);
for (int i = 0; i < TEST_THREAD_NUM; ++i) {
auto _ = pool.submit(&BasicRanges::Build, &BasicRanges::Instance());
auto _ = pool.submit(&BasicRanges::build, &BasicRanges::instance());
}
EXPECT_FALSE(BasicRanges::Instance().IsAvailable());
EXPECT_FALSE(BasicRanges::instance().is_available());
pool.wait_for_tasks();
EXPECT_TRUE(BasicRanges::Instance().IsAvailable());
EXPECT_TRUE(BasicRanges::instance().is_available());
basic_ranges_verify();
}
TEST(Cases, all_cases) {
all_cases_reset();
EXPECT_FALSE(AllCases::Instance().IsAvailable());
AllCases::Instance().Build();
EXPECT_TRUE(AllCases::Instance().IsAvailable());
AllCases::Instance().Build();
EXPECT_TRUE(AllCases::Instance().IsAvailable());
EXPECT_FALSE(AllCases::instance().is_available());
AllCases::instance().build();
EXPECT_TRUE(AllCases::instance().is_available());
AllCases::instance().build();
EXPECT_TRUE(AllCases::instance().is_available());
all_cases_verify();
}
@ -100,26 +100,26 @@ TEST(Cases, all_cases_mutex) {
BS::thread_pool pool(TEST_THREAD_NUM);
for (int i = 0; i < TEST_THREAD_NUM; ++i) {
auto _ = pool.submit(&AllCases::Build, &AllCases::Instance());
auto _ = pool.submit(&AllCases::build, &AllCases::instance());
}
EXPECT_FALSE(AllCases::Instance().IsAvailable());
EXPECT_FALSE(AllCases::instance().is_available());
pool.wait_for_tasks();
EXPECT_TRUE(AllCases::Instance().IsAvailable());
EXPECT_TRUE(AllCases::instance().is_available());
all_cases_verify();
}
TEST(Cases, all_cases_parallel) {
all_cases_reset();
BS::thread_pool executor;
EXPECT_FALSE(AllCases::Instance().IsAvailable());
AllCases::Instance().BuildParallel([&executor](auto &&func) {
EXPECT_FALSE(AllCases::instance().is_available());
AllCases::instance().build_parallel([&executor](auto &&func) {
executor.push_task(func);
});
EXPECT_TRUE(AllCases::Instance().IsAvailable());
AllCases::Instance().BuildParallel([&executor](auto &&func) {
EXPECT_TRUE(AllCases::instance().is_available());
AllCases::instance().build_parallel([&executor](auto &&func) {
executor.push_task(func);
});
EXPECT_TRUE(AllCases::Instance().IsAvailable());
EXPECT_TRUE(AllCases::instance().is_available());
all_cases_verify();
}
@ -129,42 +129,43 @@ TEST(Cases, all_cases_parallel_mutex) {
BS::thread_pool pool(TEST_THREAD_NUM);
for (int i = 0; i < TEST_THREAD_NUM; ++i) {
auto _ = pool.submit(&AllCases::BuildParallel, &AllCases::Instance(), [&executor](auto &&func) {
auto _ = pool.submit(&AllCases::build_parallel, &AllCases::instance(), [&executor](auto &&func) {
executor.push_task(func);
});
}
EXPECT_FALSE(AllCases::Instance().IsAvailable());
EXPECT_FALSE(AllCases::instance().is_available());
pool.wait_for_tasks();
executor.wait_for_tasks();
EXPECT_TRUE(AllCases::Instance().IsAvailable());
EXPECT_TRUE(AllCases::instance().is_available());
all_cases_verify();
}
TEST(Cases, all_cases_async) {
all_cases_reset();
std::atomic_flag flag;
BS::thread_pool executor;
std::promise<void> promise_1;
auto future_1 = promise_1.get_future();
AllCases::Instance().BuildParallelAsync([&executor](auto &&func) {
flag.clear();
AllCases::instance().build_parallel_async([&executor](auto &&func) {
executor.push_task(func);
}, [&promise_1]() {
promise_1.set_value();
}, [&flag]() { // callback function
flag.test_and_set();
flag.notify_all();
});
EXPECT_FALSE(AllCases::Instance().IsAvailable());
future_1.wait();
EXPECT_TRUE(AllCases::Instance().IsAvailable());
EXPECT_FALSE(AllCases::instance().is_available());
flag.wait(false);
EXPECT_TRUE(AllCases::instance().is_available());
std::promise<void> promise_2;
auto future_2 = promise_2.get_future();
AllCases::Instance().BuildParallelAsync([&executor](auto &&func) {
flag.clear();
AllCases::instance().build_parallel_async([&executor](auto &&func) {
executor.push_task(func);
}, [&promise_2]() {
promise_2.set_value();
}, [&flag]() { // callback function
flag.test_and_set();
flag.notify_all();
});
EXPECT_TRUE(AllCases::Instance().IsAvailable());
future_2.wait();
EXPECT_TRUE(AllCases::Instance().IsAvailable());
EXPECT_TRUE(AllCases::instance().is_available());
flag.wait(false);
EXPECT_TRUE(AllCases::instance().is_available());
all_cases_verify();
}
@ -175,16 +176,16 @@ TEST(Cases, all_cases_async_mutex) {
BS::thread_pool pool(TEST_THREAD_NUM);
for (int i = 0; i < TEST_THREAD_NUM; ++i) {
auto _ = pool.submit(&AllCases::BuildParallelAsync, &AllCases::Instance(), [&executor](auto &&func) {
auto _ = pool.submit(&AllCases::build_parallel_async, &AllCases::instance(), [&executor](auto &&func) {
executor.push_task(func);
}, [&callback_num]() {
callback_num.fetch_add(1);
});
}
EXPECT_FALSE(AllCases::Instance().IsAvailable());
EXPECT_FALSE(AllCases::instance().is_available());
pool.wait_for_tasks();
executor.wait_for_tasks();
EXPECT_TRUE(AllCases::Instance().IsAvailable());
EXPECT_TRUE(AllCases::instance().is_available());
EXPECT_EQ(callback_num.load(), TEST_THREAD_NUM);
all_cases_verify();
}

86
src/core_test/ffi/all_cases.cc

@ -25,15 +25,15 @@ PRIVATE_ACCESS(BasicRanges, available_, bool)
/// Reset basic ranges build state, note it is thread-unsafe.
void basic_ranges_reset() {
access_BasicRanges_available_(BasicRanges::Instance()) = false;
access_BasicRanges_available_(BasicRanges::instance()) = false;
}
/// Reset all cases build state, note it is thread-unsafe.
void all_cases_reset() {
access_AllCases_available_(AllCases::Instance()) = false;
access_AllCases_available_(AllCases::instance()) = false;
}
TEST(FFI, all_cases_prebuild) {
TEST(AllCases, all_cases_prebuild) {
basic_ranges_reset();
EXPECT_FALSE(all_cases_prebuild_available());
all_cases_prebuild();
@ -42,36 +42,36 @@ TEST(FFI, all_cases_prebuild) {
EXPECT_TRUE(all_cases_prebuild_available());
}
TEST(FFI, all_cases_prebuild_async) {
TEST(AllCases, all_cases_prebuild_async) {
basic_ranges_reset();
static std::atomic_flag chan;
static std::atomic_flag flag;
chan.clear();
flag.clear();
all_cases_prebuild_async([](void (*fn)(void*), void *arg) {
std::thread worker(fn, arg);
worker.detach();
}, []() {
chan.test_and_set();
chan.notify_all();
}, []() { // callback function
flag.test_and_set();
flag.notify_all();
});
EXPECT_FALSE(all_cases_prebuild_available());
chan.wait(false);
flag.wait(false);
EXPECT_TRUE(all_cases_prebuild_available());
chan.clear();
flag.clear();
all_cases_prebuild_async([](void (*fn)(void*), void *arg) {
std::thread worker(fn, arg);
worker.detach();
}, []() {
chan.test_and_set();
chan.notify_all();
}, []() { // callback function
flag.test_and_set();
flag.notify_all();
});
EXPECT_TRUE(all_cases_prebuild_available());
chan.wait(false);
flag.wait(false);
EXPECT_TRUE(all_cases_prebuild_available());
}
TEST(FFI, all_cases_build) {
TEST(AllCases, all_cases_build) {
all_cases_reset();
EXPECT_FALSE(all_cases_available());
all_cases_build();
@ -80,36 +80,36 @@ TEST(FFI, all_cases_build) {
EXPECT_TRUE(all_cases_available());
}
TEST(FFI, all_cases_build_async) {
TEST(AllCases, all_cases_build_async) {
all_cases_reset();
static std::atomic_flag chan;
static std::atomic_flag flag;
chan.clear();
flag.clear();
all_cases_build_async([](void (*fn)(void*), void *arg) {
std::thread worker(fn, arg);
worker.detach();
}, []() {
chan.test_and_set();
chan.notify_all();
}, []() { // callback function
flag.test_and_set();
flag.notify_all();
});
EXPECT_FALSE(all_cases_available());
chan.wait(false);
flag.wait(false);
EXPECT_TRUE(all_cases_available());
chan.clear();
flag.clear();
all_cases_build_async([](void (*fn)(void*), void *arg) {
std::thread worker(fn, arg);
worker.detach();
}, []() {
chan.test_and_set();
chan.notify_all();
}, []() { // callback function
flag.test_and_set();
flag.notify_all();
});
EXPECT_TRUE(all_cases_available());
chan.wait(false);
flag.wait(false);
EXPECT_TRUE(all_cases_available());
}
TEST(FFI, all_cases_build_parallel) {
TEST(AllCases, all_cases_build_parallel) {
all_cases_reset();
EXPECT_FALSE(all_cases_available());
all_cases_build_parallel([](void (*fn)(void*), void *arg) {
@ -124,36 +124,36 @@ TEST(FFI, all_cases_build_parallel) {
EXPECT_TRUE(all_cases_available());
}
TEST(FFI, all_cases_build_parallel_async) {
TEST(AllCases, all_cases_build_parallel_async) {
all_cases_reset();
static std::atomic_flag chan;
static std::atomic_flag flag;
chan.clear();
flag.clear();
all_cases_build_parallel_async([](void (*fn)(void*), void *arg) {
std::thread worker(fn, arg);
worker.detach();
}, []() {
chan.test_and_set();
chan.notify_all();
}, []() { // callback function
flag.test_and_set();
flag.notify_all();
});
EXPECT_FALSE(all_cases_available());
chan.wait(false);
flag.wait(false);
EXPECT_TRUE(all_cases_available());
chan.clear();
flag.clear();
all_cases_build_parallel_async([](void (*fn)(void*), void *arg) {
std::thread worker(fn, arg);
worker.detach();
}, []() {
chan.test_and_set();
chan.notify_all();
}, []() { // callback function
flag.test_and_set();
flag.notify_all();
});
EXPECT_TRUE(all_cases_available());
chan.wait(false);
flag.wait(false);
EXPECT_TRUE(all_cases_available());
}
TEST(FFI, all_cases_num) {
TEST(AllCases, all_cases_num) {
EXPECT_LT(all_cases_num(-2), 0);
EXPECT_LT(all_cases_num(-1), 0);
for (int i = 0; i < 15; ++i) {
@ -163,7 +163,7 @@ TEST(FFI, all_cases_num) {
EXPECT_LT(all_cases_num(17), 0);
}
TEST(FFI, all_cases_export) {
TEST(AllCases, all_cases_export) {
EXPECT_EQ(all_cases_export(-2), nullptr);
EXPECT_EQ(all_cases_export(-1), nullptr);
EXPECT_EQ(all_cases_export(16), nullptr);

Loading…
Cancel
Save