In this diff, I added the arc_swap crate to allow for efficient committing of proposals. The reason to use this crate is that for a nested proposal, we need to traverse the parents. One of the parents might have just been committed, and so the list of modified nodes changes. These nodes are duplicated in the new member of ImmutableProposal so we don't need to use the general node cache to read them, but we could if the transaction has been committed.
Since it doesn't actually matter which we use (the ImmutableProposal or the Committed state) we can safely ArcSwap from one to the other during commit, avoiding any locking of the parent field. This is important since these proposals are in-memory and are immutable anyway.
To properly implement the parenting, NodeStore has to now use Arc<ImmutableProposal> as the kind since this Arc is also used as a NodeStoreParent and you could have multiple proposals pointing at the same parent.
The challenging part of this was constructing new ImmutableProposals since the parent is now in an Arc. Currently, the code creates an ImmutableProposal and allocates the nodes into a separate list, then construct a new ImmutableProposal once we have all the parts. There might be a better way to do this. One idea is a new NodeStore.kind, maybe PendingProposal, to use as an intermediate when the proposal is still mutating, but this seemed like more work.
Still TODO is to add tests at the revision manager layer; we only test the reparent function itself here.
In this diff, I added the
arc_swap
crate to allow for efficient committing of proposals. The reason to use this crate is that for a nested proposal, we need to traverse the parents. One of the parents might have just been committed, and so the list of modified nodes changes. These nodes are duplicated in thenew
member ofImmutableProposal
so we don't need to use the general node cache to read them, but we could if the transaction has been committed.Since it doesn't actually matter which we use (the ImmutableProposal or the Committed state) we can safely ArcSwap from one to the other during commit, avoiding any locking of the parent field. This is important since these proposals are in-memory and are immutable anyway.
To properly implement the parenting,
NodeStore
has to now useArc<ImmutableProposal>
as thekind
since thisArc
is also used as aNodeStoreParent
and you could have multiple proposals pointing at the same parent.The challenging part of this was constructing new ImmutableProposals since the parent is now in an
Arc
. Currently, the code creates anImmutableProposal
and allocates the nodes into a separate list, then construct a new ImmutableProposal once we have all the parts. There might be a better way to do this. One idea is a newNodeStore.kind
, maybePendingProposal
, to use as an intermediate when the proposal is still mutating, but this seemed like more work.Still TODO is to add tests at the revision manager layer; we only test the reparent function itself here.