Just never use await. I wish it wasn't even in the language.

  • xyz replied to this.

    Just to give you a better answer, await breaks the normal flow of code. People think it's like a timer or pause, which it can be, but it's asynchronous and if you are not well versed in asynchronous and parallel programming most likely it's gonna crash your app.

    cybereality I wish it wasn't even in the language.

    I'd keep it... but with "here be dragons" stickers slapped all over it 🙂

    I generally don't like things that break the flow of code. I consider await on the same level as GOTO. I would much rather use signals and event driven programming, which can achieve the same goal.

    A mutex doesn't break the flow. It just stops execution, which is probably what people think await is.

    • xyz replied to this.

      cybereality It does stop the execution, but only in the current frame when used in _process(). People who are new to game programming typically don't understand how the main loop works and that the _process() is called perpetually as a part of it. So if you stop the execution in this frame, the new "instance" of the same code will start running immediately in the next frame. The execution eventually needs to return to each of accumulated stopped processes, retrieving the local objects state from before who knows how many seconds. This is quite hard to "visualize" for anyone who hasn't had some previous experience with concurrent code.

      await is quite nice to have for generator coroutines. You can just run an infinite loop and spit out the output from time to time. I wouldn't like a powerful language feature gone just because newcomers tend to misuse it.

      I guess so. I mean, await is useful for networking code in particular. But for single player I haven't needed it yet.

      • xyz replied to this.

        cybereality Coroutines are very useful in realtime apps in general, games especially. For example for doing things like this:

        func fuse():
        	for i in range(10, 0, -1):
        		print(i)
        		await get_tree().create_timer(1).timeout
        	print("BOOM!")
        	
        func _ready():
        	fuse()

        Or streaming data elegantly:

        signal need_next_chunk
        
        func stream_content():
        	var i = 0
        	while true:
        		print("getting_chunk ", i)
        		await need_next_chunk
        		i += 1
        	
        func _ready():
        	stream_content()
        
        func _process(delta):
        	while chunks.size() < chunks_wanted:
        		emit_signal("need_next_chunk")

        I'm weird. I don't like while statements either.

        • xyz replied to this.

          cybereality I don't like them either but I think it's not possible to make an endless for loop in GDScript 😃

            xyz I think it's not possible to make an endless for loop in GDScript

            	var a: Array = [0]
            	for i in a:
            		a.append(0)
                            print_debug(a.size())
            		yield(get_tree(), "idle_frame")

            The yield is only there to slow down the looping so that the printing is visible and shows that the loop doesn't terminate. Technically, the loop would probably terminate eventually when the array index hits a limit or it runs out of RAM.