From: Mike R. <mik...@gm...> - 2008-07-22 01:15:18
|
A possible alternative loop idiom is for (SIter* i = s_retain (s_iterable_get_iter (list)); !s_iter_is_end (i) || s_release (i); s_iter_advance (i)) { ... } Only after the last iteration, when s_iter_is_end() returns TRUE, would s_release() be called. Since the iterator will have a refcount of 1 before, it will be released to a refcount of 0, and freed. s_release() returns the pointer -- unless the object is freed, in which case it returns NULL. Therefore, the iterator would be freed and the OR expression would be false; the loop would be exited. Such an approach might be the "purist" approach. It still seems to me that taking the more pragmatic approach discussed earlier (automatically retaining and releasing), and recommending a sort of s_retain_forever() for the unusual cases, may ultimately be preferable. > Regarding the C89/C99 thing, I lost you a little bit. Will the new > code behave properly in both implementations? Sooc code itself does not assume that there exists something called "for" scope. All local variables are declared after an open brace and before any code that involves a function call. Therefore, the code should compile correctly on C89 compilers. However, gcc implements C99 correctly, and is the dominant choice on the target platforms (basically, Linux and OS X). Therefore, code that just uses Sooc may take advantage of the just-in-time declaration allowed by C99 (and C++, Java and other modern languages). In reality, most compilers in use today (gcc, MS cc) can probably be coaxed into accepting just-in-time declaration. Therefore, maybe even Sooc itself should use that convention. That's another subject, though. -Mike On Sun, Jul 20, 2008 at 4:53 PM, Daniel Reinish <sta...@gm...> wrote: > My initial impression was that the idea was a bit odd in that it > causes Iterators to behave differently from other standard sooc > objects. Upon further reflection, it may not be that different after > all. I forget exactly how garbage collection works internally, but > from the user's perspective, a non-retained object will disappear > "unpredictably." I use quotes since a little knowledge of the > systemcan give you an idea of whether you really need to retain > something. So, in this case, you can still retain an SIter if you > feel you need to; otherwise, it sticks around "at least" until the end > of the loop (in fact, that's exactly what it does). That seems fairly > intuitive: an SIter would be quite useless if it didn't last past the > first iteration, say. > > So, to me, it does feel natural. It definitely cleans up the code. > > > As for potential problems, I was unable to think of something other > than what you already described. So, let's see if I understand that > correctly. Suppose someone wants to use an SIter after the loop has > completed. Consequently, they make sure to retain it in the > declaration. The loop ends when s_iter_is_end() returns TRUE. > Internally, this causes s_release(), which cancels the internal > retain. The retain count is now 1. I don't know why they would do > this, but if the programmer continues to call s_iter_is_end(), they > could end up with I guess a segfault because eventually the object > will disappear. It's conceivable that this could occur because on the > surface, s_iter_is_end() appears to simply be an informational > accessor-like method rather than one that performs some sort of > complex task, like releasing the iterator. If one really needed to > use the iterator multiple times and repeatedly check whether it is at > the end, one would have to call s_retain() each time. > > I agree with you that generally speaking, an iterator is a one-use > object for dealing with one loop sequence. The question may be > whether there are any logical uses of iterators beyond the one-use > scenario. Also, even if there are not any logical uses, the fact > remains that one *can* use an iterator beyond the loop. Does the mere > fact that an iterator may persist beyond the loop (if properly > retained) mean this needs to be taken into account? I'm wondering if > this may indeed be so, simply because checking if the iterator has > reached its end doesn't seem at first like it should be a destructive > activity. So it seems like it's a question of accounting for > something somebody might actually want to do for some reason vs. > assuming that it will never happen. > > Two thoughts to add to the discussion: (1) Could this be solved > somehow using autorelease; and (2) would it be overkill to create a > special type of iterator (maybe SPersistentIter) for iterators that > don't want to die? > > > On Jul 18, 2008, at 7:53 PM, Mike Richman wrote: > >> In C++, for loops typically have the loop variable declared in the >> first part of the for(). For ordinary loops over integers and the >> like, this can be done in standard C as well -- that is, not C89, but >> in C99. However, until now, C99 could not simplify SIter loops; the >> SIter could be declared and retained inside the loop but there is no >> straightforward way of releasing it when the loop is over. >> >> For this reason, I am tentatively changing SIter retain/release >> policy. s_iterable_get_iter(), s_iterable_get_const_iter(), etc. will >> retain the new iterator before returning it. Then, when >> s_iter_is_end() or s_const_iter_is_end() is called and returns TRUE, >> it will release the iterator. A loop will go from this: >> >> >> SIter* i; >> for (i = s_retain (s_iterable_get_iter (some_list)); >> !s_iter_is_end (i); s_iter_advance (i)) { >> ... >> } >> s_release (i); >> >> >> to this: >> >> >> for (SIter* i = s_iterable_get_iter (some_list); >> !s_iter_is_end (i); s_iter_advance (i)) { >> ... >> } >> >> >> Even if C99 is not available (after all, Sooc tries to assume C89 with >> few extensions), the iterator need not be retained inside or released >> outside the loop. If you need the iterator to last, you can retain it >> and release it on your own terms. The only time this would be awkward >> is if the iterator needs to be used even after s_iter_is_end() has >> been called and has returned TRUE. However, in practice, this >> shouldn't be an issue -- that is, an iterator is normally a >> one-time-use device for iterating over a collection. >> >> What are some possible reasons why this may not be a good idea? Do >> you think it is a good idea? >> >> -Mike >> >> ------------------------------------------------------------------------- >> This SF.Net email is sponsored by the Moblin Your Move Developer's >> challenge >> Build the coolest Linux based applications with Moblin SDK & win >> great prizes >> Grand prize is a trip for two to an Open Source event anywhere in >> the world >> http://moblin-contest.org/redirect.php?banner_id=100&url=/ >> _______________________________________________ >> Sooc-devel mailing list >> Soo...@li... >> https://lists.sourceforge.net/lists/listinfo/sooc-devel > > > ------------------------------------------------------------------------- > This SF.Net email is sponsored by the Moblin Your Move Developer's challenge > Build the coolest Linux based applications with Moblin SDK & win great prizes > Grand prize is a trip for two to an Open Source event anywhere in the world > http://moblin-contest.org/redirect.php?banner_id=100&url=/ > _______________________________________________ > Sooc-devel mailing list > Soo...@li... > https://lists.sourceforge.net/lists/listinfo/sooc-devel > |