#ifndef DB_H #define DB_H #define MALLOC_ALIGN_MASK (2*sizeof(size_t) - 1) class PgfDB; extern PGF_INTERNAL_DECL __thread unsigned char* current_base __attribute__((tls_model("initial-exec"))); extern PGF_INTERNAL_DECL __thread PgfDB* current_db __attribute__((tls_model("initial-exec"))); struct malloc_state; template class PGF_INTERNAL_DECL ref { private: object offset; friend class PgfDB; 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.as_object(); } bool operator !=(ref& other) const { return offset!=other.as_object(); } 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 PgfDB { private: int fd; const char *filepath; malloc_state* ms; pthread_rwlock_t rwlock; friend class PgfReader; public: PGF_INTERNAL_DECL PgfDB(const char* filepath, int flags, int mode); PGF_INTERNAL_DECL ~PgfDB(); template static ref malloc(size_t extra_bytes=0) { return current_db->malloc_internal(sizeof(A)+extra_bytes); } template static void free(ref o) { return current_db->free_internal(o.as_object()); } static PGF_INTERNAL_DECL ref get_revision(PgfText *name); static PGF_INTERNAL_DECL void set_revision(ref pgf); static PGF_INTERNAL_DECL ref revision2pgf(PgfRevision revision); static PGF_INTERNAL_DECL void link_transient_revision(ref pgf); static PGF_INTERNAL_DECL bool unlink_transient_revision(ref pgf); PGF_INTERNAL_DECL static void sync(); private: PGF_INTERNAL_DECL void init_state(size_t size); PGF_INTERNAL_DECL object malloc_internal(size_t bytes); PGF_INTERNAL_DECL void free_internal(object o); PGF_INTERNAL_DECL object get_root_internal(); PGF_INTERNAL_DECL void set_root_internal(object root_offset); PGF_INTERNAL_DECL 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(PgfDB *db, DB_scope_mode type); ~DB_scope(); private: PgfDB* save_db; DB_scope* next_scope; }; extern PGF_INTERNAL_DECL thread_local DB_scope *last_db_scope; #endif