Struct orx_selfref_col::SelfRefColMut
source · pub struct SelfRefColMut<'rf, 'a, V, T, P = SplitVec<Node<'a, V, T>>>{ /* private fields */ }
Expand description
Struct allowing to safely, conveniently and efficiently mutate a self referential collection.
§Safety
This struct holds a mutable reference to the underlying self referential collection. Therefore, it allows to mutate the vector with immutable references, as in internal mutability of a refcell.
This struct cannot be created externally.
It is only constructed by SelfRefCol
s move_mutate
and mutate_take
methods.
§move_mutate
Move-mutate accepts a lambda having an access to SelfRefColMut
to mutate the vector and an additional value which is moved into the lambda.
The method does not return a value.
Note that the lambda is a function pointer rather than a closure. Therefore,
- a reference external to the vector cannot be leaked in;
- a reference to an element of the vector cannot leak out.
Thus the compactness of the self referential collection is preserved.
§mutate_take
Mutate-take takes a single parameter, a lambda having an access to SelfRefColMut
to mutate the vector.
The method returns a value of element type T
.
In other words, it takes out a value from the vector and returns it.
Note that the lambda is a function pointer rather than a closure. Therefore,
- a reference external to the vector cannot be leaked in;
- a reference to an element of the vector cannot leak out, note that the return type is strictly an owned value of the element type.
Thus the compactness of the self referential collection is preserved.
Mutations of the references of the self referential collection are conveniently handled by methods of SelfRefNode
.
However, all these methods require a reference to a SelfRefColMut
.
In other words, SelfRefColMut
is the key to enable these mutations.
The safety is then guaranteed by the following:
SelfRefColMut
is never explicitly constructed by the caller. The caller only provides definition of the mutations in the form of a lambda, which is specifically afn
as explained above.SelfRefCol
methodsmove_mutate
andmutate_take
require a mutable reference to the vector; and hence, there might be only at most oneSelfRefColMut
instance at any given time.- Inside the lambda, however, multiple mutations are easily enabled and allowed with the guarantees of the encapsulation.
§move_mutate_take
As the name suggests, this method is the combination of the prior two:
- we move a value to the non-capturing lambda,
- we mutate references and the collection encapsulated inside the lambda using the key,
- we take one element out.
This method is most suitable for operations involving swaps.
§Convenience
The nodes of the self referential collection, SelfRefNode
, has convenient methods to mutate the references, such as:
set_prev
set_next
clear_next
clear_prev
close_node_take_data
In addition, SelfRefColMut
provides the following vector methods:
push_get_ref
set_ends
These allow to easily and conveniently update the relations among the nodes without lifetime or ownership complexities.
§Example
For instance, the following example illustrates the push_front
method in a doubly linked list.
The lambda argument x
is a SelfRefColMut
.
You might notice that the lambda body is close enough to the pseudocode of the method.
All complexity of the safety guarantees is hidden by the additional parameter or the key, x
, passed into these mut methods.
pub fn push_front(&mut self, value: T) {
self.vec
.move_mutate(value, |x, value| match x.ends().front() {
None => {
let node = x.push_get_ref(value);
x.set_ends([Some(node), Some(node)]);
}
Some(prior_front) => {
let new_front = x.push_get_ref(value);
new_front.set_next(&x, prior_front);
prior_front.set_prev(&x, new_front);
x.set_ends([Some(new_front), x.ends().back()]);
}
});
self.len += 1;
}
Implementations§
source§impl<'rf, 'a, V, T, P> SelfRefColMut<'rf, 'a, V, T, P>
impl<'rf, 'a, V, T, P> SelfRefColMut<'rf, 'a, V, T, P>
sourcepub fn node_utilization(&self) -> f32
pub fn node_utilization(&self) -> f32
Returns the node utilization as a fraction of active nodes to the used nodes:
- 1.0 when there is no closed node;
- 0.0 when all used memory is used by closed nodes.
source§impl<'rf, 'a, V, T, P> SelfRefColMut<'rf, 'a, V, T, P>
impl<'rf, 'a, V, T, P> SelfRefColMut<'rf, 'a, V, T, P>
sourcepub fn reclaim_closed_nodes(&self)where
P: 'a,
pub fn reclaim_closed_nodes(&self)where
P: 'a,
Manually attempts to reclaim closed nodes.
sourcepub fn first_node<'b>(&self) -> Option<&'b Node<'a, V, T>>
pub fn first_node<'b>(&self) -> Option<&'b Node<'a, V, T>>
Returns a reference to the first node of the collection.
sourcepub fn last_node<'b>(&self) -> Option<&'b Node<'a, V, T>>
pub fn last_node<'b>(&self) -> Option<&'b Node<'a, V, T>>
Returns a reference to the last node of the collection.
sourcepub fn get_node<'b>(&self, at: usize) -> Option<&'b Node<'a, V, T>>
pub fn get_node<'b>(&self, at: usize) -> Option<&'b Node<'a, V, T>>
Returns a reference to the at
-th node of the collection.
sourcepub fn push_get_ref<'b>(&self, value: T) -> &'b Node<'a, V, T>
pub fn push_get_ref<'b>(&self, value: T) -> &'b Node<'a, V, T>
Pushes the value
to the vector and returns a reference to the created node.
§Example
The following code block demonstrates the push-front operation of a singly linked list. The code is branched depending on whether or not there already exists a front; i.e., the list is not empty. In either case,
- the new value is pushed to the self referential collection;
- and a reference to the new list node containing this value is received right after by the
push_get_ref
method; - this reference is then used to establish singly linked list relations.
pub fn push_front(&mut self, value: T) {
self.col
.move_mutate(value, |x, value| match x.ends().front() {
Some(prior_front) => {
let new_front = x.push_get_ref(value);
new_front.set_next(&x, prior_front);
x.set_ends(new_front);
}
None => {
let node = x.push_get_ref(value);
x.set_ends(node);
}
});
}
sourcepub fn set_ends_refs(&self, ends: V::Ends)
pub fn set_ends_refs(&self, ends: V::Ends)
Sets the ends of the self referential collection to the given ends
.
Ends represent special references of the self referential structure.
It can be nothing; i.e., NodeRefNone
; however, they are common in such structures.
For instance,
- ends of a singly linked list is the front of the list which can be represented as a
NodeRefSingle
reference; - ends of a doubly linked list contains two references, front and back of the list which can be represented by a
NodeRefsArray<2, _, _>
; - ends of a tree is the root which can again be represented as a
NodeRefSingle
reference.
Ends of a SelfRefCol
is generic over NodeRefs
trait which can be decided on the structure’s requirement.
sourcepub fn set_ends<Ends: Into<V::Ends>>(&self, ends: Ends)
pub fn set_ends<Ends: Into<V::Ends>>(&self, ends: Ends)
Sets the ends of the self referential collection to the given ends
.
Ends represent special references of the self referential structure.
It can be nothing; i.e., NodeRefNone
; however, they are common in such structures.
For instance,
- ends of a singly linked list is the front of the list which can be represented as a
NodeRefSingle
reference; - ends of a doubly linked list contains two references, front and back of the list which can be represented by a
NodeRefsArray<2, _, _>
; - ends of a tree is the root which can again be represented as a
NodeRefSingle
reference.
Ends of a SelfRefCol
is generic over NodeRefs
trait which can be decided on the structure’s requirement.
Methods from Deref<Target = SelfRefCol<'a, V, T, P>>§
sourcepub fn node_utilization(&self) -> f32
pub fn node_utilization(&self) -> f32
Returns the node utilization as a fraction of active nodes to the used nodes:
- 1.0 when there is no closed node;
- 0.0 when all used memory is used by closed nodes.
sourcepub fn ends(&self) -> &V::Ends
pub fn ends(&self) -> &V::Ends
Returns a reference to the ends of the self referential collection.
Ends represent special references of the self referential structure.
It can be nothing; i.e., NodeRefNone
; however, they are common in such structures.
For instance,
- ends of a singly linked list is the front of the list which can be represented as a
NodeRefSingle
reference; - ends of a doubly linked list contains two references, front and back of the list which can be represented by a
NodeRefsArray<2, _, _>
; - ends of a tree is the root which can again be represented as a
NodeRefSingle
reference.
Ends of a SelfRefCol
is generic over NodeRefs
trait which can be decided on the structure’s requirement.