Concerns on how ContextActionService calls it's callbacks

Hello, I am curious to why ContextActionService calls it’s callbacks in a seemingly wasteful manner:

print(coroutine.running())

game:GetService("ContextActionService"):BindAction("helo", function()
    print(coroutine.running())
end, false, Enum.KeyCode.F)

Using this psuedo script, the result in the output is:
ponder
This seems unorthodox, as if your callback does not ever yield (as shown in the sample code) wrapping a new coroutine each time is just more work for both the garbage collector and our CPU for having to switch between these tasks.

But what’s really weird, is that events actually solve this problem on their own, the callback is only coroutined on the initial connect; and then coroutined again if the callback yielded for any length of time, as shown in this psuedo code:

local randomTest = Instance.new("BindableEvent")
local calledCount = 0

randomTest.Event:Connect(function()
	calledCount += 1
	
	print("helo", coroutine.running())
	
	if calledCount == 5 then calledCount = 0 
		wait(3)
	end
end)

while true do 
	randomTest:Fire("dsahfhfsdhfdshfsdh")
	
	wait(2)
end

And then our output:
ponder

So what I’m asking is: Events have a built in solution to wasteful coroutining, but contextactionservice does not use this or anything similar? Is there a specific reason for it? Or is it unintended behavior

2 Likes

I don’t know honestly, for some reason :Connect() keeps the coroutines alive for a bit while other functions that is used for binding functions to events don’t.
This is pretty much like the :BindToRenderStep() one you talked about 2 weeks ago. Why it’s implemented that way? We don’t know since this is pretty much a black box situation where we don’t know how it work but it works properly either way so at the end you really don’t care about it that much and forget about it until some brings it up and repeat. We all just hope that their pipeline works efficiently.