#ifndef DB_H #define DB_H #define MALLOC_ALIGN_MASK (2*sizeof(size_t) - 1) class DB; extern PGF_INTERNAL_DECL __thread unsigned char* current_base __attribute__((tls_model("initial-exec"))); extern PGF_INTERNAL_DECL __thread DB* current_db __attribute__((tls_model("initial-exec"))); struct malloc_state; template class PGF_INTERNAL_DECL ref { private: object offset; friend class DB; public: ref() { } ref(object o) { offset = o; } A* operator->() const { return (A*) (current_base+offset); } operator A*() const { return (A*) (current_base+offset); } bool operator ==(ref& other) const { return offset==other->offset; } bool operator !=(ref& other) const { return offset!=other->offset; } bool operator ==(object other_offset) const { return offset==other_offset; } bool operator !=(object other_offset) const { return offset!=other_offset; } ref& operator= (const ref& r) { offset = r.offset; return *this; } static ref from_ptr(A *ptr) { return (((uint8_t*) ptr) - current_base); } object as_object() { return offset; } static object tagged(ref ref) { assert(A::tag < MALLOC_ALIGN_MASK + 1); return (ref.offset | A::tag); } static ref untagged(object v) { return (v & ~MALLOC_ALIGN_MASK); } static uint8_t get_tag(object v) { return (v & MALLOC_ALIGN_MASK); } }; class PGF_INTERNAL_DECL DB { private: int fd; malloc_state* ms; pthread_rwlock_t rwlock; friend class PgfReader; public: DB(const char* pathname, int flags, int mode); ~DB(); template static ref malloc() { return current_db->malloc_internal(sizeof(A)); } template static ref malloc(size_t bytes) { return current_db->malloc_internal(bytes); } template static ref get_root() { return current_db->get_root_internal(); } template static void set_root(ref root) { current_db->set_root_internal(root.offset); } static void sync(); private: void init_state(size_t size); object malloc_internal(size_t bytes); void free_internal(object o); object get_root_internal(); void set_root_internal(object root_offset); unsigned char* relocate(unsigned char* ptr); friend class DB_scope; }; enum DB_scope_mode {READER_SCOPE, WRITER_SCOPE}; class PGF_INTERNAL_DECL DB_scope { public: DB_scope(DB *db, DB_scope_mode type); ~DB_scope(); private: DB* save_db; DB_scope* next_scope; }; extern PGF_INTERNAL_DECL thread_local DB_scope *last_db_scope; #endif