ReUseX  0.0.5
3D Point Cloud Processing for Building Reuse
Loading...
Searching...
No Matches
cpm.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2025 Povl Filip Sonne-Frederiksen
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4
5#pragma once
6#include <algorithm>
7#include <atomic>
8#include <condition_variable>
9#include <future>
10#include <memory>
11#include <queue>
12#include <thread>
13
14// Comsumer Producer Model
15
17
18template <typename Result, typename Input, typename Model> class Instance {
19 protected:
20 struct Item {
21 Input input;
22 std::shared_ptr<std::promise<Result>> pro;
23 };
24
25 std::condition_variable cond_;
26 std::queue<Item> input_queue_;
27 std::mutex queue_lock_;
28 std::shared_ptr<std::thread> worker_;
29 std::atomic_bool run_{false};
30 std::atomic_int max_items_processed_{0};
31 void *stream_ = nullptr;
32
33 public:
34 virtual ~Instance() { stop(); }
35
36 void stop() {
37 run_ = false;
38 cond_.notify_one();
39 {
40 std::unique_lock<std::mutex> l(queue_lock_);
41 while (!input_queue_.empty()) {
42 auto &item = input_queue_.front();
43 if (item.pro)
44 item.pro->set_value(Result());
45 input_queue_.pop();
46 }
47 };
48
49 if (worker_) {
50 worker_->join();
51 worker_.reset();
52 }
53 }
54
55 virtual std::shared_future<Result> commit(const Input &input) {
56 Item item;
57 item.input = input;
58 item.pro.reset(new std::promise<Result>());
59 {
60 std::unique_lock<std::mutex> __lock_(queue_lock_);
61 input_queue_.push(item);
62 }
63 cond_.notify_one();
64 return item.pro->get_future();
65 }
66
67 virtual std::vector<std::shared_future<Result>>
68 commits(const std::vector<Input> &inputs) {
69 std::vector<std::shared_future<Result>> output;
70 {
71 std::unique_lock<std::mutex> __lock_(queue_lock_);
72 for (int i = 0; i < (int)inputs.size(); ++i) {
73 Item item;
74 item.input = inputs[i];
75 item.pro.reset(new std::promise<Result>());
76 output.emplace_back(item.pro->get_future());
77 input_queue_.push(item);
78 }
79 }
80 cond_.notify_one();
81 return output;
82 }
83
84 template <typename LoadMethod>
85 bool start(const LoadMethod &loadmethod, int max_items_processed = 1,
86 void *stream = nullptr) {
87 stop();
88
89 this->stream_ = stream;
90 this->max_items_processed_ = max_items_processed;
91 std::promise<bool> status;
92 worker_ =
93 std::make_shared<std::thread>(&Instance::worker<LoadMethod>, this,
94 std::ref(loadmethod), std::ref(status));
95 return status.get_future().get();
96 }
97
98 private:
99 template <typename LoadMethod>
100 void worker(const LoadMethod &loadmethod, std::promise<bool> &status) {
101 std::shared_ptr<Model> model = loadmethod();
102 if (model == nullptr) {
103 status.set_value(false);
104 return;
105 }
106
107 run_ = true;
108 status.set_value(true);
109
110 std::vector<Item> fetch_items;
111 std::vector<Input> inputs;
112 while (get_items_and_wait(fetch_items, max_items_processed_)) {
113 inputs.resize(fetch_items.size());
114 std::transform(fetch_items.begin(), fetch_items.end(), inputs.begin(),
115 [](Item &item) { return item.input; });
116
117 auto ret = model->forwards(inputs, stream_);
118 for (int i = 0; i < (int)fetch_items.size(); ++i) {
119 if (i < (int)ret.size()) {
120 fetch_items[i].pro->set_value(ret[i]);
121 } else {
122 fetch_items[i].pro->set_value(Result());
123 }
124 }
125 inputs.clear();
126 fetch_items.clear();
127 }
128 model.reset();
129 run_ = false;
130 }
131
132 virtual bool get_items_and_wait(std::vector<Item> &fetch_items,
133 int max_size) {
134 std::unique_lock<std::mutex> l(queue_lock_);
135 cond_.wait(l, [&]() { return !run_ || !input_queue_.empty(); });
136
137 if (!run_)
138 return false;
139
140 fetch_items.clear();
141 for (int i = 0; i < max_size && !input_queue_.empty(); ++i) {
142 fetch_items.emplace_back(std::move(input_queue_.front()));
143 input_queue_.pop();
144 }
145 return true;
146 }
147
148 virtual bool get_item_and_wait(Item &fetch_item) {
149 std::unique_lock<std::mutex> l(queue_lock_);
150 cond_.wait(l, [&]() { return !run_ || !input_queue_.empty(); });
151
152 if (!run_)
153 return false;
154
155 fetch_item = std::move(input_queue_.front());
156 input_queue_.pop();
157 return true;
158 }
159};
160}; // namespace reusex::vision::tensor_rt::cpm
std::condition_variable cond_
Definition cpm.hpp:25
bool start(const LoadMethod &loadmethod, int max_items_processed=1, void *stream=nullptr)
Definition cpm.hpp:85
virtual std::vector< std::shared_future< Result > > commits(const std::vector< Input > &inputs)
Definition cpm.hpp:68
virtual std::shared_future< Result > commit(const Input &input)
Definition cpm.hpp:55
std::shared_ptr< std::thread > worker_
Definition cpm.hpp:28
std::shared_ptr< std::promise< Result > > pro
Definition cpm.hpp:22