libpmemobj-cpp
libpmemobj-cpp copied to clipboard
Allow calling local() method from enumerable_thread_specific inside transaction.
FEAT: Allow calling local() method from enumerable_thread_specific inside transaction.
Rationale
The current requirement (local() cannot be called inside tx) makes a lot of optimizations impossible. For one example see: https://github.com/pmem/libpmemobj-cpp/issues/944
Description
In local() method we sometimes need to allocate new segment in the underlying segment_vector (if we run out of space). In current algorithm, we allocate the segment under the lock and then set an atomic variable to indicate that the storage growed. Other thread will access new segment only after seeing updated atomic variable (at which point, the segment is already committed).
The problem with allowing outer transactions is that the segment would be committed at some later point which would lead to uncommitted reads from other threads.
The solution to that is to use either action based API for segment allocation or use transaction with separate context (i.e. an independent tx but there is no support fot that in PMDK yet).
API Changes
None. (local() can be called from within a tx)
Implementation details
For action based approach: Implement segment_vector::resize_intent(count) method which would return an intent object which can be published in an atomic action. (Alternatively implement atomic resize() method which uses redo logs internally).
For separate transaction approach:
- Add support for PMDK (rebase https://github.com/wojtuss/pmdk/commit/da57304)
- Use PMDK new API's
Meta
For action based approach, if pmemobj_set_value would be concurrency-atomic we could even get rid of cached_size variable in enumerable_thread_specific.