7 #include "packager/media/file/threaded_io_file.h"
9 #include "packager/base/bind.h"
10 #include "packager/base/bind_helpers.h"
11 #include "packager/base/location.h"
12 #include "packager/base/threading/worker_pool.h"
17 using base::subtle::NoBarrier_Load;
18 using base::subtle::NoBarrier_Store;
20 ThreadedIoFile::ThreadedIoFile(std::unique_ptr<File, FileCloser> internal_file,
22 uint64_t io_cache_size,
23 uint64_t io_block_size)
24 : File(internal_file->file_name()),
25 internal_file_(std::move(internal_file)),
27 cache_(io_cache_size),
28 io_buffer_(io_block_size),
33 flush_complete_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
34 base::WaitableEvent::InitialState::NOT_SIGNALED),
35 internal_file_error_(0),
36 task_exit_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
37 base::WaitableEvent::InitialState::NOT_SIGNALED) {
38 DCHECK(internal_file_);
41 ThreadedIoFile::~ThreadedIoFile() {}
44 DCHECK(internal_file_);
46 if (!internal_file_->Open())
50 size_ = internal_file_->Size();
52 base::WorkerPool::PostTask(FROM_HERE, base::Bind(&ThreadedIoFile::TaskHandler,
53 base::Unretained(
this)),
59 DCHECK(internal_file_);
61 if (mode_ == kOutputMode)
65 task_exit_event_.Wait();
67 bool result = internal_file_.release()->Close();
73 DCHECK(internal_file_);
74 DCHECK_EQ(kInputMode, mode_);
79 if (NoBarrier_Load(&internal_file_error_))
80 return NoBarrier_Load(&internal_file_error_);
83 uint64_t bytes_read = cache_.
Read(buffer, length);
84 position_ += bytes_read;
90 DCHECK(internal_file_);
91 DCHECK_EQ(kOutputMode, mode_);
93 if (NoBarrier_Load(&internal_file_error_))
94 return NoBarrier_Load(&internal_file_error_);
96 uint64_t bytes_written = cache_.
Write(buffer, length);
97 position_ += bytes_written;
98 if (position_ > size_)
101 return bytes_written;
105 DCHECK(internal_file_);
111 DCHECK(internal_file_);
112 DCHECK_EQ(kOutputMode, mode_);
116 flush_complete_event_.Wait();
117 return internal_file_->Flush();
121 if (mode_ == kOutputMode) {
123 if (!
Flush())
return false;
124 if (!internal_file_->Seek(position))
return false;
129 task_exit_event_.Wait();
130 bool result = internal_file_->Seek(position);
133 if (!internal_file_->Seek(position_) && (position != position_)) {
134 LOG(WARNING) <<
"Seek failed. ThreadedIoFile left in invalid state.";
139 base::WorkerPool::PostTask(
141 base::Bind(&ThreadedIoFile::TaskHandler, base::Unretained(
this)),
143 if (!result)
return false;
145 position_ = position;
152 *position = position_;
156 void ThreadedIoFile::TaskHandler() {
157 if (mode_ == kInputMode)
161 task_exit_event_.Signal();
164 void ThreadedIoFile::RunInInputMode() {
165 DCHECK(internal_file_);
166 DCHECK_EQ(kInputMode, mode_);
169 int64_t read_result = internal_file_->Read(&io_buffer_[0],
171 if (read_result <= 0) {
172 NoBarrier_Store(&eof_, read_result == 0);
173 NoBarrier_Store(&internal_file_error_, read_result);
177 if (cache_.
Write(&io_buffer_[0], read_result) == 0) {
183 void ThreadedIoFile::RunInOutputMode() {
184 DCHECK(internal_file_);
185 DCHECK_EQ(kOutputMode, mode_);
188 uint64_t write_bytes = cache_.
Read(&io_buffer_[0], io_buffer_.size());
189 if (write_bytes == 0) {
193 flush_complete_event_.Signal();
198 uint64_t bytes_written(0);
199 while (bytes_written < write_bytes) {
200 int64_t write_result = internal_file_->Write(
201 &io_buffer_[bytes_written], write_bytes - bytes_written);
202 if (write_result < 0) {
203 NoBarrier_Store(&internal_file_error_, write_result);
207 bytes_written += write_result;