Browse Source

update: improve all cases build interface

master
Dnomd343 9 months ago
parent
commit
c6214a4036
  1. 38
      src/core/all_cases/all_cases.cc
  2. 3
      src/core/all_cases/all_cases.h
  3. 36
      src/core/ffi/all_cases.cc
  4. 18
      src/core/ffi/klotski.h
  5. 5
      src/core/main.cc
  6. 4
      src/main.c

38
src/core/all_cases/all_cases.cc

@ -69,6 +69,37 @@ void AllCases::BuildCases(int head, Ranges &release) noexcept {
}
}
/// Execute the build process and ensure thread safety.
void AllCases::Build() noexcept {
BuildParallel([](auto &&func) {
func();
});
}
/// Execute the build process in parallel without blocking.
void AllCases::BuildParallelAsync(Executor &&executor, Notifier &&callback) noexcept {
if (available_) {
return; // reduce consumption of mutex
}
building_.lock();
if (available_) {
building_.unlock();
return; // data is already available
}
auto counter = std::make_shared<std::atomic<int>>(0);
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]);
if (counter->fetch_add(1) == case_heads().size() - 1) {
available_ = true;
building_.unlock(); // release building mutex
all_done->operator()(); // trigger callback
}
});
}
}
/// Execute the build process with parallel support and ensure thread safety.
void AllCases::BuildParallel(Executor &&executor) noexcept {
if (available_) {
@ -95,13 +126,6 @@ void AllCases::BuildParallel(Executor &&executor) noexcept {
available_ = true;
}
/// Execute the build process and ensure thread safety.
void AllCases::Build() noexcept {
BuildParallel([](auto &&func) {
func();
});
}
RangesUnion& AllCases::GetCases() noexcept {
static RangesUnion cases;
return cases;

3
src/core/all_cases/all_cases.h

@ -49,6 +49,8 @@ namespace cases {
typedef uint32_t Range;
typedef std::vector<Range> Ranges;
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;
@ -87,6 +89,7 @@ class AllCases {
public:
void Build() noexcept;
void BuildParallel(Executor &&executor) noexcept;
void BuildParallelAsync(Executor &&executor, Notifier &&callback) noexcept;
const RangesUnion& Fetch() noexcept;
[[nodiscard]] bool IsAvailable() const noexcept;

36
src/core/ffi/all_cases.cc

@ -1,8 +1,8 @@
#include "klotski.h"
#include "all_cases.h"
#include <iostream>
#include <future>
#include <iostream>
using klotski::cases::AllCases;
using klotski::cases::BasicRanges;
@ -37,7 +37,7 @@ void all_cases_build_async(executor_t executor, notifier_t callback) {
}, (void*)callback);
}
void all_cases_parallel_build(executor_t executor) {
void all_cases_build_parallel(executor_t executor) {
typedef std::function<void()> Runner;
AllCases::Instance().BuildParallel([executor](Runner &&runner) {
executor([](void *fn) {
@ -47,29 +47,17 @@ void all_cases_parallel_build(executor_t executor) {
});
}
void all_cases_parallel_build_async(executor_t executor, notifier_t callback) {
typedef std::pair<executor_t, notifier_t> pp_t;
auto pp = new pp_t;
pp->first = executor;
pp->second = callback;
auto lambda = [](void *arg) {
std::cout << "enter lambda" << std::endl;
auto *pp = (pp_t*)arg;
all_cases_parallel_build(pp->first);
((notifier_t)pp->second)();
void all_cases_build_parallel_async(executor_t executor, notifier_t callback) {
typedef std::function<void()> Runner;
auto all_done = [callback]() {
callback();
};
executor(lambda, (void*)pp);
AllCases::Instance().BuildParallelAsync([executor](Runner &&runner) {
executor([](void *fn) {
(*(Runner*)fn)();
delete (Runner*)fn;
}, (void*)new Runner{std::move(runner)});
}, std::move(all_done));
}
int is_all_cases_available() {

18
src/core/ffi/klotski.h

@ -32,14 +32,28 @@ EXTERN void all_cases_prebuild_async(executor_t executor, notifier_t callback);
/// not completed, non-0 otherwise.
EXTERN int is_all_cases_prebuild_available();
/// Perform the build of all_cases, it is blocking, and will return directly
/// if completed.
EXTERN void all_cases_build();
/// Execute the asynchronous build of all_cases, the task will be sent to the
/// executor, and the callback will be called after completion. Even if the
/// data is ready, the callback will still be triggered.
EXTERN void all_cases_build_async(executor_t executor, notifier_t callback);
EXTERN void all_cases_parallel_build(executor_t executor);
/// Build all_cases in parallel, the tasks will be split and sent to the
/// executor, you can put them on different threads to work, but note that the
/// task can only be executed once, otherwise it will lead to unknown
/// consequences, the function will be blocked until all mission completed.
EXTERN void all_cases_build_parallel(executor_t executor);
EXTERN void all_cases_parallel_build_async(executor_t executor, notifier_t callback);
/// Similar to `all_cases_build_parallel`, but it is non-blocking. The callback
/// will be triggered after the build is completed. Note that the callback will
/// still be triggered even if the data is ready.
EXTERN void all_cases_build_parallel_async(executor_t executor, notifier_t callback);
/// Returns whether the all_cases is ready, 0 means not completed, non-0 means
/// the data is ready.
EXTERN int is_all_cases_available();
//extern const uint32_t ALL_CASES_SIZE;

5
src/core/main.cc

@ -10,8 +10,11 @@ int main() {
auto start = clock();
AllCases::Instance().Build();
// BasicRanges::Instance().Build();
// AllCases::Instance().Build();
// AllCases::Instance().BuildParallel([](auto f) {f();});
// AllCases::Instance().BuildParallelAsync([](auto f) {f();}, []() {});
std::cerr << ((clock() - start) * 1000 / CLOCKS_PER_SEC) << "ms" << std::endl;

4
src/main.c

@ -63,11 +63,11 @@ int main() {
// sleep(3);
// printf("build begin\n");
// all_cases_parallel_build(executor);
// all_cases_build_parallel(executor);
// printf("build complete\n");
printf("build begin\n");
all_cases_parallel_build_async(executor, callback);
all_cases_build_parallel_async(executor, callback);
printf("build func exited\n");
printf("build available -> %d\n", is_all_cases_available());
printf("start sleep 3s\n");

Loading…
Cancel
Save