forked from GitHub/gf-core
concrete revisions not longer take space in the revision registry
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user