Magisk/native/jni/utils/include/blocking_queue.h

95 lines
1.8 KiB
C
Raw Normal View History

#pragma once
#include <pthread.h>
#include <deque>
2019-09-26 05:55:39 +02:00
#include <misc.h>
template<typename T>
2019-09-26 05:55:39 +02:00
class blocking_queue {
std::deque<T> deque{};
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
bool cancelled = false;
public:
2019-09-26 05:55:39 +02:00
~blocking_queue();
T take();
2019-09-26 05:55:39 +02:00
T &front() const;
T &back() const;
void push(const T&);
void push(T&&);
template< class... Args >
2019-09-26 05:55:39 +02:00
void emplace(Args &&... args);
void clear();
void cancel();
};
#define run_and_notify(block) \
2019-09-26 05:55:39 +02:00
mutex_guard g(this->lock); \
block \
2019-09-26 05:55:39 +02:00
pthread_cond_signal(&this->cond);
template<typename T>
2019-09-26 05:55:39 +02:00
blocking_queue<T>::~blocking_queue() {
pthread_mutex_destroy(&lock);
pthread_cond_destroy(&cond);
}
template<typename T>
2019-09-26 05:55:39 +02:00
T blocking_queue<T>::take() {
mutex_guard g(lock);
cancelled = false;
while (deque.empty() && !cancelled)
pthread_cond_wait(&cond, &lock);
if (cancelled)
pthread_exit(nullptr);
T ret(std::move(deque.front()));
deque.pop_front();
return ret;
}
template<typename T>
2019-09-26 05:55:39 +02:00
void blocking_queue<T>::push(const T &s) {
run_and_notify({ deque.push_back(s); })
}
template<typename T>
2019-09-26 05:55:39 +02:00
void blocking_queue<T>::push(T &&s) {
run_and_notify({ deque.push_back(std::move(s)); })
}
template<typename T>
2019-09-26 05:55:39 +02:00
T &blocking_queue<T>::front() const {
mutex_guard g(lock);
return deque.front();
}
template<typename T>
2019-09-26 05:55:39 +02:00
T &blocking_queue<T>::back() const {
mutex_guard g(lock);
return deque.back();
}
template<typename T>
template<class... Args>
2019-09-26 05:55:39 +02:00
void blocking_queue<T>::emplace(Args &&... args) {
run_and_notify({ deque.emplace_back(std::forward<Args>(args)...); })
}
template<typename T>
2019-09-26 05:55:39 +02:00
void blocking_queue<T>::clear() {
mutex_guard g(lock);
std::deque<T> t;
deque.swap(t);
}
template<typename T>
2019-09-26 05:55:39 +02:00
void blocking_queue<T>::cancel() {
run_and_notify({
cancelled = true;
std::deque<T> t;
deque.swap(t);
})
}
2019-09-26 05:55:39 +02:00
#undef run_and_notify