@@ -155,57 +155,75 @@ - (void)release;
155155
156156/* *
157157 * Empties objects from the autorelease pool, stating at the head of the list
158- * specified by pool and continuing until it reaches the stop point. If the stop point is NULL then
158+ * specified by pool and continuing until it reaches the stop point. If the stop
159+ * point is NULL then all pools are cleared.
159160 */
160- static void emptyPool (struct arc_tls *tls, void *stop )
161+ static void emptyPool (struct arc_tls *tls, void *stopAt )
161162{
163+ /* Clear all pools by default. */
162164 struct arc_autorelease_pool *stopPool = NULL ;
163- if (NULL != stop)
165+ void *oldPool;
166+
167+ /* Are we clearing up to a given object? */
168+ if (stopAt != NULL )
164169 {
165170 stopPool = tls->pool ;
166- while (1 )
171+
172+ /* Find pool in which object to stop at is located. */
173+ while (stopPool != NULL )
167174 {
168- // Invalid stop location
169- if (NULL == stopPool)
170- {
171- return ;
172- }
173- // NULL is the placeholder for the top-level pool
174- if (NULL == stop && stopPool->previous == NULL )
175- {
176- break ;
177- }
178- // Stop location was found in this pool
179- if ((stop >= stopPool->pool ) && (stop < &stopPool->pool [POOL_SIZE]))
175+ if (stopAt >= (void *)stopPool->pool &&
176+ stopAt < (void *)&stopPool->pool [POOL_SIZE])
180177 {
181178 break ;
182179 }
180+
183181 stopPool = stopPool->previous ;
184182 }
183+
184+ /* Invalid pointer, quit. */
185+ if (stopPool == NULL )
186+ {
187+ return ;
188+ }
185189 }
186- do {
190+
191+ do
192+ {
193+ /* Clear all pools up to the stop pool. */
187194 while (tls->pool != stopPool)
188195 {
189196 while (tls->pool ->insert > tls->pool ->pool )
190197 {
191- tls->pool ->insert --;
192- // This may autorelease some other objects, so we have to work in
193- // the case where the autorelease pool is extended during a -release.
198+ --tls->pool ->insert ;
194199 release (*tls->pool ->insert );
195200 }
196- void *old = tls->pool ;
201+
202+ oldPool = tls->pool ;
197203 tls->pool = tls->pool ->previous ;
198- free (old );
204+ free (oldPool );
199205 }
200- if ( NULL == tls-> pool ) break ;
201- while ((stop == NULL || (tls-> pool -> insert > stop)) &&
202- (tls->pool -> insert > tls-> pool -> pool ) )
206+
207+ /* If we cleared them all, quit. */
208+ if (tls->pool == NULL )
203209 {
204- tls->pool ->insert --;
210+ return ;
211+ }
212+
213+ /*
214+ * Release objects down to the stopping point. If a new pool is
215+ * pushed, never release below the pool's base.
216+ */
217+ while (tls->pool ->insert > (id *)stopAt &&
218+ tls->pool ->insert > tls->pool ->pool )
219+ {
220+ --tls->pool ->insert ;
205221 release (*tls->pool ->insert );
206222 }
223+
224+ /* Be sure that releasing objects did not push any new pools. */
207225 } while (tls->pool != stopPool);
208- // fprintf(stderr, "New insert: %p. Stop: %p\n", tls->pool->insert, stop);
226+ /* fprintf(stderr, "New insert: %p. Stop: %p\n", tls->pool->insert, stop); */
209227}
210228
211229#ifdef arc_tls_store
0 commit comments