Originally Posted By: Slin
our goals for Rayne, which do not include the world and domination!

Jesus, someone needs to re-read the mission statement...


Anyhow, let's cover spinlocks real quick. In Rayne they are implemented as an atomic flag that a thread compares and swap against a true value until it returns false. Here is pretty much the whole code:

Code:
void Lock()
{
	while(_flag.test_and_set(std::memory_order_acquire))
	{}
}



If you really want to put a computational complexity on it, then it's O(1) in the best case and O(∞) in the worst. To give you a better answer, as long as the lock can't be acquired, the thread will burn 100% of all CPU cycles that it gets.
They really are only good if held for a minimal time, ie for less CPU cycles than the OS needs to schedule your thread out of and back to an active CPU. If in doubt, don't use a spinlock.


So, about entity updates. They are done in parallel, though you can tell the engine that your entity depends on the state of others so that it won't update until after its dependencies have been updated (a bit like PROC_LATE and PROC_EARLY in gstudio, but with more flexibility). That alone will, of course, not stop the engine from moving two entities into each other at the same time, because putting your entities in a dependency chain would be, quite frankly, stupid (unless your goal is to mitigate all performance improvements).

However, collision is a bad example since you ideally want to use something like bullet for these kinds of things. Rayne doesn't keep sufficient data for fast collision detection, nor do we want it to. There is a c_trace() equivalent, but it's slow and requires parts of the scene to be locked and the entities within it to synchronize with each other. Bullet on the other hand stores collision hulls and scenes in an ideal format for collision detection, and it also provides you with a multithreaded and GPU collision solver, and Rayne picks a renderer that is compatible with OpenCL, so ideally you want to use that path.

Anyhow, fast moving objects are a problem one way or the other, like Nils said, physics engines try to mitigate these problems using CCD, but in reality you want to keep tabs on your objects velocity and avoid small objects. Simulating bullets is a bad idea one way or the other, and should probably be avoided.

But moving away from moving entities around (see what I did there?), exchanging state between two objects is generally speaking not a concern. Though, you do have to do manual locking in these cases, unless you told the engine about the relationship between the entities (which you should in case of long running dependencies). Obviously Rayne doesn't have the required knowledge about your games execution to do this automatically, so you'll have to help it out manually there.
Usually though these things are more hierarchical, AI for example: Your have entities that are part of a squad and a squad manager that keeps tabs on them while the general AI manager keeps tabs on the squads and player. These hierarchies can be expressed by parent/child relationships and if they are, the engine will take care of updating them in the right order (ie parents are updated before any of their childs are updated, so childs accessing their parents or a parent accessing their childs during their update is guaranteed to work).
If you need it more sophisticated, for example because you want a birds eye view of everything happening, well, in this case you can just plug into the engines event tap: We need to do that too after all, and so there are interfaces for this. For example, the trigger zones are implemented that way: Instead of polling every entity every frame, it just waits to be notified about entities updating themselves in its vicinity (where vicinity is defined by the acting scene manager)

Quote:
Or the parts of the article about ending up with floating point errors talking about this? Or you think having a lot of frames will compensate for that?

No, the floating point errors are something different entirely. If you detach your movement from the FPS by multiplying it with the delta time, but the delta itself varies (because the frame are varying in length), then you will end up accumulating floating point errors in a different way each time you run your application. A solution to this is a fixed time step, not more frames.

Last edited by JustSid; 11/20/13 13:12. Reason: Words!

Shitlord by trade and passion. Graphics programmer at Laminar Research.
I write blog posts at feresignum.com