1
0
forked from GitHub/gf-core

concrete revisions not longer take space in the revision registry

This commit is contained in:
Krasimir Angelov
2024-09-21 11:56:19 +02:00
parent 8878eddb7d
commit 43671f3679
7 changed files with 118 additions and 57 deletions

View File

@@ -33,7 +33,7 @@ convertFile conf src file = do
(ex, end) = break (=='"') (tail exend)
in ((unwords (words cat),ex), tail end) -- quotes ignored
pgf = resource_pgf conf
lang = language conf
lang = concrete conf
convEx (cat,ex) = do
appn "("
let typ = maybe (error "no valid cat") id $ readType cat
@@ -61,7 +61,7 @@ convertFile conf src file = do
data ExConfiguration = ExConf {
resource_pgf :: PGF,
verbose :: Bool,
language :: Concr,
concrete :: Concr,
printExp :: Expr -> String
}

View File

@@ -397,8 +397,6 @@ struct PGF_INTERNAL_DECL PgfLRState {
};
struct PGF_INTERNAL_DECL PgfConcr {
static const uint8_t tag = 1;
Namespace<PgfFlag> cflags;
Namespace<PgfConcrLin> lins;
Namespace<PgfConcrLincat> lincats;
@@ -413,8 +411,6 @@ struct PGF_INTERNAL_DECL PgfConcr {
};
struct PGF_INTERNAL_DECL PgfPGF {
static const uint8_t tag = 0;
uint16_t major_version;
uint16_t minor_version;
Namespace<PgfFlag> gflags;

View File

@@ -131,7 +131,7 @@ struct PGF_INTERNAL_DECL malloc_state
object free_descriptors;
size_t n_revisions;
object active_revision;
PgfRevision active_revision;
revision_entry revisions[];
};
@@ -484,7 +484,7 @@ txn_t PgfDB::get_txn_id() {
}
PGF_INTERNAL
object PgfDB::register_revision(object o, txn_t txn_id)
PgfRevision PgfDB::register_revision(object o, txn_t txn_id)
{
#ifndef _WIN32
pthread_mutex_lock(&ms->rev_mutex);
@@ -564,7 +564,7 @@ object PgfDB::register_revision(object o, txn_t txn_id)
}
PGF_INTERNAL
void PgfDB::unregister_revision(object revision)
PgfConcrRevision PgfDB::register_concr_revision(PgfRevision revision, size_t index)
{
if (revision == 0 || revision-1 >= ms->n_revisions)
throw pgf_error("Invalid revision");
@@ -573,6 +573,40 @@ void PgfDB::unregister_revision(object revision)
if (entry->ref_count == 0)
throw pgf_error("Invalid revision");
// The index must be at most 16 bits long
if (((index+1) & ((1 << 16) - 1)) != (index+1))
throw pgf_error("Invalid revision");
#ifndef _WIN32
pthread_mutex_lock(&ms->rev_mutex);
#else
WaitForSingleObject(hRevMutex, INFINITE);
#endif
entry->ref_count++;
#ifndef _WIN32
pthread_mutex_unlock(&ms->rev_mutex);
#else
ReleaseMutex(hRevMutex);
#endif
return revision | ((index+1) << 16);
}
PGF_INTERNAL
void PgfDB::unregister_revision(PgfRevision revision)
{
// Take a way the higher bits for a concrete revision
revision &= ((1 << 16) - 1);
if (revision == 0 || revision-1 >= ms->n_revisions)
throw pgf_error("Invalid revision");
revision_entry *entry = &ms->revisions[revision-1];
if (entry->ref_count == 0)
throw pgf_error("Invalid revision");
#ifndef _WIN32
pthread_mutex_lock(&ms->rev_mutex);
#else
@@ -700,7 +734,7 @@ void PgfDB::cleanup_state()
}
PGF_INTERNAL
object PgfDB::get_active_revision()
PgfRevision PgfDB::get_active_revision()
{
return current_db->ms->active_revision;
}
@@ -1457,7 +1491,7 @@ void PgfDB::free_internal(object o, size_t bytes)
}
PGF_INTERNAL
ref<PgfPGF> PgfDB::revision2pgf(PgfRevision revision, size_t *p_txn_id)
ref<PgfPGF> PgfDB::revision2pgf(PgfRevision revision)
{
if (revision == 0 || revision-1 >= ms->n_revisions)
throw pgf_error("Invalid revision");
@@ -1466,22 +1500,18 @@ ref<PgfPGF> PgfDB::revision2pgf(PgfRevision revision, size_t *p_txn_id)
if (entry->ref_count == 0)
throw pgf_error("Invalid revision");
if (ref<PgfPGF>::get_tag(entry->o) != PgfPGF::tag)
if (entry->o >= top)
throw pgf_error("Invalid revision");
ref<PgfPGF> pgf = ref<PgfPGF>::untagged(entry->o);
if (pgf.as_object() >= top)
throw pgf_error("Invalid revision");
if (p_txn_id != NULL)
*p_txn_id = entry->txn_id;
return pgf;
return entry->o;
}
PGF_INTERNAL
ref<PgfConcr> PgfDB::revision2concr(PgfConcrRevision revision, size_t *p_txn_id)
ref<PgfConcr> PgfDB::revision2concr(PgfConcrRevision concr_revision)
{
PgfRevision revision = concr_revision & ((1 << 16) - 1);
size_t index = concr_revision >> 16;
if (revision == 0 || revision-1 >= ms->n_revisions)
throw pgf_error("Invalid revision");
@@ -1489,16 +1519,14 @@ ref<PgfConcr> PgfDB::revision2concr(PgfConcrRevision revision, size_t *p_txn_id)
if (entry->ref_count == 0)
throw pgf_error("Invalid revision");
if (ref<PgfPGF>::get_tag(entry->o) != PgfConcr::tag)
ref<PgfPGF> pgf = entry->o;
if (pgf.as_object() >= top)
throw pgf_error("Invalid revision");
ref<PgfConcr> concr = ref<PgfConcr>::untagged(entry->o);
if (concr.as_object() >= top)
ref<PgfConcr> concr = namespace_index(pgf->concretes, index-1);
if (concr == 0)
throw pgf_error("Invalid revision");
if (p_txn_id != NULL)
*p_txn_id = entry->txn_id;
return concr;
}
@@ -1558,7 +1586,7 @@ void PgfDB::commit(object o)
object save_top = ms->top;
object save_free_blocks = ms->free_blocks;
object save_free_descriptors = ms->free_descriptors;
object save_active_revision = ms->active_revision;
PgfRevision save_active_revision = ms->active_revision;
#ifndef _WIN32
int res;

View File

@@ -124,12 +124,13 @@ public:
current_db->free_internal(o.as_object(), sizeof(A)+extra_bytes);
}
PGF_INTERNAL_DECL object get_active_revision();
PGF_INTERNAL_DECL object register_revision(object o, txn_t txn_id);
PGF_INTERNAL_DECL void unregister_revision(object o);
PGF_INTERNAL_DECL PgfRevision get_active_revision();
PGF_INTERNAL_DECL PgfRevision register_revision(object o, txn_t txn_id);
PGF_INTERNAL_DECL PgfConcrRevision register_concr_revision(PgfRevision revision, size_t index);
PGF_INTERNAL_DECL void unregister_revision(PgfRevision o);
PGF_INTERNAL_DECL ref<PgfPGF> revision2pgf(PgfRevision revision, size_t *p_txn_id = NULL);
PGF_INTERNAL_DECL ref<PgfConcr> revision2concr(PgfConcrRevision revision, size_t *p_txn_id = NULL);
PGF_INTERNAL_DECL ref<PgfPGF> revision2pgf(PgfRevision revision);
PGF_INTERNAL_DECL ref<PgfConcr> revision2concr(PgfConcrRevision concr_revision);
PGF_INTERNAL_DECL void start_transaction();
PGF_INTERNAL_DECL void set_transaction_object(object o);

View File

@@ -606,6 +606,41 @@ ref<V> namespace_lookup(Namespace<V> map, PgfText *name)
return 0;
}
template <class V>
ref<V> namespace_lookup_index(Namespace<V> map, PgfText *name, size_t *pIndex)
{
*pIndex = 0;
while (map != 0) {
int cmp = textcmp(name,&map->value->name);
if (cmp < 0) {
map = map->left;
} else if (cmp > 0) {
map = map->right;
*pIndex += Node<ref<V>>::size(map->left)+1;
} else {
return map->value;
}
}
return 0;
}
template <class V>
ref<V> namespace_index(Namespace<V> map, size_t index)
{
while (map != 0) {
size_t sz = Node<ref<V>>::size(map->left);
if (index < sz) {
map = map->left;
} else if (index > sz) {
map = map->right;
index -= sz+1;
} else {
return map->value;
}
}
return 0;
}
template <class V>
size_t namespace_size(Namespace<V> map)
{

View File

@@ -71,7 +71,7 @@ PgfDB *pgf_read_pgf(const char* fpath, PgfRevision *revision,
db->set_transaction_object(pgf.as_object());
*revision = db->register_revision(pgf.tagged(), PgfDB::get_txn_id());
*revision = db->register_revision(pgf.as_object(), PgfDB::get_txn_id());
db->commit(pgf.as_object());
}
@@ -126,7 +126,7 @@ PgfDB *pgf_boot_ngf(const char* pgf_path, const char* ngf_path,
db->set_transaction_object(pgf.as_object());
*revision = db->register_revision(pgf.tagged(), PgfDB::get_txn_id());
*revision = db->register_revision(pgf.as_object(), PgfDB::get_txn_id());
db->commit(pgf.as_object());
}
@@ -199,7 +199,7 @@ PgfDB *pgf_boot_ngf_cookie(void *cookie,
db->set_transaction_object(pgf.as_object());
*revision = db->register_revision(pgf.tagged(), PgfDB::get_txn_id());
*revision = db->register_revision(pgf.as_object(), PgfDB::get_txn_id());
db->commit(pgf.as_object());
}
@@ -234,7 +234,7 @@ PgfDB *pgf_read_ngf(const char *fpath,
ref<PgfPGF> pgf = db->get_active_revision();
*revision = 0;
if (pgf != 0) {
*revision = db->register_revision(pgf.tagged(), PgfDB::get_txn_id()-1);
*revision = db->register_revision(pgf.as_object(), PgfDB::get_txn_id()-1);
db->ref_count++;
}
}
@@ -284,7 +284,7 @@ PgfDB *pgf_new_ngf(PgfText *abstract_name,
db->set_transaction_object(pgf.as_object());
*revision = db->register_revision(pgf.tagged(), PgfDB::get_txn_id());
*revision = db->register_revision(pgf.as_object(), PgfDB::get_txn_id());
db->commit(pgf.as_object());
}
@@ -469,14 +469,14 @@ void pgf_iter_concretes(PgfDB *db, PgfRevision revision,
PgfItor *itor, PgfExn *err)
{
PGF_API_BEGIN {
size_t txn_id;
DB_scope scope(db, READER_SCOPE);
ref<PgfPGF> pgf = db->revision2pgf(revision, &txn_id);
ref<PgfPGF> pgf = db->revision2pgf(revision);
size_t index = 0;
std::function<bool(ref<PgfConcr>)> f =
[txn_id,db,itor,err](ref<PgfConcr> concr) {
object rev = db->register_revision(concr.tagged(), txn_id);
[db,revision,itor,err,&index](ref<PgfConcr> concr) {
PgfConcrRevision rev = db->register_concr_revision(revision, index);
index++;
db->ref_count++;
itor->fn(itor, &concr->name, rev, err);
return (err->type == PGF_EXN_NONE);
@@ -490,18 +490,17 @@ PgfConcrRevision pgf_get_concrete(PgfDB *db, PgfRevision revision,
PgfText *name, PgfExn *err)
{
PGF_API_BEGIN {
size_t txn_id;
DB_scope scope(db, READER_SCOPE);
ref<PgfPGF> pgf = db->revision2pgf(revision, &txn_id);
ref<PgfPGF> pgf = db->revision2pgf(revision);
size_t index;
ref<PgfConcr> concr =
namespace_lookup(pgf->concretes, name);
namespace_lookup_index(pgf->concretes, name, &index);
if (concr == 0)
return 0;
db->ref_count++;
return db->register_revision(concr.tagged(), txn_id);
return db->register_concr_revision(revision, index);
} PGF_API_END
return 0;
@@ -1425,7 +1424,7 @@ PgfRevision pgf_start_transaction(PgfDB *db, PgfExn *err)
db->set_transaction_object(new_pgf.as_object());
object rev = db->register_revision(new_pgf.tagged(), PgfDB::get_txn_id());
object rev = db->register_revision(new_pgf.as_object(), PgfDB::get_txn_id());
PgfDB::free(pgf);
@@ -1456,7 +1455,7 @@ PgfRevision pgf_checkout_revision(PgfDB *db, PgfExn *err)
ref<PgfPGF> pgf = db->get_active_revision();
object rev = 0;
if (pgf != 0) {
rev = db->register_revision(pgf.tagged(), PgfDB::get_txn_id()-1);
rev = db->register_revision(pgf.as_object(), PgfDB::get_txn_id()-1);
db->ref_count++;
}
return rev;
@@ -1689,8 +1688,9 @@ PgfConcrRevision pgf_create_concrete(PgfDB *db, PgfRevision revision,
ref<PgfPGF> pgf = db->revision2pgf(revision);
size_t index;
ref<PgfConcr> concr =
namespace_lookup(pgf->concretes, name);
namespace_lookup_index(pgf->concretes, name, &index);
if (concr != 0)
throw pgf_error("The concrete syntax already exists");
@@ -1702,8 +1702,6 @@ PgfConcrRevision pgf_create_concrete(PgfDB *db, PgfRevision revision,
concr->printnames = 0;
memcpy(&concr->name, name, sizeof(PgfText)+name->size+1);
object rev = db->register_revision(concr.tagged(), PgfDB::get_txn_id());
Namespace<PgfConcr> concrs =
namespace_insert(pgf->concretes, concr);
if (concrs == 0) {
@@ -1711,6 +1709,8 @@ PgfConcrRevision pgf_create_concrete(PgfDB *db, PgfRevision revision,
}
pgf->concretes = concrs;
object rev = db->register_concr_revision(revision, index);
db->ref_count++;
return rev;
} PGF_API_END
@@ -1726,15 +1726,16 @@ PgfConcrRevision pgf_clone_concrete(PgfDB *db, PgfRevision revision,
DB_scope scope(db, WRITER_SCOPE);
ref<PgfPGF> pgf = db->revision2pgf(revision);
size_t index;
ref<PgfConcr> concr =
namespace_lookup(pgf->concretes, name);
namespace_lookup_index(pgf->concretes, name, &index);
if (concr == 0)
throw pgf_error("Unknown concrete syntax");
concr = clone_concrete(pgf, concr);
object rev = db->register_revision(concr.tagged(), PgfDB::get_txn_id());
object rev = db->register_concr_revision(revision, index);
db->ref_count++;
return rev;
} PGF_API_END

View File

@@ -178,7 +178,7 @@ foreign import ccall pgf_iter_categories :: Ptr PgfDB -> Ptr PGF -> Ptr PgfItor
foreign import ccall pgf_iter_concretes :: Ptr PgfDB -> Ptr PGF -> Ptr PgfItor -> Ptr PgfExn -> IO ()
foreign import ccall pgf_get_concrete :: Ptr PgfDB -> Ptr PGF -> Ptr PgfItor -> Ptr PgfExn -> IO (Ptr Concr)
foreign import ccall pgf_get_concrete :: Ptr PgfDB -> Ptr PGF -> Ptr PgfText -> Ptr PgfExn -> IO (Ptr Concr)
foreign import ccall pgf_start_cat :: Ptr PgfDB -> Ptr PGF -> Ptr PgfUnmarshaller -> Ptr PgfExn -> IO (StablePtr Type)