OPIC
Object Persistence In C
op_malloc.h
Go to the documentation of this file.
1 
8 /* This program is free software: you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation, either version 3 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this program. If not, see
20  * <http://www.gnu.org/licenses/>.
21  */
22 
23 /* Code: */
24 
25 
26 #ifndef OP_MALLOC_H
27 #define OP_MALLOC_H 1
28 
29 #include <stdbool.h>
30 #include <stdio.h>
31 #include <stdint.h>
32 #include <inttypes.h>
33 #include <fcntl.h>
34 #include <string.h>
35 #include "opic/common/op_assert.h"
36 #include "opic/common/op_macros.h"
37 
38 OP_BEGIN_DECLS
39 
48 #define OPHEAP_BITS 36
49 
54 #define OPHEAP_SIZE (1UL << OPHEAP_BITS)
55 
61 typedef struct OPHeap OPHeap;
62 
109 typedef uintptr_t opref_t;
110 
135 typedef uintptr_t oplenref_t;
136 
143 #define OPLENREF_MAX_LEN (1ULL << (64 - OPHEAP_BITS))
144 
179 OPHeap* OPHeapOpen(const char* path, int flags);
180 
204 
217 void OPHeapMSync(OPHeap* heap);
218 
226 void OPHeapClose(OPHeap* heap);
227 
236 void OPHeapStorePtr(OPHeap* heap, void* ptr, int pos);
237 
246 void* OPHeapRestorePtr(OPHeap* heap, int pos);
247 
256 void* OPMalloc(OPHeap* heap, size_t size)
257  __attribute__ ((malloc));
258 
268 void* OPCalloc(OPHeap* heap, size_t num, size_t size)
269  __attribute__ ((malloc));
270 
280 void* OPMallocAdviced(OPHeap* heap, size_t size, int advice)
281  __attribute__ ((malloc));
282 
293 void* OPCallocAdviced(OPHeap* heap, size_t num, size_t size, int advice)
294  __attribute__ ((malloc));
295 
302 void
303 OPDealloc(void* addr);
304 
312 static inline OPHeap*
313 ObtainOPHeap(void* addr)
314 {
315  return (OPHeap*)((uintptr_t)addr & ~(OPHEAP_SIZE - 1));
316 }
317 
325 static inline opref_t
326 OPPtr2Ref(void* addr)
327 {
328  return (opref_t)addr & (OPHEAP_SIZE - 1);
329 }
330 
339 static inline void*
340 OPRef2Ptr(void* ptr_in_heap, opref_t ref)
341 {
342  return (void*)((opref_t)ObtainOPHeap(ptr_in_heap) + ref);
343 }
344 
352 static inline size_t
354 {
355  return (size_t)(ref >> OPHEAP_BITS);
356 }
357 
358 #ifndef DOXYGEN_SKIP
359 /*
360  * Internal use only. Extracts opref_t part from oplenref_t. This
361  * value could be 0 if the size portion of oplenref_t is smaller than
362  * the container size.
363  *
364  * In most cases, user should use OPLenRef2Ptr instead of this
365  * function.
366  *
367  */
368 static inline opref_t
369 OPLenRef2Ref(oplenref_t ref)
370 {
371  return ref & (OPHEAP_SIZE - 1);
372 }
373 
374 /*
375  * Internal use only. It encodes if a reference is an empty key in
376  * container.
377  */
378 static inline bool
379 OPLenRefIsEmpty(oplenref_t ref)
380 {
381  return ref == 0;
382 }
383 
384 /*
385  * Internal use only. It encodes if a reference is a deleted key in
386  * container.
387  */
388 static inline bool
389 OPLenRefIsDeleted(oplenref_t ref)
390 {
391  return ref == ~0ULL;
392 }
393 #endif
394 
404 static inline void*
405 OPLenRef2Ptr(oplenref_t* ref, size_t container_size)
406 {
407  uintptr_t uintref = (uintptr_t)ref;
408  if (OPLenRefIsEmpty(*ref) || OPLenRefIsDeleted(*ref))
409  return NULL;
410  if (OPLenRef2Size(*ref) > container_size)
411  return OPRef2Ptr(ObtainOPHeap(ref), OPLenRef2Ref(*ref));
412  return (void*)(uintref + sizeof(oplenref_t));
413 }
414 
429 static inline void*
430 OPLenRef2PtrOnHeap(oplenref_t* ref, size_t container_size, OPHeap* heap)
431 {
432  uintptr_t uintref = (uintptr_t)ref;
433  if (OPLenRefIsEmpty(*ref) || OPLenRefIsDeleted(*ref))
434  return NULL;
435  if (OPLenRef2Size(*ref) > container_size)
436  return OPRef2Ptr(heap, OPLenRef2Ref(*ref));
437  return (void*)(uintref + sizeof(oplenref_t));
438 }
439 
460 static inline void
461 OPLenRefCreate(oplenref_t* ref, void* data, size_t data_size,
462  size_t container_size)
463 {
464  uintptr_t uintref = (uintptr_t)ref;
465  if (data_size > OPLENREF_MAX_LEN)
466  {
467  *ref = 0;
468  return;
469  }
470  if (data_size > container_size)
471  {
472  void* ptr;
473  ptr = OPCalloc(ObtainOPHeap(ref), 1, data_size);
474  if (!ptr)
475  {
476  *ref = 0;
477  return;
478  }
479  memcpy(ptr, data, data_size);
480  *ref = (oplenref_t)OPPtr2Ref(ptr);
481  }
482  else
483  {
484  memcpy((void*)(uintref + sizeof(oplenref_t)), data, data_size);
485  *ref = 0;
486  }
487  *ref |= data_size << OPHEAP_BITS;
488 }
489 
501 static inline void
502 OPLenRefDelete(oplenref_t* ref, size_t container_size)
503 {
504  if (OPLenRefIsEmpty(*ref) || OPLenRefIsDeleted(*ref))
505  return;
506  if (OPLenRef2Size(*ref) > container_size)
507  {
508  OPDealloc(OPLenRef2Ptr(ref, container_size));
509  }
510  *ref = ~0ULL;
511 }
512 
526 static inline void
527 OPLenRefRelpace(oplenref_t* ref, void* data, size_t data_size,
528  size_t container_size)
529 {
530  if (OPLenRefIsEmpty(*ref) || OPLenRefIsDeleted(*ref))
531  {
532  OPLenRefCreate(ref, data, data_size, container_size);
533  return;
534  }
535  if (data == OPLenRef2Ptr(ref, container_size))
536  return;
537  if (OPLenRef2Size(*ref) > container_size)
538  {
539  OPDealloc(OPLenRef2Ptr(ref, container_size));
540  }
541  OPLenRefCreate(ref, data, data_size, container_size);
542 }
543 
544 OP_END_DECLS
545 
546 #endif
547 
548 /* op_malloc.h ends here */
void * OPCalloc(OPHeap *heap, size_t num, size_t size) __attribute__((malloc))
Allocate a chunk of memory filled with 0s.
void * OPHeapRestorePtr(OPHeap *heap, int pos)
Restore a pointer from specified root pointer slot.
OPHeap * OPHeapOpen(const char *path, int flags)
OPHeap constructor which opens a memory mapped file to hold the heap.
Memory allocator object with persistent storage on disk.
uintptr_t oplenref_t
Another "pointer type" used within objects created in OPHeap.
Definition: op_malloc.h:135
#define OPHEAP_SIZE
Size of OPHeap.
Definition: op_malloc.h:54
void OPHeapClose(OPHeap *heap)
Flushes the changes in OPHeap to disk, closes the file, and un-maps the memory.
static opref_t OPPtr2Ref(void *addr)
Converts a pointer allocated in OPHeap to an opref_t.
Definition: op_malloc.h:326
static OPHeap * ObtainOPHeap(void *addr)
Given any pointer in the OPHeap, returns the pointer to OPHeap.
Definition: op_malloc.h:313
void OPDealloc(void *addr)
Dealloc an object created by OPHeap.
void OPHeapStorePtr(OPHeap *heap, void *ptr, int pos)
Store a pointer to a root pointer slot in OPHeap.
#define OPHEAP_BITS
Size of OPHeap represented in bits.
Definition: op_malloc.h:48
static void * OPLenRef2Ptr(oplenref_t *ref, size_t container_size)
Converts an oplenref_t reference to a regular pointer.
Definition: op_malloc.h:405
void * OPMalloc(OPHeap *heap, size_t size) __attribute__((malloc))
Allocate an object from OPHeap with given size.
uintptr_t opref_t
The "pointer type" used within objects created by OPHeap.
Definition: op_malloc.h:109
OPHeap * OPHeapOpenTmp()
OPHeap constructor which uses a temporal file to hold the heap.
static void * OPRef2Ptr(void *ptr_in_heap, opref_t ref)
Converts an opref_t reference to a regular pointer.
Definition: op_malloc.h:340
static void OPLenRefCreate(oplenref_t *ref, void *data, size_t data_size, size_t container_size)
A constructor for oplenref_t to hold the input data.
Definition: op_malloc.h:461
void OPHeapMSync(OPHeap *heap)
Flushes changes in OPHeap to the file that holds the heap.
void * OPMallocAdviced(OPHeap *heap, size_t size, int advice) __attribute__((malloc))
Allocate an object of given size with an arena hint.
static void * OPLenRef2PtrOnHeap(oplenref_t *ref, size_t container_size, OPHeap *heap)
Converts an oplenref_t reference to a regular pointer on specified heap.
Definition: op_malloc.h:430
void * OPCallocAdviced(OPHeap *heap, size_t num, size_t size, int advice) __attribute__((malloc))
Allocate a chunk of memory filled with 0s with an arena hint.
#define OPLENREF_MAX_LEN
Maximum size oplenref_t can hold.
Definition: op_malloc.h:143
static void OPLenRefRelpace(oplenref_t *ref, void *data, size_t data_size, size_t container_size)
Relace the data stored in oplenref_t.
Definition: op_malloc.h:527
static void OPLenRefDelete(oplenref_t *ref, size_t container_size)
A destructor for oplenref_t.
Definition: op_malloc.h:502
static size_t OPLenRef2Size(oplenref_t ref)
Obtain the size encoded in oplenref_t.
Definition: op_malloc.h:353