ENIGMA Forums

Contributing to ENIGMA => Developing ENIGMA => Topic started by: Goombert on January 29, 2014, 08:13:54 PM

Title: Asynchronous Dialogs/Win32 Threads Implemented
Post by: Goombert on January 29, 2014, 08:13:54 PM
I have implemented the Win32 thread functions to allow threading of scripts, this completely does away with the need for Asynchronous events allowing users to properly use cross-platform threading.

This is the pull request I have made.
https://github.com/enigma-dev/enigma-dev/pull/634

Interim documentation is available on this page.
http://enigma-dev.org/docs/Wiki/Game_State_Functions

A basic example is the following.
1) Create a new script called "scr_asynch_message" and add the following code.
Code: (EDL) [Select]
show_message("Hello, world!");2) Create a new object and in the create event add the following code.
Code: (EDL) [Select]
script_thread(scr_asynch_message);3) In the draw event add the following code.
Code: (EDL) [Select]
draw_set_color(c_red);
repeat (50) {
        draw_circle(random(room_width), random(room_height), 5, false);
}
4) Create a new room and place a single instance of this object
5) Run the game
(http://i.imgur.com/EBMjqhl.png)
As you can see an asynchronous message dialog will appear while the game continues to randomly draw circles in the background.
Title: Re: Win32 Threads Implemented
Post by: DaSpirit on January 29, 2014, 08:46:22 PM
As awesome as this is, it's not very useful with ENIGMA itself not being thread safe.
Title: Re: Win32 Threads Implemented
Post by: Goombert on January 29, 2014, 08:49:45 PM
What do you mean ENIGMA's not thread-safe? It's at least thread-safe for basic functions for now, and asynchronous dialogs.
Title: Re: Win32 Threads Implemented
Post by: DaSpirit on January 29, 2014, 09:11:44 PM
I'm going to assume you don't know what "thread safe" means so I'm going to show you what it means.

Make a script that creates a few objects and run it in a few threads at the same time. Next, check the ids. You'll notice that they overlap. This is because threading is a race and sometimes, this happens (due to the way that you have to get a variable first and then increment it, so that if both get it at the same time, they're both change it to the same value). To make ENIGMA thread safe, every variable either has to be locked by a mutex or use the faster, but less safe atomic type. A mutex essentially locks a bus. To do this, you have to make every variable in ENIGMA use a mutex (or lock instances of classes as whole).
Title: Re: Win32 Threads Implemented
Post by: Goombert on January 29, 2014, 09:22:53 PM
You mean mutual exclusion, not important right now since its only used for asynchronous messages atm.
https://en.wikipedia.org/wiki/Mutual_exclusion

I was not aware of that though, so thanks for informing me. However I have to disagree because if somebody has that going on they clearly haven't written their threads correctly. This occured with me when making some plugin changes where the plugin plays red light green light when loading so that it can register the EGM format, start loading the plugin DLL in a thread, and at the same time return to the main LGM thread and start loading the project and then fire a reload performed which propagates back to the plugin when the driver is finished being initialized.

Take a look at the main entry point for the LGM plugin and you'll see.
https://github.com/enigma-dev/lgmplugin/blob/master/org/enigma/EnigmaRunner.java#L201
The fixes to my original version are thanks to TGMG.
Title: Re: Win32 Threads Implemented
Post by: DaSpirit on January 29, 2014, 09:37:25 PM
Quote
However I have to disagree because if somebody has that going on they clearly haven't written their threads correctly.
There is no way to add it correctly as of yet, though. We need mutexes and atomic types (which I don't know how we'd implement without templates in EDL).
Title: Re: Asynchronous Dialogs/Win32 Threads Implemented
Post by: Goombert on January 30, 2014, 05:32:24 AM
Not to sound like I am ignoring you we discussed this further on the IRC.

But I want to add to this post I also went ahead and added the asynchronous dialog functions to a new Asynchronous dialog extension. It works perfectly just like Studio and I ran plenty of tests on it. The reason for making it an extension is because of how retarded these functions are and that they rely on other extensions such as data structures as well as threading (though not an extension).

I have partially corrected their stupidity by making the async functions not just return a retarded id but they actually return the index of the thread. Then you can bypass the async dialog event all together and just call thread_get_return(id);

Interim documentation is available on the Wiki.
http://enigma-dev.org/docs/Wiki/Message_Box_Functions
Title: Re: Asynchronous Dialogs/Win32 Threads Implemented
Post by: TheExDeus on January 30, 2014, 08:03:30 AM
Quote
As awesome as this is, it's not very useful with ENIGMA itself not being thread safe.
It's just as useful as the GMThreads extension way back for GM. It was used (to great success) to do async loading. Right now every sprite_add, background_add etc. is blocking. What you can do is create a pretty animated loading screen and load them in a thread. You can even load them during gameplay. And there race conditions are hard to do, because you only use the _add functions in that thread. If you also keep tabs on what is loaded and what is not (global.spr_player = -1, then in a thread global.spr_player = spr_add(..)) then you are fine. I have done that before and didn't have any problems. This can also be done to speed up the loading, as you can load many resources in parallel.

And there are many other cases where with sane programming you can get away without using a mutex.

edit: And just for a record - what namespace the threads run in? Can you actually access instance local's and such? Or just globals like GMThreads?
edit2: And is it async to room_speed too? Like an infinite loop in the script will run it as fast as possible (like thousands of times a second and thus create a CPU spike)?
Title: Re: Asynchronous Dialogs/Win32 Threads Implemented
Post by: Goombert on January 30, 2014, 08:36:17 AM
Quote
This can also be done to speed up the loading, as you can load many resources in parallel.
I have been thinking about that this entire time. Though what got me started on it was video streaming for that new guy who posted yesterday.

Quote
edit: And just for a record - what namespace the threads run in? Can you actually access instance local's and such? Or just globals like GMThreads?
If you can access object locals from a script then yes obviously, but that could lead to the mutex issues DaSpirit and dazappa are complaining about.

Quote
And is it async to room_speed too? Like an infinite loop in the script will run it as fast as possible (like thousands of times a second and thus create a CPU spike)?
Hum, that's a good question, I think I want to say it goes to infinity because only the main thread does the framerate stuff. So nothing is blocking the execution. But there is always sleep()

Just set a global.framerate_rendered = true; everytime the draw event occurs, then check that in your thread.
Title: Re: Asynchronous Dialogs/Win32 Threads Implemented
Post by: Darkstar2 on January 30, 2014, 01:00:56 PM
Very interesting, so with this you can have a loading screen, background music playing and loading of resources in memory at the same time right ?
Title: Re: Asynchronous Dialogs/Win32 Threads Implemented
Post by: Goombert on January 30, 2014, 07:58:23 PM
Yeah that is pretty much what this is, the changes are already in the new Windows Portable ZIP.
http://enigma-dev.org/docs/Wiki/Install:Windows