ID:2024649
 
Applies to:Dream Daemon
Status: Open

Issue hasn't been assigned a status value.
To assist in garbage collection, add two variable type keywords:

/*
Volatile: This variable does not prevent the datum from being
garbage collected. When it is, the variable becomes null.
*/

var/volatile/datum/VD
/*
Depend: When the linked object is deleted,
depending on the variable type, something happens:
Proc var: The proc throws an error
Object var: The object is deleted
Global var: throws an error to world.Error()
*/

var/depend/datum/DD
/*
The two can mix; the datum can garbage collect and kill its parent
*/

var/volatile/depend/datum/VDD



This can simplify some logic and help address memory leaks.
Relatedly, it would be nice if we could specify that datums in a list do not leave a null list entry when they are deleted.

I won't go so far as to request that lists have types (eg datum-only list), but a list that can be guaranteed to have no nulls would be useful to prevent errors.
I don't understand how either of those is supposed to work. The volatile keyword sounds like it just means "Don't refcount this value", which isn't reasonable, and the depend keyword doesn't make a lot of sense either.

Vars don't really work this way. Reference counting is a completely separate thing from the vars that values are stored in.
In response to Lummox JR
Lummox JR wrote:
I don't understand how either of those is supposed to work. The volatile keyword sounds like it just means "Don't refcount this value", which isn't reasonable, and the depend keyword doesn't make a lot of sense either.

Vars don't really work this way. Reference counting is a completely separate thing from the vars that values are stored in.

I think he means like weak references on the object in a similar way to how C++ does it (std::weak_ptr at least stores a seperate reference count for weak pointers so that they read null whenever accessed when the shared_ptr count is 0). As for depend... I'm really not sure how that would work.
Weak references have been requested before; they're not really doable.
We have \ref for weak references if you're okay with a locate() call
I thought they might not be but it was worth asking.

I am not sure what you mean when you say they don't make sense. Is there something you need me to explain our are you using that to say it is infeasible?
In response to SuperSayu
SuperSayu wrote:
I am not sure what you mean when you say they don't make sense. Is there something you need me to explain our are you using that to say it is infeasible?

Both. I don't follow how either of those is supposed to work, but I think the reason I don't follow is probably because you're working from a concept of how vars and refs work that isn't correct.

For instance, when a soft var is assigned a new value, here's how it works:

1) The var set routine first checks the object to see if it's a built-in type, and if so then it checks the built-in vars.

2) Once the built-in vars have been checked, any soft vars are looked at. If there's already a soft var in use with that name, a pointer to its value is retrieved. If not, a new var slot is created. If there's no var definition matching this var name at all, it throws an error.

3) The pointer that was retrieved then is given to the assignment function, along with the new value. The old value is set aside temporarily. The new value has its refcount incremented, and then is placed in the pointer's memory. Then the old value has its refcount decremented.

The takeaway here is that the value assignment function doesn't care if the pointer it was given is supposed to go with a var of a certain type, or what flags that var slot might hold; the pointer's only job is to hold a value.

What's more, if any advanced checking were to be put into place for var writes, processing would become slower. Even a simple if() check that ends up getting skipped costs processor cycles, which means all var writes would suffer. The amount of degradation would be subtle, but considering one of my long-term goals is to eke out all the performance I can, it's a step backward.
I guess I forgot about, I guess you call them soft vars, using the :operator and vars[]. Given that context it is difficult to create volatile object variables that remain volatile when accessed implicitly.

Given what you said (and understanding I may not understand you correctly) it feels like you could have a separate list of volatile variables attached to an object which are assigned to differently (a different assignment function is called, or different assignment code is generated when the assignment statement is compiled). When searching for the correct soft variable you would check this table separately from the other soft variables and the assignment would proceed differently as regarding refcounting. If you check volatiles after other soft variables, this should only add execution overhead when a volatile is being used.

When you are not using : and are explicitly referencing a variable known to be volatile obviously you can select the correct assignment code at compile time, I assume that's not what you're confused about. If on the other hand refcounting itself does not work the way I assume, or accurate refcounts are needed e.g. for accurate del() reference nulling, then it may all be impractical.

Regarding depend variables, the principle is solid: whenever an object is deleted, it checks to see if there are any depend-references on it, and if so, those are deleted. There is already a similar hunt-and-kill algorithm to remove references to deleted objects; I am ignorant of how it works and admit that, but it seems like a list (global or per object) of parent objects would not be difficult, although it might be more expensive than you want in terms of execution time.

Obviously part of this would mean saving pointers to execution contexts and I have no idea how feasible that is, especially since those may appear and disappear in milliseconds. The idea of having them attached to functions is that you can guarantee that a function will exit out with an error instead of proceeding with a null value that needs to be checked every, for example, loop iteration.
In response to SuperSayu
SuperSayu wrote:
Given what you said (and understanding I may not understand you correctly) it feels like you could have a separate list of volatile variables attached to an object which are assigned to differently (a different assignment function is called, or different assignment code is generated when the assignment statement is compiled). When searching for the correct soft variable you would check this table separately from the other soft variables and the assignment would proceed differently as regarding refcounting. If you check volatiles after other soft variables, this should only add execution overhead when a volatile is being used.

Nope. Let's say the var definition routine comes back with a flag that says it's a weak reference. (I'm not calling such a thing "volatile", because the term has a meaning that has nothing to do with weak references.) To do anything with that flag, an if() statement has to be checked. So there's your performance hit right there.

Regarding depend variables, the principle is solid: whenever an object is deleted, it checks to see if there are any depend-references on it, and if so, those are deleted. There is already a similar hunt-and-kill algorithm to remove references to deleted objects; I am ignorant of how it works and admit that, but it seems like a list (global or per object) of parent objects would not be difficult, although it might be more expensive than you want in terms of execution time.

References do not carry with them any kind of list of where they came from. They are strictly handled by counting. When vars have to be searched to null out a reference, the garbage collector has to go through them one by one, the hard way, until it finds the last one.

Implementing a list of where references came from would be a huge performance and memory hit, to say nothing of the massive overhaul to the innards of the server.
In response to Lummox JR
Lummox JR wrote:
Nope. Let's say the var definition routine comes back with a flag that says it's a weak reference. (I'm not calling such a thing "volatile", because the term has a meaning that has nothing to do with weak references.) To do anything with that flag, an if() statement has to be checked. So there's your performance hit right there.

It all comes down to the particulars of how you do it; it could have been organized in a way that code already naturally branches depending on the var type, or it could simply return a pointer and then you have to go out of your way to check flags. It's fine if it doesn't work, but it was worth asking.

References do not carry with them any kind of list of where they came from. They are strictly handled by counting. When vars have to be searched to null out a reference, the garbage collector has to go through them one by one, the hard way, until it finds the last one.

Implementing a list of where references came from would be a huge performance and memory hit, to say nothing of the massive overhaul to the innards of the server.

Fortunately most variables would not need this, but it runs into the same problem with weak vars, I guess.

I imagine if you had getters and setters on an object, internally, you could alter the rules on an object-by-object basis more easily, it sounds like you are trying to use exactly the same variable setter code for every variable irrespective of context, which sounds problematic to me in general. That said I understand not wanting to dig in and toy with large mind-bending systems as well.

Again whether or not it was feasible all comes down to how it is wired internally, it was worth asking.