So, I guess I just don't get it. If you have a system where the enemies in your game are immutable, and everyone has a copy of this immutable structure, then you can be sure that something else isn't going to change the data underneath you. But you also have no way of knowing whether the immutable data you're looking at is stale or not. So you need to build some dispatcher in your system that is responsible for accepting actions like "move enemy 1 to x position 10", which then creates a mutated copy of the immutable original and notifies all the interested parties that the object has changed. And these interested parties need to be aware of the possibility that some other component is already in the processing of making a change, so that, for instance, the player does not try to interact with an enemy that has already been destroyed, or loot a chest that has just vanished, So now the components of your concurrent system have to be aware that the data they're looking at might be stale, and you need some kind of system for synchronization of changes so you can safely dispatch changes and interact with the rest of the engine with certainty. But you also now no longer know what other components may be interacting with the dispatcher and the synchronization system, so you're back to square one, where your interactions and architecture are influenced by components you're not aware of. All you've really done is reinvent the same problems at a higher level of abstraction. And that seems to be the case with so many attempts to build these message passing based systems. When you're dealing with components that are genuinely separate services with independent responsibilities, and which can fire-and-forget requests to each other, then it works. But the moment you have to have some degree of real cooperation. E.g. a player and an enemy have to know who shot first, or whether they're trying to move into the same game tile at the same moment, then you end up with nasty synchronization problems. And all the complicated message passing and immutability infrastructure really does is reimplement the mutable object infrastructure of the underlying language at a higher level of abstraction.
amtiskaw The world moves in steps. In each step, you recalculate the world and ship a new frame to the screen. All changes to the state are made through messages. When two players try to step in a single square, they both send a message to move, but since the messages are serialized, one of them will arrive earlier and the other will see the square already occupied.
I love hearing Evan talk about this stuff, it's such a nice paradigm
Are you using a compiler? It is dealing with the concurrency you don't know is there, and interleaving operations to fit the cpu.
Slides (or rather, prezi) are not available at the link which is a pity as they are hard to follow in the video
+Simon Hampton prezi.com/oi4ujfhlnn3r/accidentally-concurrent/
I sure wish the camera shot was tighter so we could see the screen.
+UK2AK The slides are here: prezi.com/oi4ujfhlnn3r/accidentally-concurrent/ We'll give your feedback to the camera crew for next year.
+Erlang Solutions Suggest they check mic input levels too.
+Erlang Solutions The year 2000 called. It wants its flash dependency back.
@@someman7 The year 2019 called, Prezi doesn't depend on Flash anymore 🎉
So, I guess I just don't get it. If you have a system where the enemies in your game are immutable, and everyone has a copy of this immutable structure, then you can be sure that something else isn't going to change the data underneath you. But you also have no way of knowing whether the immutable data you're looking at is stale or not. So you need to build some dispatcher in your system that is responsible for accepting actions like "move enemy 1 to x position 10", which then creates a mutated copy of the immutable original and notifies all the interested parties that the object has changed. And these interested parties need to be aware of the possibility that some other component is already in the processing of making a change, so that, for instance, the player does not try to interact with an enemy that has already been destroyed, or loot a chest that has just vanished,
So now the components of your concurrent system have to be aware that the data they're looking at might be stale, and you need some kind of system for synchronization of changes so you can safely dispatch changes and interact with the rest of the engine with certainty. But you also now no longer know what other components may be interacting with the dispatcher and the synchronization system, so you're back to square one, where your interactions and architecture are influenced by components you're not aware of. All you've really done is reinvent the same problems at a higher level of abstraction.
And that seems to be the case with so many attempts to build these message passing based systems. When you're dealing with components that are genuinely separate services with independent responsibilities, and which can fire-and-forget requests to each other, then it works. But the moment you have to have some degree of real cooperation. E.g. a player and an enemy have to know who shot first, or whether they're trying to move into the same game tile at the same moment, then you end up with nasty synchronization problems. And all the complicated message passing and immutability infrastructure really does is reimplement the mutable object infrastructure of the underlying language at a higher level of abstraction.
amtiskaw The world moves in steps. In each step, you recalculate the world and ship a new frame to the screen. All changes to the state are made through messages. When two players try to step in a single square, they both send a message to move, but since the messages are serialized, one of them will arrive earlier and the other will see the square already occupied.
@@zmotula "one of them will arrive earlier" was the problem that amtiskaw addressed.