xref: /xnu-11417.140.69/libkern/libkern/c++/OSCollectionIterator.h (revision 43a90889846e00bfb5cf1d255cdc0a701a1e05a4)
1 /*
2  * Copyright (c) 2019 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 /* IOCollectionIterator.h created by gvdl on Fri 1998-10-30 */
29 
30 #ifndef _OS_OSCOLLECTIONITERATOR_H
31 #define _OS_OSCOLLECTIONITERATOR_H
32 
33 #include <libkern/c++/OSIterator.h>
34 #include <libkern/c++/OSCollection.h>
35 #include <libkern/c++/OSPtr.h>
36 
37 class OSCollectionIterator;
38 
39 typedef OSCollectionIterator* OSCollectionIteratorPtr;
40 
41 #if XNU_KERNEL_PRIVATE
42 
43 __enum_closed_decl(OSCollectionIteratorStorageType, uint8_t, {
44 	OSCollectionIteratorStorageUnallocated = 0,
45 	OSCollectionIteratorStorageInvalid = 1,
46 	OSCollectionIteratorStorageInline = 2,
47 	OSCollectionIteratorStoragePointer = 3, /* two bits set, matches top bits of kernel pointer */
48 });
49 
50 #endif /* XNU_KERNEL_PRIVATE */
51 
52 /*!
53  * @header
54  *
55  * @abstract
56  * This header declares the OSCollectionIterator collection class.
57  */
58 
59 
60 /*!
61  * @class OSCollectionIterator
62  *
63  * @discussion
64  * OSCollectionIterator defines a consistent mechanism to iterate
65  * through the objects of an OSCollection.
66  * It expands on the basic interface of
67  * @link //apple_ref/cpp/class/OSIterator OSIterator@/link
68  * to allow association of an iterator with a specific collection.
69  *
70  * To use an OSCollectionIterator, you create it with the collection
71  * to be iterated, then call
72  * @link //apple_ref/cpp/class/OSIterator OSIterator@/link
73  * as long as it returns an object:
74  *
75  * @textblock
76  * <pre>
77  *     OSPtr <OSCollectionIterator> iterator =
78  *         OSCollectionIterator::withCollection(myCollection);
79  *     OSObject * object;
80  *     while (object = iterator->getNextObject()) {
81  *         // do something with object
82  *     }
83  *     // optional
84  *     if (!iterator->isValid()) {
85  *         // report that collection changed during iteration
86  *     }
87  *     iterator = nullptr;
88  * </pre>
89  * @/textblock
90  *
91  * Note that when iterating associative collections,
92  * the objects returned by <code>getNextObject</code> are keys;
93  * if you want to work with the associated values,
94  * simply look them up in the collection with the keys.
95  *
96  * <b>Use Restrictions</b>
97  *
98  * With very few exceptions in the I/O Kit, all Libkern-based C++
99  * classes, functions, and macros are <b>unsafe</b>
100  * to use in a primary interrupt context.
101  * Consult the I/O Kit documentation related to primary interrupts
102  * for more information.
103  *
104  * OSCollectionIterator provides no concurrency protection.
105  */
106 class OSCollectionIterator : public OSIterator
107 {
108 	OSDeclareDefaultStructors(OSCollectionIterator);
109 
110 protected:
111 // xx-review: Do we want to document these?
112 	OSPtr<const OSCollection> collection;
113 #if __LP64__ && XNU_KERNEL_PRIVATE
114 	union {
115 		struct {
116 			uint8_t inlineStorage[4];
117 			uint8_t __padding[4];
118 		};
119 		void * collIterator;
120 	};
121 #else
122 	void * collIterator;
123 #endif /* __LP64__ && XNU_KERNEL_PRIVATE */
124 	unsigned int         initialUpdateStamp;
125 	bool                 valid;
126 
127 #if XNU_KERNEL_PRIVATE
128 private:
129 	/*
130 	 * Returns true if this object is an instance of a OSCollectionIterator subclass
131 	 */
132 	bool   isSubclassed();
133 
134 	/*
135 	 * Initialize iterator storage.
136 	 *
137 	 * If storage is already initialized, return false. Otherwise, return true.
138 	 */
139 	bool   initializeIteratorStorage();
140 
141 	/*
142 	 * Get the iterator storage. If storage is not initialized, this returns NULL.
143 	 */
144 	void * getIteratorStorage();
145 
146 	/*
147 	 * Free iterator storage. If storage is not initialized, this has no effect.
148 	 */
149 	void   freeIteratorStorage();
150 
151 	/*
152 	 * Determine if storage is unallocated, allocated, or inline.
153 	 */
154 	OSCollectionIteratorStorageType getStorageType();
155 
156 	/*
157 	 * Set the storage type. The expectation is that this is called AFTER the conditions
158 	 * for the storage type have been set. For example, collIterator must be set to a valid
159 	 * pointer before calling setStorageType(OSCollectionIteratorStoragePointer)
160 	 */
161 	void setStorageType(OSCollectionIteratorStorageType storageType);
162 #endif
163 
164 public:
165 /*!
166  * @function withCollection
167  *
168  * @abstract
169  * Creates and initializes an OSCollectionIterator
170  * for the provided collection object.
171  *
172  * @param inColl  The OSCollection-derived collection object to be iteratated.
173  *
174  * @result
175  * A new instance of OSCollectionIterator, or <code>NULL</code> on failure.
176  */
177 	static OSPtr<OSCollectionIterator> withCollection(const OSCollection * inColl);
178 
179 
180 /*!
181  * @function initWithCollection
182  *
183  * @abstract
184  * Initializes an OSCollectionIterator
185  * for the provided collection object.
186  *
187  * @param inColl  The OSCollection-derived collection object to be iteratated.
188  * @result
189  * <code>true</code> if the initialization was successful,
190  * or <code>false</code> on failure.
191  *
192  * @discussion
193  * Not for general use. Use the static instance creation method
194  * <code>@link withCollection withCollection@/link</code> instead.
195  */
196 	virtual bool initWithCollection(const OSCollection * inColl);
197 
198 
199 /*!
200  * @function free
201  *
202  * @abstract
203  * Releases or deallocates any resources used
204  * by the OSCollectionIterator object.
205  *
206  * @discussion
207  * This function should not be called directly;
208  * use
209  * <code>@link
210  * //apple_ref/cpp/instm/OSObject/release/virtualvoid/()
211  * release@/link</code>
212  * instead.
213  */
214 	virtual void free() APPLE_KEXT_OVERRIDE;
215 
216 
217 /*!
218  * @function reset
219  *
220  * @abstract
221  * Resets the iterator to the beginning of the collection,
222  * as if it had just been created.
223  */
224 	virtual void reset() APPLE_KEXT_OVERRIDE;
225 
226 
227 /*!
228  * @function isValid
229  *
230  * @abstract
231  * Checks that the collection hasn't been modified during iteration.
232  *
233  * @return
234  * <code>true</code> if the iterator is valid for continued use,
235  * <code>false</code> otherwise
236  * (typically because the iteration context has been modified).
237  */
238 	virtual bool isValid() APPLE_KEXT_OVERRIDE;
239 
240 
241 /*!
242  * @function getNextObject
243  *
244  * @abstract
245  * Advances to and returns the next object in the iteration.
246  *
247  * @return
248  * The next object in the iteration context,
249  * <code>NULL</code> if there is no next object
250  * or if the iterator is no longer valid.
251  *
252  * @discussion
253  * This function first calls
254  * <code>@link //apple_ref/cpp/instm/OSCollectionIterator/isValid/virtualbool/()
255  * isValid@/link</code>
256  * and returns <code>NULL</code> if that function
257  * returns <code>false</code>.
258  *
259  * Subclasses must implement this pure virtual function
260  * to check for validity with
261  * <code>@link
262  * //apple_ref/cpp/instm/OSCollectionIterator/isValid/virtualbool/()
263  * isValid@/link</code>,
264  * and then to advance the iteration context to the next object (if any)
265  * and return that next object, or <code>NULL</code> if there is none.
266  */
267 	virtual OSObject * getNextObject() APPLE_KEXT_OVERRIDE;
268 };
269 
270 #endif /* !_OS_OSCOLLECTIONITERATOR_H */
271