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(scoped_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_(internal_file.Pass()),
27 cache_(io_cache_size),
28 io_buffer_(io_block_size),
33 flush_complete_event_(false, false),
34 internal_file_error_(0),
35 task_exit_event_(false, false) {
36 DCHECK(internal_file_);
39 ThreadedIoFile::~ThreadedIoFile() {}
42 DCHECK(internal_file_);
44 if (!internal_file_->Open())
48 size_ = internal_file_->Size();
50 base::WorkerPool::PostTask(FROM_HERE, base::Bind(&ThreadedIoFile::TaskHandler,
51 base::Unretained(
this)),
57 DCHECK(internal_file_);
59 if (mode_ == kOutputMode)
63 task_exit_event_.Wait();
65 bool result = internal_file_.release()->Close();
71 DCHECK(internal_file_);
72 DCHECK_EQ(kInputMode, mode_);
77 if (NoBarrier_Load(&internal_file_error_))
78 return NoBarrier_Load(&internal_file_error_);
81 uint64_t bytes_read = cache_.
Read(buffer, length);
82 position_ += bytes_read;
88 DCHECK(internal_file_);
89 DCHECK_EQ(kOutputMode, mode_);
91 if (NoBarrier_Load(&internal_file_error_))
92 return NoBarrier_Load(&internal_file_error_);
94 uint64_t bytes_written = cache_.
Write(buffer, length);
95 position_ += bytes_written;
96 if (position_ > size_)
103 DCHECK(internal_file_);
109 DCHECK(internal_file_);
110 DCHECK_EQ(kOutputMode, mode_);
114 flush_complete_event_.Wait();
115 return internal_file_->Flush();
119 if (mode_ == kOutputMode) {
121 if (!
Flush())
return false;
122 if (!internal_file_->Seek(position))
return false;
127 task_exit_event_.Wait();
128 bool result = internal_file_->Seek(position);
131 if (!internal_file_->Seek(position_) && (position != position_)) {
132 LOG(WARNING) <<
"Seek failed. ThreadedIoFile left in invalid state.";
137 base::WorkerPool::PostTask(
139 base::Bind(&ThreadedIoFile::TaskHandler, base::Unretained(
this)),
141 if (!result)
return false;
143 position_ = position;
150 *position = position_;
154 void ThreadedIoFile::TaskHandler() {
155 if (mode_ == kInputMode)
159 task_exit_event_.Signal();
162 void ThreadedIoFile::RunInInputMode() {
163 DCHECK(internal_file_);
164 DCHECK_EQ(kInputMode, mode_);
167 int64_t read_result = internal_file_->Read(&io_buffer_[0],
169 if (read_result <= 0) {
170 NoBarrier_Store(&eof_, read_result == 0);
171 NoBarrier_Store(&internal_file_error_, read_result);
175 if (cache_.
Write(&io_buffer_[0], read_result) == 0) {
181 void ThreadedIoFile::RunInOutputMode() {
182 DCHECK(internal_file_);
183 DCHECK_EQ(kOutputMode, mode_);
186 uint64_t write_bytes = cache_.
Read(&io_buffer_[0], io_buffer_.size());
187 if (write_bytes == 0) {
191 flush_complete_event_.Signal();
196 uint64_t bytes_written(0);
197 while (bytes_written < write_bytes) {
198 int64_t write_result = internal_file_->Write(
199 &io_buffer_[bytes_written], write_bytes - bytes_written);
200 if (write_result < 0) {
201 NoBarrier_Store(&internal_file_error_, write_result);
205 bytes_written += write_result;