blob: cf90510cd295d50fef838177923f7c100e3ae062 [file] [log] [blame]
// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "arc/vm/libvda/event_pipe.h"
#include <utility>
#include <fcntl.h>
#include <base/bind.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include "arc/vm/libvda/libvda_decode.h"
#include "arc/vm/libvda/libvda_encode.h"
namespace arc {
namespace {
// This method should only be called on the |event_write_thread| in order to
// write |event|. This is done so that all events are sent in sequence
// (important for PICTURE_READY events), and to ensure that a full write of
// |event| is always done as a single operation. Using the IPC thread was
// considered, but then in cases where the pipe buffer is close to being full,
// write() could block, which would not be acceptable to the IPC thread.
// Setting the pipe to non-blocking mode was also considered, but then
// we would have to re-post a new task to complete the write which could
// cause ordering issues.
template <class T>
void WriteToFd(int fd, const T event) {
CHECK(base::WriteFileDescriptor(fd, reinterpret_cast<const char*>(&event),
sizeof(T)));
}
} // namespace
EventPipe::EventPipe() : event_write_thread_("EventWriteThread") {
int pipe_fds[2];
CHECK_EQ(pipe2(pipe_fds, O_CLOEXEC), 0);
event_read_fd_.reset(pipe_fds[0]);
event_write_fd_.reset(pipe_fds[1]);
// Start the dedicated event write thread for this session context.
CHECK(event_write_thread_.Start());
}
EventPipe::~EventPipe() = default;
int EventPipe::GetReadFd() const {
return event_read_fd_.get();
}
void EventPipe::WriteVdaEvent(const vda_event_t& event) {
event_write_thread_.task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&WriteToFd<vda_event_t>, event_write_fd_.get(), event));
}
void EventPipe::WriteVeaEvent(const vea_event_t& event) {
event_write_thread_.task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&WriteToFd<vea_event_t>, event_write_fd_.get(), event));
}
} // namespace arc