/* * pvector_pop_back -- decreases the number of values and executes * a user-defined callback in which the caller must zero the value. */ uint64_t pvector_pop_back(struct pvector_context *ctx, entry_op_callback cb) { if (ctx->nvalues == 0) return 0; uint64_t idx = ctx->nvalues - 1; struct array_spec s = pvector_get_array_spec(idx); uint64_t *arrp = OBJ_OFF_TO_PTR(ctx->pop, ctx->vec->arrays[s.idx]); uint64_t ret = arrp[s.pos]; if (cb) cb(ctx->pop, &arrp[s.pos]); if (s.pos == 0 && s.idx != 0 /* the array 0 is embedded */) { #ifdef USE_VG_PMEMCHECK if (On_valgrind) { size_t usable_size = sizeof(uint64_t) * (1ULL << (s.idx + PVECTOR_INIT_SHIFT)); VALGRIND_REMOVE_FROM_TX(arrp, usable_size); } #endif pfree(ctx->pop, &ctx->vec->arrays[s.idx]); } ctx->nvalues--; return ret; }
/* * pvector_get -- returns the vector value at the index. */ static uint64_t pvector_get(PMEMobjpool *pop, struct pvector *vec, uint64_t idx) { struct array_spec s = pvector_get_array_spec(idx); uint64_t *arrp = OBJ_OFF_TO_PTR(pop, vec->arrays[s.idx]); return arrp[s.pos]; }
/* * pvector_push_back -- bumps the number of values in the vector and returns * the pointer to the value position to which the caller must set the * value. Calling this method without actually setting the value will * result in an inconsistent vector state. */ uint64_t * pvector_push_back(struct pvector_context *ctx) { uint64_t idx = ctx->nvalues; struct array_spec s = pvector_get_array_spec(idx); if (s.idx >= PVECTOR_MAX_ARRAYS) { ERR("Exceeded maximum number of entries in persistent vector"); return NULL; } PMEMobjpool *pop = ctx->pop; /* * If the destination array does not exist, calculate its size * and allocate it. */ if (ctx->vec->arrays[s.idx] == 0) { if (s.idx == 0) { /* * In the case the vector is completely empty the * initial embedded array must be assigned as the first * element of the sequence. */ ASSERTeq(util_is_zeroed(ctx->vec, sizeof(*ctx->vec)), 1); ctx->vec->arrays[0] = OBJ_PTR_TO_OFF(pop, &ctx->vec->embedded); pmemops_persist(&pop->p_ops, &ctx->vec->arrays[0], sizeof(ctx->vec->arrays[0])); } else { size_t arr_size = sizeof(uint64_t) * (1ULL << (s.idx + PVECTOR_INIT_SHIFT)); if (pmalloc_construct(pop, &ctx->vec->arrays[s.idx], arr_size, pvector_array_constr, NULL, 0, OBJ_INTERNAL_OBJECT_MASK, 0) != 0) return NULL; } } ctx->nvalues++; uint64_t *arrp = OBJ_OFF_TO_PTR(pop, ctx->vec->arrays[s.idx]); return &arrp[s.pos]; }