blob: f120759a06b2d81796fce594c84b18641b0f9ede [file] [edit]
#include <deque>
#include <iterator>
#include <memory>
#include <utility>
#include <vector>
#include "event.h"
#include "event_queue.h"
#include "absl/base/thread_annotations.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/synchronization/mutex.h"
#include "absl/time/time.h"
namespace safepower_agent {
struct EventQueue::Impl {
absl::Mutex mutex;
std::deque<Event> queue ABSL_GUARDED_BY(mutex);
bool closed ABSL_GUARDED_BY(mutex) = false;
bool NotEmptyOrClosed() const ABSL_SHARED_LOCKS_REQUIRED(mutex) {
return !queue.empty() || closed;
}
};
EventQueue::EventQueue() : impl_(std::make_unique<Impl>()) {}
EventQueue::~EventQueue() = default;
void EventQueue::Push(Event event) {
absl::MutexLock lock(impl_->mutex);
if (impl_->closed) {
LOG(DFATAL) << "Attempted to push to a closed EventQueue.";
return;
}
impl_->queue.push_back(std::move(event));
}
void EventQueue::Close() {
absl::MutexLock lock(impl_->mutex);
impl_->closed = true;
}
absl::StatusOr<std::vector<Event>> EventQueue::PopAllWithTimeout(
absl::Duration timeout) {
absl::MutexLock lock(impl_->mutex);
if (impl_->queue.empty() && !impl_->closed &&
timeout > absl::ZeroDuration()) {
impl_->mutex.AwaitWithTimeout(
absl::Condition(impl_.get(), &Impl::NotEmptyOrClosed), timeout);
}
if (impl_->queue.empty() && impl_->closed) {
return absl::AbortedError("Event queue closed");
}
std::vector<Event> events(std::make_move_iterator(impl_->queue.begin()),
std::make_move_iterator(impl_->queue.end()));
impl_->queue.clear();
return events;
}
} // namespace safepower_agent