1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
use crate::;
/// Unsynchronized access to records in a collection.
///
/// The trait provides *unsynchronized* access to *records*, defined by the
/// associated [`Record`](Self::Record) type, that are indexed by the `Index` parameter.
/// This trait gives data structures a means to give users
/// unfettered access to its records, without exposing internal implementation details
/// to the user. In turn, it is the responsibility of the user to maintain the invariants
/// of Rust's memory safety model.
///
/// An access object for a data structure is usually a lightweight wrapper around one
/// or more pointers, plus necessary metadata.
///
/// In order to use higher-level functionality in `paradis`,
/// implementors should try to implement [`BoundedParAccess`] too, whenever possible.
///
/// # Safety
///
/// A user must ensure that a record — accessed by the same index — is only accessed once,
/// at any given time. It may be helpful to imagine that [`Record`](Self::Record) is
/// a mutable reference, `&mut T`, and so it is undefined behavior to obtain two mutable
/// references to the same object. In other words, once a specific [`Record`](Self::Record)
/// is accessed, it can not be accessed through this access object again until the previous
/// instance is dropped.
///
/// An implementor must ensure that, for as long as any access object exists, the size of the
/// data structure remains unchanged, and that the same index always refers to the same "slot"
/// in the data structure.
///
/// # Notes on design
///
/// In an early iteration of `paradis`, [`Record`](Self::Record) was not required to implement
/// `Send`. The idea was that you should be able to use the abstraction also in single-threaded
/// scenarios, possibly with types that are not `Send`. However, since we want `ParAccess` to
/// be `Send` and `Sync`, this could lead to unsoundness because moving an access object
/// into a thread would allow us to create, say, a single-threaded iterator to records in
/// that thread, even though those records were not constrained to be `Send`.
/// To eliminate problems like these, we therefore require that [`Record`](Self::Record)
/// implements `Send`.
pub unsafe
/// Unsynchronized access to a bounded collection.
///
/// This trait allows a data structure that is structurally similar to a multidimensional array
/// to describe its bounds, which enables use of the data structure with higher-level functionality
/// in `paradis`.
///
/// # Safety
///
/// The bounds reported *must* be correct, in the sense that any index contained in the bounds
/// may be used to access a valid record.
pub unsafe
/// A type that can be converted into a parallel access object.
/// An unsynchronized access to an array-like structure, indexed by `usize`.
///
/// # Safety
///
/// The length of the collection must be reported correctly.
pub unsafe