Skip to content

Commit fb5f37f

Browse files
committed
fixup: improve generators header comment
1 parent 77ac9db commit fb5f37f

File tree

1 file changed

+87
-2
lines changed

1 file changed

+87
-2
lines changed

include/swift/Basic/Generators.h

Lines changed: 87 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212
//
13-
// This file defines a basic generator concept and some useful common
14-
// implementations of it.
13+
// This file defines a few types for defining types that follow this
14+
// simple generator concept:
1515
//
1616
// concept Generator {
1717
// // ...some number of accessors for the current value...
@@ -28,6 +28,25 @@
2828
// void finish();
2929
// };
3030
//
31+
// concept SimpleGenerator : Generator {
32+
// type reference;
33+
//
34+
// reference claimNext();
35+
// }
36+
//
37+
// Generators are useful when some structure needs to be traversed but
38+
// that traversal can't be done in a simple lexical loop. For example,
39+
// you can't do two traversals in parallel with a single loop unless you
40+
// break down all the details of the traversal. This is a minor problem
41+
// for simple traversals like walking a flat array, but it's a significant
42+
// problem when traversals get more complex, like when different components
43+
// of an array are grouped together according to some additional structure
44+
// (such as the abstraction pattern of a function's parameter list).
45+
// It's tempting to write those traversals as higher-order functions that
46+
// invoke a callback for each element, but this breaks down when parallel
47+
// traversal is required. Expressing the traversal as a generator
48+
// allows the traversal logic to to be reused without that limitation.
49+
//
3150
//===----------------------------------------------------------------------===//
3251

3352
#ifndef SWIFT_BASIC_GENERATORS_H
@@ -123,6 +142,72 @@ class ArrayRefGenerator {
123142
}
124143
};
125144

145+
/// An abstracting reference to an existing generator.
146+
///
147+
/// The implementation of this type holds the reference to the existing
148+
/// generator without allocating any additional storage; it is sufficient
149+
/// for the caller ensures that the object passed to the constructor
150+
/// stays valid. Values of this type can otherwise be safely copied
151+
/// around.
152+
template <class T>
153+
class SimpleGeneratorRef {
154+
public:
155+
using reference = T;
156+
157+
private:
158+
struct VTable {
159+
bool (*isFinished)(const void *impl);
160+
reference (*claimNext)(void *impl);
161+
void (*advance)(void *impl);
162+
void (*finish)(void *impl);
163+
};
164+
165+
template <class G> struct VTableImpl {
166+
static constexpr VTable vtable = {
167+
[](const void *p) { return static_cast<const G*>(p)->isFinished(); },
168+
[](void *p) -> reference { return static_cast<G*>(p)->claimNext(); },
169+
[](void *p) { static_cast<G*>(p)->advance(); },
170+
[](void *p) { static_cast<G*>(p)->finish(); },
171+
};
172+
};
173+
174+
const VTable *vtable;
175+
void *pointer;
176+
177+
public:
178+
constexpr SimpleGeneratorRef() : vtable(nullptr), pointer(nullptr) {}
179+
180+
template <class G>
181+
constexpr SimpleGeneratorRef(G &generator)
182+
: vtable(&VTableImpl<G>::vtable), pointer(&generator) {}
183+
184+
/// Test whether this generator ref was initialized with a
185+
/// valid reference to a generator.
186+
explicit operator bool() const {
187+
return pointer != nullptr;
188+
}
189+
190+
bool isFinished() const {
191+
assert(pointer);
192+
return vtable->isFinished(pointer);
193+
}
194+
195+
reference claimNext() {
196+
assert(pointer);
197+
return vtable->claimNext(pointer);
198+
}
199+
200+
void advance() {
201+
assert(pointer);
202+
vtable->advance(pointer);
203+
}
204+
205+
void finish() {
206+
assert(pointer);
207+
vtable->finish(pointer);
208+
}
209+
};
210+
126211
} // end namespace swift
127212

128213
#endif

0 commit comments

Comments
 (0)