• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "ReadBuffer.h"
17 
18 #include "host-common/logging.h"
19 
20 #include <algorithm>
21 
22 #include <assert.h>
23 #include <string.h>
24 #include <limits.h>
25 
26 namespace gfxstream {
27 
ReadBuffer(size_t bufsize)28 ReadBuffer::ReadBuffer(size_t bufsize) {
29     m_size = bufsize;
30     m_buf = (unsigned char*)malloc(m_size);
31     m_validData = 0;
32     m_readPtr = m_buf;
33 }
34 
~ReadBuffer()35 ReadBuffer::~ReadBuffer() {
36     free(m_buf);
37 }
38 
setNeededFreeTailSize(size_t size)39 void ReadBuffer::setNeededFreeTailSize(size_t size) {
40     m_neededFreeTailSize = size;
41 }
42 
getData(IOStream * stream,size_t minSize)43 int ReadBuffer::getData(IOStream* stream, size_t minSize) {
44     assert(stream);
45     assert(minSize > m_validData);
46 
47     const size_t minSizeToRead = minSize - m_validData;
48     const size_t neededFreeTailThisTime =
49         std::max(minSizeToRead,
50                  m_neededFreeTailSize);
51 
52     size_t maxSizeToRead;
53     const size_t freeTailSize = m_buf + m_size - (m_readPtr + m_validData);
54     if (freeTailSize >= neededFreeTailThisTime) {
55         maxSizeToRead = freeTailSize;
56     } else {
57         if (freeTailSize + (m_readPtr - m_buf) >= neededFreeTailThisTime) {
58             // There's some gap in the beginning, if we move the data over it
59             // that's going to be enough.
60             memmove(m_buf, m_readPtr, m_validData);
61         } else {
62             // Not enough space even with moving, reallocate.
63             // Note: make sure we can fit at least two of the requested packets
64             //  into the new buffer to minimize the reallocations and
65             //  memmove()-ing stuff around.
66           size_t new_size = std::max(2 * minSizeToRead + m_validData, 2 * m_size);
67           if (new_size < m_size) {  // overflow check
68                 new_size = INT_MAX;
69             }
70 
71             const auto new_buf = (unsigned char*)malloc(new_size);
72             if (!new_buf) {
73                 ERR("Failed to alloc %zu bytes for ReadBuffer\n", new_size);
74                 return -1;
75             }
76 
77             memcpy(new_buf, m_readPtr, m_validData);
78             free(m_buf);
79             m_buf = new_buf;
80             m_size = new_size;
81         }
82         // We can read more now, let's request it in case all data is ready
83         // for reading.
84         maxSizeToRead = m_size - m_validData;
85         m_readPtr = m_buf;
86     }
87 
88     // get fresh data into the buffer;
89     int readTotal = 0;
90     do {
91         const size_t readNow = stream->read(m_readPtr + m_validData,
92                                             maxSizeToRead - readTotal);
93 
94         if (!readNow) {
95             if (readTotal > 0) {
96                 return readTotal;
97             } else {
98                 return -1;
99             }
100         }
101         readTotal += readNow;
102         m_validData += readNow;
103     } while (readTotal < minSizeToRead);
104 
105     return readTotal;
106 }
107 
consume(size_t amount)108 void ReadBuffer::consume(size_t amount) {
109     assert(amount <= m_validData);
110     m_validData -= amount;
111     m_readPtr += amount;
112 }
113 
onSave(android::base::Stream * stream)114 void ReadBuffer::onSave(android::base::Stream* stream) {
115     stream->putBe32(m_size);
116     stream->putBe32(m_validData);
117     stream->write(m_readPtr, m_validData);
118 }
119 
onLoad(android::base::Stream * stream)120 void ReadBuffer::onLoad(android::base::Stream* stream) {
121     const auto size = stream->getBe32();
122     if (size > m_size) {
123         m_size = size;
124         free(m_buf);
125         m_buf = (unsigned char*)malloc(m_size);
126     }
127     m_readPtr = m_buf;
128     m_validData = stream->getBe32();
129     assert(m_validData <= m_size);
130     stream->read(m_readPtr, m_validData);
131 }
132 
printStats()133 void ReadBuffer::printStats() {
134     printf("ReadBuffer::%s: tail move time %f ms\n", __func__,
135             (float)m_tailMoveTimeUs / 1000.0f);
136     m_tailMoveTimeUs = 0;
137 }
138 }  // namespace gfxstream
139