是否使用 unique_ptr 成员变量?
Using unique_ptr member variables or not?
创建阻塞缓冲区队列的更好设计模式是什么,它可以在 C++11/14 中有效地使用资源而不需要太多 allocs/moves?使用 Queue<std::unique_ptr<Workitem>>
或
Queue<Workitem>
并且在实现中隐藏了资源管理(有点像 stl 容器)。注意,第二个思路(Queue)被注释掉了。注释掉的版本对 heap/stack 有何影响?那么使用 std::unique_ptr<Queue<Workitem>> q
呢?
我不是很会c++,但是不管是什么版本,我都不会真的泄漏内存吧? (推理:不是 new/delete -> 没有内存泄漏)
代码在这里:
#include <condition_variable>
#include <mutex>
#include <queue>
template <class T> class Queue {
public:
Queue(size_t size);
// push item to _queue if _queue.size() < _size
// else block
void push(T item);
// void push(std::unique_ptr<T> item);
// pop item if !_queue.empty()
// else block or return false after timeout
bool pop(T &item);
// bool pop(std::unique_ptr<T> &item);
private:
std::mutex _mutex;
std::size_t _size;
std::queue<T> _queue;
// std::queue<std::unique_ptr<T>> _queue;
std::condition_variable _condition_full;
std::condition_variable _condition_empty;
};
struct Workitem {
size_t idx;
void *workdetails;
};
void do_work(Queue<std::unique_ptr<Workitem>> &work_q,
Queue<std::unique_ptr<Workitem>> &write_q,
struct options_s &opts) {
std::unique_ptr<Workitem> work;
while (work_q.pop(work)) {
// calculation w/ work
std::unique_ptr<Workitem> res = consume(work, opts);
write_q.push(std::move(work));
}
}
void do_write(Queue<std::unique_ptr<Workitem>> &write_q,
struct options_s &opts) {
std::unique_ptr<Workitem> work;
while (write_q.pop(work)) {
prepare_for_writing(work, opts); // clean item
write(work);
}
}
auto w1 = std::thread(do_work, std::ref(work_q), std::ref(write_q),
std::ref(options));
auto w2 = std::thread(do_work, std::ref(work_q), std::ref(write_q),
std::ref(options));
auto writer = std::thread(do_write, std::ref(write_q), std::ref(options));
int main() {
Queue<std::unique_ptr<Workitem>> work_q{4};
Queue<std::unique_ptr<Workitem>> write_q{4};
// Queue<Workitem> q{4};
// ??? std::unique_ptr<Queue<Workitem>> q{4} ???
for (size_t i, ...) { // do many iterations
std::unique_ptr<Workitem> w{};
// Workitem w{};
populate(w, i); // populate work item
work_q.push(std::move(w));
}
w1.join();
w2.join();
writer.join();
}
如果有帮助,我可以提供实现,我只是不想弄乱所有内容,所以我将其遗漏了。需要注意的是,队列由线程使用。我使用两个队列用于多个工作线程和一个编写器线程来跨内核分配负载。
干杯
What is a better designpattern for creating a blocking bufferqueue, that uses resources efficiently in C++11/14 without too many allocs/moves? Using Queue<std::unique_ptr<Workitem>>
OR Queue<Workitem>
鉴于该标准,Queue<Workitem>
更好,因为它避免了一层动态分配。
What are the implications of the commented out version also regarding heap/stack?
堆与栈之间并没有什么区别。对象在两种变体中都是动态分配的。
I can't really leak memory right? (reasonging: not new/delete -> no memoryleaks)
你的推理很有道理。您显示的示例代码没有内存泄漏。
然而,有一个裸指针成员变量 Workitem::workdetails
如果被滥用(如果它曾经拥有它指向的内存)可能会导致内存泄漏。
创建阻塞缓冲区队列的更好设计模式是什么,它可以在 C++11/14 中有效地使用资源而不需要太多 allocs/moves?使用 Queue<std::unique_ptr<Workitem>>
或
Queue<Workitem>
并且在实现中隐藏了资源管理(有点像 stl 容器)。注意,第二个思路(Queue)被注释掉了。注释掉的版本对 heap/stack 有何影响?那么使用 std::unique_ptr<Queue<Workitem>> q
呢?
我不是很会c++,但是不管是什么版本,我都不会真的泄漏内存吧? (推理:不是 new/delete -> 没有内存泄漏)
代码在这里:
#include <condition_variable>
#include <mutex>
#include <queue>
template <class T> class Queue {
public:
Queue(size_t size);
// push item to _queue if _queue.size() < _size
// else block
void push(T item);
// void push(std::unique_ptr<T> item);
// pop item if !_queue.empty()
// else block or return false after timeout
bool pop(T &item);
// bool pop(std::unique_ptr<T> &item);
private:
std::mutex _mutex;
std::size_t _size;
std::queue<T> _queue;
// std::queue<std::unique_ptr<T>> _queue;
std::condition_variable _condition_full;
std::condition_variable _condition_empty;
};
struct Workitem {
size_t idx;
void *workdetails;
};
void do_work(Queue<std::unique_ptr<Workitem>> &work_q,
Queue<std::unique_ptr<Workitem>> &write_q,
struct options_s &opts) {
std::unique_ptr<Workitem> work;
while (work_q.pop(work)) {
// calculation w/ work
std::unique_ptr<Workitem> res = consume(work, opts);
write_q.push(std::move(work));
}
}
void do_write(Queue<std::unique_ptr<Workitem>> &write_q,
struct options_s &opts) {
std::unique_ptr<Workitem> work;
while (write_q.pop(work)) {
prepare_for_writing(work, opts); // clean item
write(work);
}
}
auto w1 = std::thread(do_work, std::ref(work_q), std::ref(write_q),
std::ref(options));
auto w2 = std::thread(do_work, std::ref(work_q), std::ref(write_q),
std::ref(options));
auto writer = std::thread(do_write, std::ref(write_q), std::ref(options));
int main() {
Queue<std::unique_ptr<Workitem>> work_q{4};
Queue<std::unique_ptr<Workitem>> write_q{4};
// Queue<Workitem> q{4};
// ??? std::unique_ptr<Queue<Workitem>> q{4} ???
for (size_t i, ...) { // do many iterations
std::unique_ptr<Workitem> w{};
// Workitem w{};
populate(w, i); // populate work item
work_q.push(std::move(w));
}
w1.join();
w2.join();
writer.join();
}
如果有帮助,我可以提供实现,我只是不想弄乱所有内容,所以我将其遗漏了。需要注意的是,队列由线程使用。我使用两个队列用于多个工作线程和一个编写器线程来跨内核分配负载。
干杯
What is a better designpattern for creating a blocking bufferqueue, that uses resources efficiently in C++11/14 without too many allocs/moves? Using
Queue<std::unique_ptr<Workitem>>
ORQueue<Workitem>
鉴于该标准,Queue<Workitem>
更好,因为它避免了一层动态分配。
What are the implications of the commented out version also regarding heap/stack?
堆与栈之间并没有什么区别。对象在两种变体中都是动态分配的。
I can't really leak memory right? (reasonging: not new/delete -> no memoryleaks)
你的推理很有道理。您显示的示例代码没有内存泄漏。
然而,有一个裸指针成员变量 Workitem::workdetails
如果被滥用(如果它曾经拥有它指向的内存)可能会导致内存泄漏。