DASH Media Packaging SDK
 All Classes Namespaces Functions Variables Typedefs Enumerator
io_cache.cc
1 // Copyright 2015 Google Inc. All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style
4 // license that can be found in the LICENSE file or at
5 // https://developers.google.com/open-source/licenses/bsd
6 
7 #include "packager/media/file/io_cache.h"
8 
9 #include <string.h>
10 
11 #include <algorithm>
12 
13 #include "packager/base/logging.h"
14 #include "packager/base/stl_util.h"
15 
16 namespace edash_packager {
17 
18 using base::AutoLock;
19 using base::AutoUnlock;
20 
21 namespace media {
22 
23 IoCache::IoCache(uint64_t cache_size)
24  : cache_size_(cache_size),
25  read_event_(false, false),
26  write_event_(false, false),
27  // Make the buffer one byte larger than the cache so that when the
28  // condition r_ptr == w_ptr is unambiguous (buffer empty).
29  circular_buffer_(cache_size + 1),
30  end_ptr_(&circular_buffer_[0] + cache_size + 1),
31  r_ptr_(vector_as_array(&circular_buffer_)),
32  w_ptr_(vector_as_array(&circular_buffer_)),
33  closed_(false) {}
34 
35 IoCache::~IoCache() {
36  Close();
37 }
38 
39 uint64_t IoCache::Read(void* buffer, uint64_t size) {
40  DCHECK(buffer);
41 
42  AutoLock lock(lock_);
43  while (!closed_ && (BytesCachedInternal() == 0)) {
44  AutoUnlock unlock(lock_);
45  write_event_.Wait();
46  }
47 
48  size = std::min(size, BytesCachedInternal());
49  uint64_t first_chunk_size(std::min(size, static_cast<uint64_t>(
50  end_ptr_ - r_ptr_)));
51  memcpy(buffer, r_ptr_, first_chunk_size);
52  r_ptr_ += first_chunk_size;
53  DCHECK_GE(end_ptr_, r_ptr_);
54  if (r_ptr_ == end_ptr_)
55  r_ptr_ = &circular_buffer_[0];
56  uint64_t second_chunk_size(size - first_chunk_size);
57  if (second_chunk_size) {
58  memcpy(static_cast<uint8_t*>(buffer) + first_chunk_size, r_ptr_,
59  second_chunk_size);
60  r_ptr_ += second_chunk_size;
61  DCHECK_GT(end_ptr_, r_ptr_);
62  }
63  read_event_.Signal();
64  return size;
65 }
66 
67 uint64_t IoCache::Write(const void* buffer, uint64_t size) {
68  DCHECK(buffer);
69 
70  const uint8_t* r_ptr(static_cast<const uint8_t*>(buffer));
71  uint64_t bytes_left(size);
72  while (bytes_left) {
73  AutoLock lock(lock_);
74  while (!closed_ && (BytesFreeInternal() == 0)) {
75  AutoUnlock unlock(lock_);
76  read_event_.Wait();
77  }
78  if (closed_)
79  return 0;
80 
81  uint64_t write_size(std::min(bytes_left, BytesFreeInternal()));
82  uint64_t first_chunk_size(std::min(write_size, static_cast<uint64_t>(
83  end_ptr_ - w_ptr_)));
84  memcpy(w_ptr_, r_ptr, first_chunk_size);
85  w_ptr_ += first_chunk_size;
86  DCHECK_GE(end_ptr_, w_ptr_);
87  if (w_ptr_ == end_ptr_)
88  w_ptr_ = &circular_buffer_[0];
89  r_ptr += first_chunk_size;
90  uint64_t second_chunk_size(write_size - first_chunk_size);
91  if (second_chunk_size) {
92  memcpy(w_ptr_, r_ptr, second_chunk_size);
93  w_ptr_ += second_chunk_size;
94  DCHECK_GT(end_ptr_, w_ptr_);
95  r_ptr += second_chunk_size;
96  }
97  bytes_left -= write_size;
98  write_event_.Signal();
99  }
100  return size;
101 }
102 
104  AutoLock lock(lock_);
105  r_ptr_ = w_ptr_ = vector_as_array(&circular_buffer_);
106  // Let any writers know that there is room in the cache.
107  read_event_.Signal();
108 }
109 
111  AutoLock lock(lock_);
112  closed_ = true;
113  read_event_.Signal();
114  write_event_.Signal();
115 }
116 
118  AutoLock lock(lock_);
119  CHECK(closed_);
120  r_ptr_ = w_ptr_ = vector_as_array(&circular_buffer_);
121  closed_ = false;
122  read_event_.Reset();
123  write_event_.Reset();
124 }
125 
127  AutoLock lock(lock_);
128  return BytesCachedInternal();
129 }
130 
131 uint64_t IoCache::BytesFree() {
132  AutoLock lock(lock_);
133  return BytesFreeInternal();
134 }
135 
136 uint64_t IoCache::BytesCachedInternal() {
137  return (r_ptr_ <= w_ptr_) ?
138  w_ptr_ - r_ptr_ :
139  (end_ptr_ - r_ptr_) + (w_ptr_ - vector_as_array(&circular_buffer_));
140 }
141 
142 uint64_t IoCache::BytesFreeInternal() {
143  return cache_size_ - BytesCachedInternal();
144 }
145 
147  AutoLock lock(lock_);
148  while (!closed_ && BytesCachedInternal()) {
149  AutoUnlock unlock(lock_);
150  read_event_.Wait();
151  }
152 }
153 
154 } // namespace media
155 } // namespace edash_packager
void Reopen()
Reopens the cache. Any data still in the cache will be lost.
Definition: io_cache.cc:117
void WaitUntilEmptyOrClosed()
Waits until the cache is empty or has been closed.
Definition: io_cache.cc:146
uint64_t Write(const void *buffer, uint64_t size)
Definition: io_cache.cc:67
void Clear()
Empties the cache.
Definition: io_cache.cc:103
uint64_t Read(void *buffer, uint64_t size)
Definition: io_cache.cc:39