diff --git a/src/runtime/c/pgf/db.cxx b/src/runtime/c/pgf/db.cxx index 848ad6a86..1eb6afe67 100644 --- a/src/runtime/c/pgf/db.cxx +++ b/src/runtime/c/pgf/db.cxx @@ -1027,29 +1027,32 @@ object PgfDB::delete_block_descriptor(object map, size_t *psize, object *po) fit: *po = descr->o; + object new_map; + if (descr->left == 0) { + new_map = descr->right; + } else if (descr->right == 0) { + new_map = descr->left; + } else { + if (ptr(block_descr,descr->left)->sz > ptr(block_descr,descr->right)->sz) { + object right = descr->right; + object left = pop_last_block_descriptor(descr->left, &new_map); + new_map = upd_block_descr(new_map, left, right); + new_map = balanceR_block_descriptor(new_map); + } else { + object left = descr->left; + object right = pop_first_block_descriptor(descr->right, &new_map); + new_map = upd_block_descr(new_map, left, right); + new_map = balanceL_block_descriptor(new_map); + } + } + int index = (descr->descr_txn_id != ms->curr_txn_id); descr->chain = free_descriptors[index]; free_descriptors[index] = map; if (index == 1 && free_descriptors[2] == 0) free_descriptors[2] = map; - if (descr->left == 0) { - return descr->right; - } else if (descr->right == 0) { - return descr->left; - } else { - if (ptr(block_descr,descr->left)->sz > ptr(block_descr,descr->right)->sz) { - object right = descr->right; - object left = pop_last_block_descriptor(descr->left, &map); - map = upd_block_descr(map, left, right); - return balanceR_block_descriptor(map); - } else { - object left = descr->left; - object right = pop_first_block_descriptor(descr->right, &map); - map = upd_block_descr(map, left, right); - return balanceL_block_descriptor(map); - } - } + return new_map; } } @@ -1125,7 +1128,7 @@ object PgfDB::malloc_internal(size_t bytes) } PGF_INTERNAL -object PgfDB::realloc_internal(object oldo, size_t old_bytes, size_t new_bytes) +object PgfDB::realloc_internal(object oldo, size_t old_bytes, size_t new_bytes, txn_t txn_id) { if (oldo == 0) return malloc_internal(new_bytes); @@ -1133,31 +1136,36 @@ object PgfDB::realloc_internal(object oldo, size_t old_bytes, size_t new_bytes) size_t old_nb = request2size(old_bytes); size_t new_nb = request2size(new_bytes); - if (oldo + old_nb == top) { - ssize_t nb = new_nb-old_nb; - ssize_t free_size = mmap_size - top; + if (txn_id == ms->curr_txn_id) { + if (old_nb == new_nb) + return oldo; - if (nb > free_size) { - size_t alloc_size = - ((nb - free_size + page_size - 1) / page_size) * page_size; - size_t new_size = - ms->file_size + alloc_size; + if (oldo + old_nb == top) { + ssize_t nb = new_nb-old_nb; + ssize_t free_size = mmap_size - top; - resize_map(new_size); - } + if (nb > free_size) { + size_t alloc_size = + ((nb - free_size + page_size - 1) / page_size) * page_size; + size_t new_size = + ms->file_size + alloc_size; - // If the object is at the end of the allocation area - top += nb; + resize_map(new_size); + } + + // If the object is at the end of the allocation area + top += nb; #ifdef DEBUG_MEMORY_ALLOCATOR - fprintf(stderr, "realloc_internal(%016lx,%ld,%ld)\n", oldo, old_bytes, new_bytes); + fprintf(stderr, "realloc_internal(%016lx,%ld,%ld)\n", oldo, old_bytes, new_bytes); #endif - return oldo; + return oldo; + } } object newo = malloc_internal(new_bytes); - memcpy(base+newo, base+oldo, old_bytes < new_bytes ? old_bytes : new_bytes); + memcpy(base+newo, base+oldo, (old_bytes < new_bytes) ? old_bytes : new_bytes); free_internal(oldo, old_bytes); return newo; } diff --git a/src/runtime/c/pgf/db.h b/src/runtime/c/pgf/db.h index e76ba90a2..d471a5406 100644 --- a/src/runtime/c/pgf/db.h +++ b/src/runtime/c/pgf/db.h @@ -103,8 +103,8 @@ public: } template - static ref realloc(ref r, size_t old_extra_bytes, size_t new_extra_bytes) { - return current_db->realloc_internal(r.as_object(), sizeof(A)+old_extra_bytes, sizeof(A)+new_extra_bytes); + static ref realloc(ref r, size_t old_extra_bytes, size_t new_extra_bytes, txn_t txn_id) { + return current_db->realloc_internal(r.as_object(), sizeof(A)+old_extra_bytes, sizeof(A)+new_extra_bytes, txn_id); } template @@ -144,7 +144,7 @@ private: PGF_INTERNAL_DECL object malloc_internal(size_t bytes); - PGF_INTERNAL_DECL object realloc_internal(object oldo, size_t old_bytes, size_t new_bytes); + PGF_INTERNAL_DECL object realloc_internal(object oldo, size_t old_bytes, size_t new_bytes, txn_t txn_id); PGF_INTERNAL_DECL void free_internal(object o, size_t bytes); diff --git a/src/runtime/c/pgf/pgf.cxx b/src/runtime/c/pgf/pgf.cxx index 363d5808f..340f7d9ba 100644 --- a/src/runtime/c/pgf/pgf.cxx +++ b/src/runtime/c/pgf/pgf.cxx @@ -1847,7 +1847,7 @@ public: size_t len = entry->backrefs->len; ref> backrefs = - vector_unsafe_resize(entry->backrefs, len+1); + vector_resize(entry->backrefs, len+1, PgfDB::get_txn_id()); backrefs->data[len].container = container; backrefs->data[len].seq_index = seq_index; entry->backrefs = backrefs; diff --git a/src/runtime/c/pgf/phrasetable.cxx b/src/runtime/c/pgf/phrasetable.cxx index 38fa7da64..1f00ce62f 100644 --- a/src/runtime/c/pgf/phrasetable.cxx +++ b/src/runtime/c/pgf/phrasetable.cxx @@ -270,13 +270,12 @@ PgfPhrasetable phrasetable_internalize(PgfPhrasetable table, : 0; ref> backrefs = - vector_copy(table->value.backrefs, len+1); + vector_resize(table->value.backrefs, len+1, table->txn_id); backrefs->data[len].container = container; backrefs->data[len].seq_index = seq_index; PgfPhrasetable new_table = Node::upd_node(table, table->left, table->right); - Vector::release(new_table->value.backrefs); new_table->value.backrefs = backrefs; *pentry = ref::from_ptr(&new_table->value); return new_table; @@ -299,7 +298,7 @@ ref phrasetable_relink(PgfPhrasetable table, : table->value.backrefs->len; ref> backrefs = - vector_unsafe_resize(table->value.backrefs, len+1); + vector_resize(table->value.backrefs, len+1, table->txn_id); backrefs->data[len].container = container; backrefs->data[len].seq_index = seq_index; table->value.backrefs = backrefs; @@ -342,29 +341,25 @@ PgfPhrasetable phrasetable_delete(PgfPhrasetable table, size_t len = table->value.backrefs->len; if (len > 1) { ref> backrefs = - vector_new(len-1); + vector_resize(table->value.backrefs, len-1, table->txn_id); size_t i = 0; while (i < len) { - ref backref = - vector_elem(table->value.backrefs, i); + ref backref = + vector_elem(backrefs, i); if (backref->container == container && backref->seq_index == seq_index) { break; } - *vector_elem(backrefs, i) = *backref; i++; } i++; while (i < len) { - ref backref = - vector_elem(table->value.backrefs, i); - *vector_elem(backrefs, i-1) = *backref; + *vector_elem(backrefs, i-1) = *vector_elem(backrefs, i); i++; } PgfPhrasetable new_table = Node::upd_node(table, table->left, table->right); - Vector::release(new_table->value.backrefs); new_table->value.backrefs = backrefs; return new_table; } else { diff --git a/src/runtime/c/pgf/vector.h b/src/runtime/c/pgf/vector.h index fd7e36585..0a03b813f 100644 --- a/src/runtime/c/pgf/vector.h +++ b/src/runtime/c/pgf/vector.h @@ -31,55 +31,20 @@ ref vector_new(Vector C::* field, size_t len) PGF_INTERNAL_DECL size_t get_next_padovan(size_t min); -/* Resize a vector by creating a new one and copying the old content. - * The new vector is now also safe to update */ -template inline PGF_INTERNAL -ref> vector_copy(ref> vec, size_t len) -{ - size_t size = len*sizeof(A); - ref> res = PgfDB::malloc>(size); - res->len = len; - memcpy(res->data, vec->data, size); - return res; -} - /* Resize a vector by changing its length. If there is no enough space * the implementation will create a copy, but whenever possible it will - * return the reference of the original vector. In the later case, it - * changes the length in-place which means that the function is safe - * only if the vector was created during the current transaction. */ + * return the reference to the original vector. A copy is created also + * if txn_id is different from the current transaction. In this way + * it is safe to change the length. */ template inline PGF_INTERNAL -ref> vector_unsafe_resize(ref> vec, size_t len) +ref> vector_resize(ref> vec, size_t len, txn_t txn_id) { + size_t new_len = get_next_padovan(len); size_t old_len = get_next_padovan(vec->len); - size_t new_len = get_next_padovan(len); - if (old_len == new_len) - return vec; - - ref> res = PgfDB::realloc>(vec,old_len*sizeof(A),new_len*sizeof(A)).as_object(); - res->len = len; - return res; -} - -/* Resize a vector embedded in another structure, by changing its length. - * If there is no enough space the implementation will copy the structure, - * but whenever possible it will return a reference to - * the original structure. In the later case, it changes - * the vector's length in-place which means that the function is safe - * only if the structure was created during the current transaction. */ -template inline PGF_INTERNAL -ref vector_unsafe_resize(ref r, Vector C::* field, size_t len) -{ - size_t old_len = get_next_padovan((r->*field).len); - size_t new_len = get_next_padovan(len); - - if (old_len == new_len) - return r; - - ref res = PgfDB::realloc(r,old_len*sizeof(A),new_len*sizeof(A)).as_object(); - (res->*field).len = len; - return res; + vec = PgfDB::realloc>(vec,old_len*sizeof(A),new_len*sizeof(A),txn_id); + vec->len = len; + return vec; } template inline PGF_INTERNAL