From: Max Horn <max@...>
> > You can have a static usecode variable pointing to an object which
> > is cached out; the ID would then be invalidated, but the variable
> > would still refer to it.
> So how is this dealt with in a shared_ptr setup? In which form does the
> static usecode variable refer to the object? How does using a shared ptr
> solve the issue?
The shared_ptr/weak_ptr would detect that the object is gone and return an invalid (null) object pointer, and it would be guaranteed to do so; the case with the ID might not be as clean. Consider this: between two calls for a usecode function which uses a given static var, the referenced object might have been cached out and another one might have been cached in with the same ID. Now the usecode var refers to the wrong object. This is actually possible if the player avoids reloading for a long enough amount of time (even if he saves regularly) and walks around towns with large object counts, triggering multiple cache-outs and cache-ins; it would be *unlikely*, I admit.
The shared_ptr/weak_ptr would still not solve the issue of correctly saving the static var, except for the case when it has been invalidated.
> Can't we just solve this by using 32bit ids, which are not reused (well,
> only after a looong time) ? That way it's trivial to detect deletion of
> an object, too. Lookup gets a bit more expensive, because you can't use
> use the ID as an index anymore. However, if we keep the arrays in a
> sorted list, then binary search would still allow for quick lookup.
32-bit IDs would fit in the space currently laid aside for static usecode vars in "usecode.var". One thing I have thought about for this problem in the past was to break those 32-bits into an 8-bit index (to indicate whether it is an NPC, monster or other object). Then, have an 8-bit superchunk index and a 16-bit identifier into the superchunk (or the NPC's #). This could fail on extremelly 'busy' superchunks, though(such as in the middle or a large city). And it still doesn't work for cached-out objects.
> Personally, though I prefer the object ID approach a lot over using a
> shared_ptr / weak_ptr, for this particular task, at least. Using
> shared_ptr/weak_ptr objects correctly (avoiding things like circular
> references etc) can be quite a PITA.
That is true. But the usecode vars are actually a minor issue here (we have lived this long with them being invalidated on save/reload); the real problem is that currently, we are passing live pointers all around, storing them in several places and sometimes deleting them.
A practical example: in schedule.h, we have that Waiter_schedule keeps two Game_object lists: "prep_tables" and "eating_tables". When the avatar steps far enough away (Main_actor::step), it triggers a cache out (Main_actor::switched_chunks which leads to Game_window::emulate_cache which calls Deleted_objects::flush which deletes objects in the cached-out chunks), after which the objects in the lists may all be pointing to freed memory locations that get used by the schedule (for example, because the waiter NPC is still in a cached-in chunk and thus isn't dormant yet).
I'd rather deal with this problem first, then worry about the IDs (although solving both at the same time would be better).
Marzo Sette Torres Junior --+-- marzojr@...
marzojr@... ----+---- marzojr@...
"Mental slavery is mental death and every man who has
given up his intellectual freedom is the living
coffin of his dead soul."
-- Robert Green Ingersoll, "Individuality" (1873)