Skip to content

Commit 15b2e98

Browse files
committed
Added Channel class
1 parent c0a2835 commit 15b2e98

1 file changed

Lines changed: 35 additions & 18 deletions

File tree

ext/or-tools/constraint.cpp

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,33 @@ namespace Rice::detail {
7878
};
7979
} // namespace Rice::detail
8080

81+
template<typename T>
82+
class Channel {
83+
public:
84+
std::queue<T> queue;
85+
std::mutex mutex;
86+
std::condition_variable cv;
87+
88+
void send(T message) {
89+
std::lock_guard<std::mutex> guard(mutex);
90+
queue.push(message);
91+
cv.notify_one();
92+
}
93+
94+
template<typename U, typename V>
95+
std::optional<T> recv_timeout(const std::chrono::duration<U, V>& duration) {
96+
T message;
97+
std::unique_lock<std::mutex> lock(mutex);
98+
auto time = std::chrono::system_clock::now() + duration;
99+
if (!cv.wait_until(lock, time, [&] { return !queue.empty(); })) {
100+
return std::nullopt;
101+
}
102+
message = std::move(queue.front());
103+
queue.pop();
104+
return message;
105+
}
106+
};
107+
81108
void init_constraint(Rice::Module& m) {
82109
Rice::define_class_under<Domain>(m, "Domain")
83110
.define_constructor(Rice::Constructor<Domain, int64_t, int64_t>())
@@ -436,9 +463,7 @@ void init_constraint(Rice::Module& m) {
436463
m.Add(NewSatParameters(parameters));
437464

438465
std::atomic<bool> done{false};
439-
std::queue<CpSolverResponse> queue;
440-
std::mutex mutex;
441-
std::condition_variable cv;
466+
Channel<CpSolverResponse> channel;
442467
Rice::Object ruby_thread;
443468
std::optional<Rice::Exception> exception;
444469

@@ -454,28 +479,22 @@ void init_constraint(Rice::Module& m) {
454479
return Rice::detail::no_gvl([&]() {
455480
while (true) {
456481
if (done.load()) {
457-
std::lock_guard<std::mutex> guard(mutex);
458-
if (queue.empty()) {
482+
std::lock_guard<std::mutex> guard(channel.mutex);
483+
if (channel.queue.empty()) {
459484
break;
460485
}
461486
}
462487

463488
while (true) {
464-
CpSolverResponse r;
465-
{
466-
std::unique_lock<std::mutex> lock(mutex);
467-
auto time = std::chrono::system_clock::now() + std::chrono::milliseconds(10);
468-
if (!cv.wait_until(lock, time, [&] { return !queue.empty(); })) {
469-
break;
470-
}
471-
r = std::move(queue.front());
472-
queue.pop();
489+
std::optional<CpSolverResponse> r = channel.recv_timeout(std::chrono::milliseconds(10));
490+
if (!r) {
491+
break;
473492
}
474493

475494
bool stop = false;
476495
with_gvl([&]() {
477496
try {
478-
callback.call("response=", r);
497+
callback.call("response=", r.value());
479498
callback.call("on_solution_callback");
480499
stop = static_cast<bool>(callback.attr_get("@stopped"));
481500
} catch (const Rice::Exception& e) {
@@ -510,9 +529,7 @@ void init_constraint(Rice::Module& m) {
510529

511530
m.Add(NewFeasibleSolutionObserver(
512531
[&](const CpSolverResponse& r) {
513-
std::lock_guard<std::mutex> guard(mutex);
514-
queue.push(r);
515-
cv.notify_one();
532+
channel.send(r);
516533
})
517534
);
518535
}

0 commit comments

Comments
 (0)