ID:1668131
 
Not a bug
BYOND Version:506
Operating System:Windows 7 Ultimate 64-bit
Web Browser:Chrome 36.0.1985.143
Applies to:DM Language
Status: Not a bug

This is not a bug. It may be an incorrect use of syntax or a limitation in the software. For further discussion on the matter, please consult the BYOND forums.
Descriptive Problem Summary: Since turfs are never truly deleted, only superseded by another turf with the same reference ID, infinite loops and other procs currently running on one turf instance will transfer to the newly created turf.

Code Snippet (if applicable) to Reproduce Problem:
turf
Click()
new/turf/testturf(src)

testturf
New()
RunLoop()

Click()
del src
proc
RunLoop()
set waitfor = 0
var/count = 0
while(1)
world << ++count
sleep(10)


Expected Results:

The infinite loop should suspend after the attached instance is removed.

Actual Results:

The infinite loop never suspends.

Workarounds:

None
Lummox JR resolved issue (Not a bug)
As you say, the turf is never truly deleted. (It is if the map dimensions are reduced, of course.) The performance hit to games to look for turf instances changing in these cases, to stop existing procs, would be bad, and there may well be many games that rely on the existing behavior.
So, basically, to put this in perspective, any loop involving turfs that spans over one frame is potentially unsafe, and that's intentional?
I think the issue boils down more to del(turf) not really being supported at the moment, due to the fact that turfs are literally references to their location on the map, which is immutable. That is a design by efficiency, but it probably could be improved since there is a lot of inconsistency in the way this is presented.
My real issue is that it's impossible to ensure that running functions tied to /turf will not quit execution when their instance is superseded by another.

That's a serious OO no-no when you look at it, and probably a consistent cause of CPU consumption on games designed by people who don't fully understand how BYOND works underneath by design.

When someone deletes an instance, they expect all proc calls to cease from that instance instantaneously. They don't expect potentially invalid nodes from another class's tree being shoehorned into the new instance and potentially making otherwise valid compiled code suddenly start spewing out runtime errors for invalid variable references.
For now, you could attach a helper object to the turf and delete that instead of the turf.

Like I said, the concept of turf creation/deletion is a bit ambiguous in DM just due to the way it is represented in the backend. New & del() shouldn't even really be options since they use hackery to work. But at least you can workaround it knowing this in advance.
Yeah, I've actually worked around it a fair bit already.

var
list/turf_instances = list()
list/free_turf_instances = list()
proc
reference_turf(turf/ref)
if(free_turf_instances.len)
ref.instance_id = free_turf_instances[1]
free_turf_instances.Cut(1,2)
turf_instances[ref.instance_id] = ref
else
ref.instance_id = turf_instances.len+1
turf_instances += ref

free_turf(turf/ref)
set waitfor = 0
var/refnum = ref.instance_id
turf_instances[refnum] = null
sleep(TICK_LAG)
free_turf_instances += refnum
turf
var
instance_id
New()
reference_turf(src)
Del()
free_turf(src)


I've essentually mimicked the way that object reference ids are assigned this way, and by checking whether the current turf's reference id equals the reference id assigned to that turf at the loop's start, I can manually eject out of loops.

It's a bit backward to have two reference id structures for all turfs in the game, but it shouldn't be that big of a memory hit. Just 5 bytes per turf.

Ultimately, the existing way turfs handle themselves is somewhat counter-intuitive moreso than problematic. I was only able to overcome this problem because my level of knowledge about how DM works internally is somewhere closer to you two's level of knowledge than it is your average DM programmer.
I understand what you mean about the expectation of the proc ending. On the one hand it's easy to say "Well, turfs don't ever really get deleted, so you just shouldn't expect that." But yeah, a lot of people don't quite.

The helper object approach is a good one, as IIRC the attached vars reset when a turf gets "remade". Though I don't know if that'll help users much who make the mistake of thinking they can just start something off in turf/New().
Maybe this sunday we'll see an article about this particular problem, and strategies for avoiding it. Just so we at least have some kind of community documentation on avoiding this problem.
Nah, you'll be too busy playing with the webclient. :)
In response to Lummox JR
Lummox JR wrote:
Nah, you'll be too busy playing with the webclient. :)

OUUUUWWWW OKK OKK!! :D