@@ -10,6 +10,21 @@ namespace morphio {
1010
1111class CollectionImpl ;
1212
13+ template <class M >
14+ class LoadUnordered ;
15+
16+ /* *
17+ * Enable if `T` is a immutable morphology.
18+ */
19+ template <class T , class U = void >
20+ struct enable_if_immutable : public std ::enable_if<std::is_same<T, Morphology>::value, U> {};
21+
22+ /* *
23+ * Enable if `T` is a mutable morphology.
24+ */
25+ template <class T , class U = void >
26+ struct enable_if_mutable : public std ::enable_if<std::is_same<T, mut::Morphology>::value, U> {};
27+
1328class Collection
1429{
1530 public:
@@ -34,15 +49,34 @@ class Collection
3449 * Load the morphology as an immutable morphology.
3550 */
3651 template <class M >
37- typename std::enable_if<std::is_same< M, Morphology>::value, M>::type load (
38- const std::string& morph_name, unsigned int options = NO_MODIFIER) const ;
52+ typename enable_if_mutable< M, M>::type load (const std::string& morph_name,
53+ unsigned int options = NO_MODIFIER) const ;
3954
4055 /* *
4156 * Load the morphology as a mutable morphology.
4257 */
4358 template <class M >
44- typename std::enable_if<std::is_same<M, mut::Morphology>::value, M>::type load (
45- const std::string& morph_name, unsigned int options = NO_MODIFIER) const ;
59+ typename enable_if_immutable<M, M>::type load (const std::string& morph_name,
60+ unsigned int options = NO_MODIFIER) const ;
61+
62+ /* *
63+ * Returns an iterable of loop index, morphology pairs.
64+ *
65+ * See `LoadUnordered` for details.
66+ */
67+ template <class M >
68+ LoadUnordered<M> load_unordered (std::vector<std::string> morphology_names,
69+ unsigned int options = NO_MODIFIER) const ;
70+
71+ /* *
72+ * Returns the reordered loop indices.
73+ *
74+ * This is the suggested order in which one should load the morphologies to
75+ * minimize seeking within the file.
76+ *
77+ * Note: This API is 'experimental', meaning it might change in the future.
78+ */
79+ std::vector<size_t > argsort (const std::vector<std::string>& morphology_names) const ;
4680
4781 /* *
4882 * Close the collection.
@@ -61,10 +95,99 @@ class Collection
6195 std::shared_ptr<CollectionImpl> _collection;
6296};
6397
64- extern template mut::Morphology Collection::load<mut::Morphology>(const std::string& morph_name,
65- unsigned int options) const ;
98+ class LoadUnorderedImpl ;
99+
100+ /* *
101+ * An iterable of loop index and morphologies.
102+ *
103+ * When reading from containers, the order in which morphologies are read can
104+ * have a large impact on the overall time to load those morphologies.
105+ *
106+ * This iterator provides means of reordering loops to optimize the access
107+ * pattern. Loops such as the following
108+ *
109+ * for(size_t k = 0; k < morphology_names.size; ++k) {
110+ * auto morph = collection.load<M>(morphology_names[k]);
111+ * f(k, morph);
112+ * }
113+ *
114+ * can be replaced with
115+ *
116+ * for(auto [k, morph] : collection.load_unordered<M>(morphology_names)) {
117+ * assert(collection.load<M>(morphology_names[k]) == morph);
118+ * f(k, morph);
119+ * }
120+ *
121+ * The order in which the morphologies are returned in unspecified, but the
122+ * loop index `k` can be used to retrieve the correct state corresponding to
123+ * iteration `k` of the original loop.
124+ *
125+ * Note, that it is safe for an `LoadUnordered` object to outlive its
126+ * `collection`. Internally a shallow copy of the original `collection` is
127+ * stored inside of and kept alive for the life time of the `LoadUnordered`
128+ * object.
129+ *
130+ * Note: This API is 'experimental', meaning it might change in the future.
131+ */
132+ template <class M >
133+ class LoadUnordered
134+ {
135+ protected:
136+ class Iterator
137+ {
138+ public:
139+ Iterator (std::shared_ptr<LoadUnorderedImpl> load_unordered_impl, size_t k);
140+
141+ template <class U = M>
142+ typename enable_if_immutable<U, std::pair<size_t , M>>::type operator *() const ;
143+
144+ template <class U = M>
145+ typename enable_if_mutable<U, std::pair<size_t , M>>::type operator *() const ;
146+
147+ Iterator& operator ++();
148+ Iterator operator ++(int );
149+
150+ bool operator ==(const Iterator& other) const ;
151+ bool operator !=(const Iterator& other) const ;
152+
153+ private:
154+ size_t _k;
155+ std::shared_ptr<LoadUnorderedImpl> _load_unordered_impl;
156+ };
157+
158+ public:
159+ LoadUnordered (std::shared_ptr<LoadUnorderedImpl> load_unordered_impl);
160+
161+ Iterator begin () const ;
162+ Iterator end () const ;
163+
164+ protected:
165+ std::shared_ptr<LoadUnorderedImpl> _load_unordered_impl;
166+ };
167+
168+ extern template class LoadUnordered <Morphology>;
169+ extern template class LoadUnordered <mut::Morphology>;
170+
171+ extern template class LoadUnordered <Morphology>::Iterator;
172+ extern template class LoadUnordered <mut::Morphology>::Iterator;
173+
174+ extern template typename enable_if_immutable<Morphology, std::pair<size_t , Morphology>>::type
175+ LoadUnordered<Morphology>::Iterator::operator *<Morphology>() const ;
176+
177+ extern template
178+ typename enable_if_mutable<mut::Morphology, std::pair<size_t , mut::Morphology>>::type
179+ LoadUnordered<mut::Morphology>::Iterator::operator *<mut::Morphology>() const ;
180+
181+ extern template typename enable_if_mutable<mut::Morphology, mut::Morphology>::type
182+ Collection::load<mut::Morphology>(const std::string& morph_name, unsigned int options) const ;
183+
184+ extern template typename enable_if_immutable<Morphology, Morphology>::type
185+ Collection::load<Morphology>(const std::string& morph_name, unsigned int options) const ;
186+
187+ extern template LoadUnordered<Morphology> Collection::load_unordered<Morphology>(
188+ std::vector<std::string> morphology_names, unsigned int options) const ;
66189
67- extern template Morphology Collection::load< Morphology>(const std::string& morph_name,
68- unsigned int options) const ;
190+ extern template LoadUnordered<mut:: Morphology> Collection::load_unordered<mut:: Morphology>(
191+ std::vector<std::string> morphology_names, unsigned int options) const ;
69192
70193} // namespace morphio
0 commit comments