Are applied coroutines performed concurrently?


#1

Suppose a coroutine containing the following code is applied (%) to a list containing actors that seek items in the world. If they find one, they ‘pick it up’ by destroying it. Without knowledge of the underlying concurrency model (assuming one exists) I cannot knowingly prevent instances where one actor is mutating a list that another actor is currently operating on. You can probably see where I’m headed.

// Reached the item. 'Pick it up'
if pickup_items.find?[item = criteria]; !idx [
   !matched_item : pickup_items.pop_at(idx)
   matched_item.destroy_sk_actor
]

Is this code at risk for destroying an element in a list that another actor assumes still exists and therefore amounts to something like a segfault?

It is insufficient to check if matched_item is valid, because the idx that one actor thought corresponded to an item now points to a different item. Classic synchronization problem here.

But if each actor is acting in a linear, sequential manner, then I think I’m safe, because the list of pickup items will have updated by the time the next actor has a chance to respond.


#2

In :ue4:, :sk: runs everything in a single thread (all coroutines included), so there aren’t any synchronization issues here. The only issue you might have is one of your own design; grabbing things, trying to use them later but deleting them in-between.


#3

Hmm. Well, that is a plus on one hand.

I am curious, does SK play well with multi-threaded aspects of Unreal?


#4

:ue4: doesn’t have a multi-threaded game programming model, so :sk: plays as well as C++ and blueprints. You can get yourself into more trouble in C++ since you can spin up threads, but UObject manipulation is taboo unless you’re on the game thread, so you’d only be using threads for non-game oriented tasks.


#5

Hmm yea. I think we can deal with that.
But, our design is putting almost all the logic into the SK side except for when we have to ask UE4 a question…

Which brings up the next thought… since SK is single threaded, we can’t really offload our AI calcs to threads unless SK has some way to do that.


#6

SkookumScript is designed to manage tasks concurrently (several tasks effectively running at the same time though generally on a single thread/core/CPU) rather than in parallel (separate tasks running on several cores/CPUs literally at the same time).

Concurrency can still give a speed up over non-concurrent programming (such as re-entrant code such as Tick()) though caching and generally less infrastructure coding needing to describe tasks that occur over time. Being concurrent rather than parallel has many advantages with respect to necessary housekeeping code and not melting your brain. There is no need for mutexes, semaphores, thread context switches, worrying about race conditions, etc, etc.

The C++ engine may still do some work in a parallel fashion - such as graphics rendering and potentially audio - and then it will communicate on a single thread/CPU with SkookumScript to do the stage direction aspects.

It is theoretically possible for SkookumScript to have several independent environments that each process in true parallel, though this may be of limited utility - and more importantly the code and infrastructure has not been written for it. :madsci:


#7

Thanks. This information does require a change in (my) overall planning which was to use threading for background calcs in SK, but it is early enough that we have not invested in threading yet. I suppose the many benefits of not worrying about thread safety are alluring.
However, based on the posts here, it seems we can ask UE4 to perform some types of threading.
So, we might be able to improve performance and stay within those constraints. I have another Concurrency question… so will ask that in separate thread.