src/buffer.c

changeset 1291
5942859fd76c
parent 1290
4ac889e14211
child 1292
1e7ee17777f4
equal deleted inserted replaced
1290:4ac889e14211 1291:5942859fd76c
27 */ 27 */
28 28
29 #include "cx/buffer.h" 29 #include "cx/buffer.h"
30 30
31 #include <stdio.h> 31 #include <stdio.h>
32 #include <unistd.h>
32 #include <string.h> 33 #include <string.h>
33 #include <errno.h> 34 #include <errno.h>
34 35
35 static int buffer_copy_on_write(CxBuffer* buffer) { 36 static int buffer_copy_on_write(CxBuffer* buffer) {
36 if (0 == (buffer->flags & CX_BUFFER_COPY_ON_WRITE)) return 0; 37 if (0 == (buffer->flags & CX_BUFFER_COPY_ON_WRITE)) return 0;
187 size_t newcap 188 size_t newcap
188 ) { 189 ) {
189 if (newcap <= buffer->capacity) { 190 if (newcap <= buffer->capacity) {
190 return 0; 191 return 0;
191 } 192 }
193
194 unsigned long pagesize = sysconf(_SC_PAGESIZE);
195 // if page size is larger than 64 KB - for some reason - truncate to 64 KB
196 if (pagesize > 65536) pagesize = 65536;
197 if (newcap < pagesize) {
198 // when smaller as one page, map to the next power of two
199 newcap--;
200 newcap |= newcap >> 1;
201 newcap |= newcap >> 2;
202 newcap |= newcap >> 4;
203 // last operation only needed for pages larger 4096 bytes
204 // but if/else would be more expensive than just doing this
205 newcap |= newcap >> 8;
206 newcap++;
207 } else {
208 // otherwise, map to a multiple of the page size
209 newcap -= newcap % pagesize;
210 newcap += pagesize;
211 // note: if newcap is already page aligned,
212 // this gives a full additional page (which is good)
213 }
214
192 215
193 const int force_copy_flags = CX_BUFFER_COPY_ON_WRITE | CX_BUFFER_COPY_ON_EXTEND; 216 const int force_copy_flags = CX_BUFFER_COPY_ON_WRITE | CX_BUFFER_COPY_ON_EXTEND;
194 if (buffer->flags & force_copy_flags) { 217 if (buffer->flags & force_copy_flags) {
195 void *newspace = cxMalloc(buffer->allocator, newcap); 218 void *newspace = cxMalloc(buffer->allocator, newcap);
196 if (NULL == newspace) return -1; 219 if (NULL == newspace) return -1;

mercurial