Question about window idle system event

BlitzMax Forums/BlitzMax Programming/Question about window idle system event

Takis76(Posted 2015) [#1]
Sometimes when I have loading screens , loading levels or load new game graphics , the game freezes and then a (Not Responding) message appears on the window title OR when you try to click on the application window or if the window lost ITS focus until the game loads.

Is it possible to catch the window idle system event and then windows will not believe the game is frozen during loading process?

Thank you :)


Brucey(Posted 2015) [#2]
You could try adding a 'Delay 1' to your long loops.


col(Posted 2015) [#3]
The reason this happens is that ( in the background ) the Windows OS sends a message to your app thread message pump to know if its still sending and receiving messages and it expects a reply. If after about 4 seconds there's no reply, caused by your app being in a long time consuming loop, then the OS considers that you app has hung/crashed. So 'all' you need to do is make sure that the thread that the message pump is on ( ie your main application thread ) is allowed to run freely at all times.

I know some folks are scared of multithreading but your case is a prime candidate for exactly that. Create a new thread to load your resources and signal the main thread when its done. There are plenty of different ways of doing that ranging from very very simple up to complete job queues with signalling etc.

An example of such a simple system is in this thread


Takis76(Posted 2015) [#4]
I didn't understand much. about threads
And I used Delay 1 between my loading screens or when I load data and the game still freezes. (It doesn't crash but it remains frozen for a while until the data load and then continues normally).


Henri(Posted 2015) [#5]
Hi,

if the file is big (or take more processing time) then using threads is probably the only solution. If your files are smaller you could try to call this function between operations:
Function UpdateWindow()
	Delay 1
	For Local i:Int = 0 To 9
		PollSystem()
	Next
EndFunction


-Henri


Takis76(Posted 2015) [#6]
Pollsystem() between loading my files doesn't hang the program and I don't see not responding in the window title anymore. Bu I would like to learn and understand how the threads are working too. :)


col(Posted 2015) [#7]
Trying to describe threading in laymans terms is very difficult without using the correct terminology.

But I'll try...
Your main program is running in what is called the main thread. Your main code ( main thread ) can create new threads. New threads can also create new threads. Each thread runs a section of code that you tell it via an initial function call:- Each thread is started with a function call and that function is running in the new thread including any other functions that it calls. All threads that you create run at the same time ( asynchronously ) with all other threads including your main thread. Each thread also has unrestricted access to your variables:- and that is where the fun begins :-)

To understand the 'why did my code just run ok but now it crashes and I've not changed a single thing' scenario that plagues everyone new to multi-threading then you NEED to have a basic understanding of how the cpu accesses variables and at the low level too.

When, in your code, you write something such as 'enemyX :+ 1' then the cpu needs to get the value stored for enemyX, modify its value by incrementing it and then save that value back to the address where enemyX is stored. You have 3 operations 'Read,Modify and Write'. Lets have an example of why this creates a problem...

Problems arise when one thread Reads the value, then it begins to modify it, then another thread reads the value, and also modifies it, the first thread write its value back, then the second thread write it value, BUT the value has only been incremented once even though 2 threads have incremented it.
Lets go through that again step by step.

the address of enemyX stores a value of 10.
Thread 1 reads the value stored at the address for enemyX ( 10 ) and stores it in one of its registers.
Thread 1 then modifies the register value so its now 11, but at the same time...
Thread 2 comes along and reads the value stored for enemyX ( 10 ) into one if its registers.
Thread 2 increments the register value to 11.
Thread 1 writes the value of 11 back to memory for enemyX ( 11 )
Thread 2 writes the value of 11 back to memory for enemyX ( 11 ).

This is a called a 'race condition' in the world of multi-threading. In your code you were expecting the value of enemyX to be incremented by 2 but instead its only been incremented by 1 !!, and that is pretty much THE whole issue of why multi-thread programming can be a nightmare, but don't let it scare you as 'all' you need is some way for the cpu to update the value of enemyX in one single command, and that's where the 'Atomic' functions come in. It means that one thread will complete its RMW (Read,Modify,Write) phases without another thread having access to that same memory address at the same time.

Atomic functions are guaranteed to be thread safe and they are used as a basis for all other thread synchronisation primitives, such as the 'Mutex', Semaphore' and 'Condition Variable'. You can create your own of these thread sync primitives but the ones the OS supply will be tried, tested and more efficient than what you'd come up with.

Anyway you can write a couple of thousand page book about multi-threading which would also include various techniques of how to avoid using Atomic functions altogether, but for us in BlitzMax land we only have Atomic functions, Mutex, Semaphore and Condition Variables to use for synchronisation and these are more than enough to start you off on your multi-threaded adventures :-)

EDITED:
As always an example is always best. The first code show a race condition in action. The second code shows a simple fix using an atomic operation.