7 #include "packager/file/io_cache.h"
13 #include "packager/base/logging.h"
18 using base::AutoUnlock;
20 IoCache::IoCache(uint64_t cache_size)
21 : cache_size_(cache_size),
22 read_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
23 base::WaitableEvent::InitialState::NOT_SIGNALED),
24 write_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
25 base::WaitableEvent::InitialState::NOT_SIGNALED),
28 circular_buffer_(cache_size + 1),
29 end_ptr_(&circular_buffer_[0] + cache_size + 1),
30 r_ptr_(circular_buffer_.data()),
31 w_ptr_(circular_buffer_.data()),
38 uint64_t IoCache::Read(
void* buffer, uint64_t size) {
42 while (!closed_ && (BytesCachedInternal() == 0)) {
43 AutoUnlock unlock(lock_);
47 size = std::min(size, BytesCachedInternal());
48 uint64_t first_chunk_size(
49 std::min(size, static_cast<uint64_t>(end_ptr_ - r_ptr_)));
50 memcpy(buffer, r_ptr_, first_chunk_size);
51 r_ptr_ += first_chunk_size;
52 DCHECK_GE(end_ptr_, r_ptr_);
53 if (r_ptr_ == end_ptr_)
54 r_ptr_ = &circular_buffer_[0];
55 uint64_t second_chunk_size(size - first_chunk_size);
56 if (second_chunk_size) {
57 memcpy(static_cast<uint8_t*>(buffer) + first_chunk_size, r_ptr_,
59 r_ptr_ += second_chunk_size;
60 DCHECK_GT(end_ptr_, r_ptr_);
66 uint64_t IoCache::Write(
const void* buffer, uint64_t size) {
69 const uint8_t* r_ptr(static_cast<const uint8_t*>(buffer));
70 uint64_t bytes_left(size);
73 while (!closed_ && (BytesFreeInternal() == 0)) {
74 AutoUnlock unlock(lock_);
80 uint64_t write_size(std::min(bytes_left, BytesFreeInternal()));
81 uint64_t first_chunk_size(
82 std::min(write_size, static_cast<uint64_t>(end_ptr_ - w_ptr_)));
83 memcpy(w_ptr_, r_ptr, first_chunk_size);
84 w_ptr_ += first_chunk_size;
85 DCHECK_GE(end_ptr_, w_ptr_);
86 if (w_ptr_ == end_ptr_)
87 w_ptr_ = &circular_buffer_[0];
88 r_ptr += first_chunk_size;
89 uint64_t second_chunk_size(write_size - first_chunk_size);
90 if (second_chunk_size) {
91 memcpy(w_ptr_, r_ptr, second_chunk_size);
92 w_ptr_ += second_chunk_size;
93 DCHECK_GT(end_ptr_, w_ptr_);
94 r_ptr += second_chunk_size;
96 bytes_left -= write_size;
97 write_event_.Signal();
102 void IoCache::Clear() {
103 AutoLock lock(lock_);
104 r_ptr_ = w_ptr_ = circular_buffer_.data();
106 read_event_.Signal();
109 void IoCache::Close() {
110 AutoLock lock(lock_);
112 read_event_.Signal();
113 write_event_.Signal();
116 void IoCache::Reopen() {
117 AutoLock lock(lock_);
119 r_ptr_ = w_ptr_ = circular_buffer_.data();
122 write_event_.Reset();
125 uint64_t IoCache::BytesCached() {
126 AutoLock lock(lock_);
127 return BytesCachedInternal();
130 uint64_t IoCache::BytesFree() {
131 AutoLock lock(lock_);
132 return BytesFreeInternal();
135 uint64_t IoCache::BytesCachedInternal() {
136 return (r_ptr_ <= w_ptr_)
138 : (end_ptr_ - r_ptr_) + (w_ptr_ - circular_buffer_.data());
141 uint64_t IoCache::BytesFreeInternal() {
142 return cache_size_ - BytesCachedInternal();
145 void IoCache::WaitUntilEmptyOrClosed() {
146 AutoLock lock(lock_);
147 while (!closed_ && BytesCachedInternal()) {
148 AutoUnlock unlock(lock_);