Yes, I had the problem of events being created as a result of another event's execution. What I did was, in the main loop, events are flagged for deletion rather than actually being removed. All incoming events are put into a temporary list. After the main processing loop, a second loop removes events to be deleted. Then the temporary list is tacked onto the main queue.
--Palrich. ----- Original Message ----- From: "Jeremy Hill" <[EMAIL PROTECTED]> To: <[email protected]> Sent: Tuesday, February 03, 2004 9:09 PM Subject: Linked lists--new elements introduced outside loop creates problems > Greetings, > > I have implemented a 'wait' mobprogram command that delays execution of a mob > program for a certain amount of time, much like the 'mpsleep' snippet that is > out there. I am doing this with the event system I have created for events > such > as these. (Pun intended) Here's what an event looks like. > struct event > { > struct event * next; > union > { > ... > struct prog_event_args prog; > /* etc.... */ > } event_args; > > sh_int delay; > char *comments; > void (*fire)(struct event *); > void (*destroy)(struct event *); > bool valid; > }; > > However, I'm coming across a small problem that I'm not sure how to resolve, > and > wondered if you might have an idea in how to straighten this out. > > An event is created with an XXX_event function; in this instance, in > program_flow: prog_event(ch, (void *)mob, MOB, prog, count+1, timer); > > ...and is placed into the 'events' list until it is ready to fire. It is > fired, > which is a function specific to the event's properties, and then it > self-destroys, another function. However, when I create a new event within > the > previous event's fire function, the linked list gets out of whack. I'll lay > out > some code that'll help explain my problem. > > Like mobile_update and the other update routines, events are updated as well: > void event_update(void) > { > EVENT *ev = NULL, *ev_next = NULL, *ev_last = NULL; > > for(ev = events; ev; ev = ev_next) > { > ev_next = ev->next; > > if(--ev->delay <= 0) //Expired, kill it > { > --> ev->fire(ev); <--- > > if(ev_last) //We're past the first element of the list. > ev_last->next = ev_next; > else //First element. > events = ev_next; > > --> ev->destroy(ev); <--- > } > else //Not ready yet; start from here. > ev_last = ev; > } > } > > Pretty straightforward stuff, the items between --> <-- are the focus. > Now, firing a program that is done waiting with ev->fire(ev) (function trimmed > for brevity): > > void fire_prog_event(EVENT * ev) > { > extern void program_flow( sh_int, char *, CHAR_DATA *, OBJ_DATA *, > ROOM_INDEX_DATA *, > CHAR_DATA *, const void *, const void *, int ); > > ... > if (ev->event_args.prog.mob && ev->event_args.prog.ch && > ev->event_args.prog.mob->in_room == > ev->event_args.prog.ch->in_room) > { > program_flow(ev->event_args.prog.prog_code->vnum, > ev->event_args.prog.prog_code->code, > ev->event_args.prog.mob, > NULL, > NULL, > ev->event_args.prog.ch, > NULL, NULL, ev->event_args.prog.line); > } > } > } > > So if the event's program is still valid--i.e. the mob and ch still exist and > are in the same room yet--then it'll continue execution with a call to > program_flow. This means if there is another wait in the mobprog code, this > call to program_flow will create a new event to wait again. As you can see, > this is all done inside the ev->fire(ev), meaning the linked list is now > different for the rest of the code in the event_update()'s for loop. > > What do you think? I'm thinking I may have to put firing events onto their own > linked list so as not to disrupt the list of the ones still hatching. > However, > is there a much more elegant solution? > > > > > -- > ROM mailing list > [email protected] > http://www.rom.org/cgi-bin/mailman/listinfo/rom

