Not really - it just gives the illusion of safety.
Firstly, there's a lock around all of the DBPro commands, meaning that there is only one running at a time, effectively using multiple threads to give you single-threading.
Secondly, take a look and think of all the points where the current thread can be pre-empted in the following very simple code, assuming the type of locking I believe is provided by PureGDK:
if object exist(Obj)
x = object position x(Obj) ` plus maybe some manipulation
y = object position y(Obj) ` plus maybe some manipulation
z = object position z(Obj) ` plus maybe some manipulation
` maybe some more manipulation of x/y/z here
position object Obj, x, y, z
endif
So each individual function/command is safe in the presence of threads. Now imagine another thread jumping in after this thread has tested the object exists, and then deleting it. Or another thread moving the object after this thread captures the x position but before it positions the object (providing inconsistent data).
The above exact situation isn't too likely (dealing with a single object in this way on multiple threads), but think about the situation where you are manipulating an object based on another objects position and dealing with them on separate threads.
Safe threading isn't just about making a single command safe in the presence of shared data, but is about making a whole user procedure safe in the presence of shared data.
You can only do that by passing the burden onto the programmer, making this the sort of thing that is needed:
if lock object exists(Obj) ` Now nothing else can access this object until it is unlocked
x = object position x(Obj) ` plus maybe some manipulation
y = object position y(Obj) ` plus maybe some manipulation
z = object position z(Obj) ` plus maybe some manipulation
` maybe some more manipulation of x/y/z here
position object Obj, x, y, z
unlock object Obj ` mustn't forget this otherwise it'll be locked forever
endif
Where LOCK OBJECT EXISTS returns false if the object exists, and returns true otherwise, and takes a blocking lock on the object, itself blocking if the object is already locked. The programmer then also needs to remember to unlock the object when done. ('exists' and 'lock' need to be combined into an atomic operation, as if they were separate, your code could check for existance, delete the object in another thread, then attempt to lock and object that no longer exists).
However the locking of the object would also need to lock out rendering too, and rendering itself would need to lock all objects, all cameras, all lights, all sound & music, all sprites, all images etc.
There are other issues too:
- recursive locking - allow it, or not?
- fine grained or high level locking - fine grained (eg per object) gives more control but gives the larger speed hit as you are doing more of it, high level locks out all objects.
- deadly embraces - how to deal with them? (for example, rendering starts by attempting to lock all objects and manages to lock up to 9, blocking on 10, but another thread has a lock on object 10 and attempts to lock object 9, blocking - now they are each waiting on the other to unlock).
All this complexity is probably the main reason why DBPro never went multi-threaded (and it also takes it out of the 'beginners' language camp), and why I keep saying that it's something that has to be designed in from day 1, not hacked in later. That's not to say that it's impossible, but I am saying that it's more complex and will take a lot more effort than people suppose, and that it hasn't yet been done properly and as fully as is needed.