[Gambas-devel] New(er) enumeration API

Tobias Boege tobias at ...692...
Mon Oct 8 16:32:13 CEST 2012


On Mon, 08 Oct 2012, Beno?t Minisini wrote:
> Le 03/10/2012 22:22, Tobias Boege a ?crit :
> > On Wed, 03 Oct 2012, Tobias Boege wrote:
> >> On Wed, 03 Oct 2012, Tobias Boege wrote:
> >>> On Wed, 03 Oct 2012, Beno?t Minisini wrote:
> >>>> Le 03/10/2012 20:56, Tobias Boege a ?crit :
> >>>>> On Wed, 03 Oct 2012, Tobias Boege wrote:
> >>>>>> Hi,
> >>>>>>
> >>>>>> today while debugging the new List code for gb.data I encountered problems
> >>>>>> with the new enumeration API. There are _few_ places to learn from (I took
> >>>>>> CResult.c) but apparently something doesn't quite work out with it:
> >>>>>>
> >>>>>> I want to run through all references I manage for a chunk in a List (a
> >>>>>> 'chunk' contains some Variants). These are the 'Current' pointer and all the
> >>>>>> enumerations currently active. The ultimate goal is to update members of
> >>>>>> these reference structures just because the elements they point to in the
> >>>>>> chunk changed their location. The convenience macro looks like this:
> >>>>>>
> >>>>>> #define for_all_persistent_vals(list, vp, es, ebuf)                     \
> >>>>>> 	for (ebuf = GB.BeginEnum(list), vp = &list->current, es = NULL;	\
> >>>>>> 	vp ? 1 : (GB.EndEnum(ebuf), 0);					\
> >>>>>> 		!GB.NextEnum() ? (es = (struct enum_state*) GB.GetEnum(),\
> >>>>>> 			vp = &es->next) : (vp = NULL))
> >>>>>>
> >>>>>> (admittely not a very appealing piece of code)
> >>>>>>
> >>>>>> where 'list' is the Gambas List object, 'vp' is a pointer to the structure
> >>>>>> I want to update, 'es' is my struct enum_state and 'ebuf' is whatever I get
> >>>>>> back from GB.BeginEnum() and have to pass to GB.EndEnum().
> >>>>>>
> >>>>>> The thing now is that, even if no enumeration runs in the Gambas code, I get
> >>>>>> some 'es' which contains information that could actually have been valid (in
> >>>>>> fact, it refers to the last enumerated object in the last enumeration).
> >>>>>> For some reason, the important part (the pointer to the chunk which sits at
> >>>>>> offset 0 from the 'es' pointer) is set to NULL and thus, my library
> >>>>>> segfaults on NULL pointer dereference.
> >>>>>>
> >>>>>
> >>>>> Actually, I set it myself to NULL which indicates the end of enumeration to
> >>>>> the List_next routine. But why does that 'es' appear again without being in
> >>>>> enumeration?
> >>>>>
> >>>>> I have a really bad feeling now since I only get the 'es' filled if I put in
> >>>>> some basically unrelated Gambas code before the List.Take() from which the
> >>>>> above problem originates...
> >>>>>
> >>>>> I just want to know: Is it possible under normal circumstances to get an old
> >>>>> non-running enumerator from that GB.*Enum() interface?
> >>>>>
> >>>>>> Benoit, can you please enlighten me if I am doing something wrong with these
> >>>>>> functions?
> >>>>>
> >>>>
> >>>> I can't know. See me the full code because you can't do what you want
> >>>> between GB.BeginEnum() ... GB.EndEnum() (i.e. you can't do something
> >>>> that may call another enumeration-related function).
> >>>>
> >>>> Moreover, I'm not sure that your spaghetti macro is right. Can you
> >>>> rewrite it as clear as possible (i.e. without using the ',' operator)?
> >
> > Arrg! And the loop body must be before that unrolled while-body, so that:
> >
> > ebuf = GB.BeginEnum(list);
> > vp   = &list->current; /* Begin with Current */
> > es   = NULL; /* Just signal that vp is not an enumerator */
> > while (vp) {
> > 	/* Here goes the loop body, modifying vp */
> >
> > 	/* Get all enumerators next */
> > 	if (!GB.NextEnum())
> > 		break; /* In the macro done via vp = NULL */
> > 	es = GB.GetEnum();
> > 	vp = &es->next;
> > }
> > GB.EndEnum(ebuf);
> >
> 
> Can you commit your code and give me a project example of the bug?
> 

I will commit (with a worked-around code) when it works so that I can kill
two birds with one stone then...





More information about the Devel mailing list