Recent

Author Topic: Synchronize not working  (Read 20657 times)

GeneCode

  • New Member
  • *
  • Posts: 25
  • What is the cost of lies?
Re: Synchronize not working
« Reply #15 on: November 23, 2021, 06:50:45 am »
So I found out the cause of the problem. It was not related to Synchronize at all.
It has something to do with the child form that I created wrongly. (noobie mistake  :P)

Referring to the test project,

Form2 was autocreated at application run. And then I went and declared another instance of Form2 as "settings" and created another one
and show that one.

What i did to fix it was to remove the autocreate Form2 in Project1.lpr.

Code: Pascal  [Select][+][-]
  1.   RequireDerivedFormResource:=True;
  2.   Application.Initialize;
  3.   Application.CreateForm(TForm1, Form1);
  4.  // Application.CreateForm(TForm2, Form2);
  5.   Application.Run;


And then calling the Form2 directly when creating the form.

Code: Pascal  [Select][+][-]
  1.     Form2 := TForm2.Create(Form1);
  2.   Form2.Show;  

That's all. Anyway thank you to all of you that responded to my question. Very much appreciated.
Windows 10
Lazarus 1.8.4

SymbolicFrank

  • Hero Member
  • *****
  • Posts: 779
Re: Synchronize not working
« Reply #16 on: November 24, 2021, 03:19:18 pm »
Sleep(0) or Sleep(1) is often a better alternative of ProcessMessages.

Are you absolutely sure of that? Application.ProcessMessages specifically causes the message queue to be checked, while Sleep() simply withholds the CPU for some number of mSec.

MarkMLl

Sleep gives other threads / processes a chance to run. If you run the CPU at max, everything that is waiting for something else, freezes. The same if you use threads: they all need time to process incoming data and respond. And then you don't need ProcessMessages, it happens automatically. Even the messages inside your own collection of threads require the Windows Kernel and the resources they use to have the processing time to do so.

If you think you need Application.ProcessMessages, the chances are it occasionally freezes your application because it is waiting for something else. Sleep fixes that.

Thaddy

  • Hero Member
  • *****
  • Posts: 11085
Re: Synchronize not working
« Reply #17 on: November 24, 2021, 03:38:10 pm »
no. the only Sleep() that does that under windows is Sleep(0) which is documented as "Relinquish Process" or depending on version "relinquish timeslice"'. All other values may still be blocking. A common error and a source of many a fake news.  see msdn.
https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleep

Very carefully read the official documentation...

Any other value- in the context of synchronization - is usually programmer error.
« Last Edit: November 24, 2021, 04:01:58 pm by Thaddy »
The average programmer productivity is 4-5 hours per day. Peak performance 72 hours for short bursts. MTBF is 1 second or less.

SymbolicFrank

  • Hero Member
  • *****
  • Posts: 779
Re: Synchronize not working
« Reply #18 on: November 24, 2021, 06:07:11 pm »
no. the only Sleep() that does that under windows is Sleep(0) which is documented as "Relinquish Process" or depending on version "relinquish timeslice"'. All other values may still be blocking. A common error and a source of many a fake news.  see msdn.
https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleep

Very carefully read the official documentation...

Any other value- in the context of synchronization - is usually programmer error.

I did. (Well, not recently.) It says:

Quote from: Microsoft
This function causes a thread to relinquish the remainder of its time slice and become unrunnable for an interval based on the value of dwMilliseconds.

With a value of 0, it only gives up the remainder of its timeslice. With other values, it does that as well as waiting for the time to pass (and the next timer tick).

The idea is to have the OS manage the message passing, instead of trying to force that to happen yourself. Because you cannot force other processes to start processing their messages.

I use a small value, like 1, if I want to make sure the other processes get enough time to do their thing. In all other cases I use "WaitForObject" or something like a mutex.
« Last Edit: November 24, 2021, 06:10:25 pm by SymbolicFrank »

PascalDragon

  • Hero Member
  • *****
  • Posts: 3624
  • Compiler Developer
Re: Synchronize not working
« Reply #19 on: November 25, 2021, 09:27:32 pm »
The idea is to have the OS manage the message passing, instead of trying to force that to happen yourself. Because you cannot force other processes to start processing their messages.

I use a small value, like 1, if I want to make sure the other processes get enough time to do their thing. In all other cases I use "WaitForObject" or something like a mutex.

This does however not help if you want your own application to process its own messages while you're in the thread that is responsible for processing the messages. Then you can Sleep all you want, but nothing will happen then.

440bx

  • Hero Member
  • *****
  • Posts: 2618
Re: Synchronize not working
« Reply #20 on: November 26, 2021, 04:01:05 am »
MS has been saying that Sleep(0) causes a thread to relinquish the remainder of its time slice, probably for ever.  I've tested that on every version of Windows, probably since Win95 and, it does NOT.  That is simply and provably NOT true.  It didn't work that way even on NT4.

The easiest way to write a supposedly "well behaved" application is to put a call to Sleep(0) in a loop that breaks on some way in the future condition and watch one core go to 100% utilization _every_ time.  Sleep(0) is bad news (unless you want the program to consume an entire core, then it's made to order.)

@whoever wants to see what Sleep() really does:

Some time ago I posted a little test program that shows how Sleep() behaves (including source).  Anyone interested can find that test program (and a few others in the archive) at https://forum.lazarus.freepascal.org/index.php/topic,52973.msg391376.html#msg391376

Also, as @PascalDragon indicated, Sleep() is most definitely not a substitute for processing messages.  Sleep() tells the O/S not to schedule the thread for X amount of time, that's very different thing than what takes place when an application calls GetMessage.

One thing a programmer should keep in mind when reading documentation: documentation is the way it's supposed to work (IOW, what the programmer who wrote it dreamed) it isn't necessarily the way it _actually_ works.




« Last Edit: November 26, 2021, 04:03:09 am by 440bx »
FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

Mr.Madguy

  • Hero Member
  • *****
  • Posts: 748
Re: Synchronize not working
« Reply #21 on: November 26, 2021, 07:11:13 am »
One thing a programmer should keep in mind when reading documentation: documentation is the way it's supposed to work (IOW, what the programmer who wrote it dreamed) it isn't necessarily the way it _actually_ works.
Yeah, sometimes docs focus too much on unimportant details, while completely missing really important things. For example for me the biggest mystery - is IDXGIOutput.FindClosestMatchingMode behavior, that seems to be wrong due to wrong treatment of DXGI_MODE_SCALING. But it isn't explained anywhere.
29.12.2021 - migration to DynamicData 4.1 is completed - complete overhaul of data access driver.
My project still requires full Delphi 2009 support to be ported to Lazarus.
It's time to finally do it, because Delphi 2009 is 12 years old.

MarkMLl

  • Hero Member
  • *****
  • Posts: 3647
Re: Synchronize not working
« Reply #22 on: November 26, 2021, 09:33:33 am »
MS has been saying that Sleep(0) causes a thread to relinquish the remainder of its time slice, probably for ever.  I've tested that on every version of Windows, probably since Win95 and, it does NOT.  That is simply and provably NOT true.  It didn't work that way even on NT4.

Does it? The way I've always read the docs (and this applies to most multitasking OSes) is that it says that it re-runs the scheduling algorithm: it makes no statement as to which thread will be resumed which could very easily be the same one that called Sleep(0) if it's the best candidate.

Quote
Also, as @PascalDragon indicated, Sleep() is most definitely not a substitute for processing messages.  Sleep() tells the O/S not to schedule the thread for X amount of time, that's very different thing than what takes place when an application calls GetMessage.

Agreed, a point I tried to make earlier.

Code: Pascal  [Select][+][-]
  1.   PostMessage(...);
  2.   Sleep(0)
  3.  

and

Code: Pascal  [Select][+][-]
  1.   Synchronize(...)
  2.  

are not equivalent.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

440bx

  • Hero Member
  • *****
  • Posts: 2618
Re: Synchronize not working
« Reply #23 on: November 26, 2021, 11:43:25 am »
Does it? The way I've always read the docs (and this applies to most multitasking OSes) is that it says that it re-runs the scheduling algorithm: it makes no statement as to which thread will be resumed which could very easily be the same one that called Sleep(0) if it's the best candidate.
That is true but, it quickly becomes very suspicious when it is _always_ the thread that executed the Sleep(0) that gets immediately rescheduled. The results of testing Sleep(0)'s behavior indicate it _renews_ the time slice (the opposite of what the documentation states.)  If the thread was truly giving up the remainder of its time slice, it could not be using 100% of a core because there would be some portion of the time slice given up in each call.
FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

MarkMLl

  • Hero Member
  • *****
  • Posts: 3647
Re: Synchronize not working
« Reply #24 on: November 26, 2021, 11:55:53 am »
If the thread was truly giving up the remainder of its time slice, it could not be using 100% of a core because there would be some portion of the time slice given up in each call.

Unless there were nothing else scheduled ready to run, i.e. everything else on the system were waiting on a (kernel) timer or event.

In any event, Sleep()- with any parameter- is not equivalent to APM.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Warfley

  • Hero Member
  • *****
  • Posts: 654
Re: Synchronize not working
« Reply #25 on: November 26, 2021, 12:05:26 pm »
That is true but, it quickly becomes very suspicious when it is _always_ the thread that executed the Sleep(0) that gets immediately rescheduled. The results of testing Sleep(0)'s behavior indicate it _renews_ the time slice (the opposite of what the documentation states.)  If the thread was truly giving up the remainder of its time slice, it could not be using 100% of a core because there would be some portion of the time slice given up in each call.

Could it be that sleep, as an optimization, rather than always rescheduling, checks if there is a process in the queue for the current CPU and if so does reschedule and in all other cases just renews the time slice to not have to go through the scheduler?

It would be interesting to see how two processes on the same CPU (e.g. via CPU pinning in task manager) behave if one does the following:
Code: Pascal  [Select][+][-]
  1. While True do;
and the other one does:
Code: Pascal  [Select][+][-]
  1. While True do Sleep(0);
I would guess that the second one should get a much smaller slice of the CPU time. But sadly I don't have the ability to test it right now

MarkMLl

  • Hero Member
  • *****
  • Posts: 3647
Re: Synchronize not working
« Reply #26 on: November 26, 2021, 12:08:20 pm »
@Warfley: ISWYM, thread affinity in Linux terms.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

440bx

  • Hero Member
  • *****
  • Posts: 2618
Re: Synchronize not working
« Reply #27 on: November 26, 2021, 12:36:06 pm »
If the thread was truly giving up the remainder of its time slice, it could not be using 100% of a core because there would be some portion of the time slice given up in each call.

Unless there were nothing else scheduled ready to run, i.e. everything else on the system were waiting on a (kernel) timer or event.
The problem is a call to Sleep() is, theoretically, a way to tell the CPU "don't schedule me for x amount of time" and obviously the scheduler isn't honoring that request. If it did, it would be impossible for the thread to consume 100% of a core because there would be some time given up.  The fact that the CPU utilization is at 100% indicates no time is given up.    Also, the O/S, most of the time, has internal housekeeping chores to take care of (such as zeroing out free pages, getting them ready to be handed to a process that will later, at some point in time, make a memory request), IOW, most of the time, the O/S has something to do other than rescheduling a thread that explicitly asked not be rescheduled until the next cycle.


In any event, Sleep()- with any parameter- is not equivalent to APM.
Absolutely.
FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

MarkMLl

  • Hero Member
  • *****
  • Posts: 3647
Re: Synchronize not working
« Reply #28 on: November 26, 2021, 12:57:59 pm »
The problem is a call to Sleep() is, theoretically, a way to tell the CPU "don't schedule me for x amount of time" and obviously the scheduler isn't honoring that request. If it did, it would be impossible for the thread to consume 100% of a core because there would be some time given up.  The fact that the CPU utilization is at 100% indicates no time is given up.    Also, the O/S, most of the time, has internal housekeeping chores to take care of (such as zeroing out free pages, getting them ready to be handed to a process that will later, at some point in time, make a memory request), IOW, most of the time, the O/S has something to do other than rescheduling a thread that explicitly asked not be rescheduled until the next cycle.

But it /is/ honouring it. Sleep() is defined as taking a parameter in (usually, depending on OS) mSec representing a minimum wallclock time, not a number of cycles of system or application execution. Since a finite (albeit small) amount of wallclock time is taken by the syscall itself, Sleep(0) is behaving as expected.

More significant is whether Sleep(1) reliably pauses for at least one complete mSec on a system where the tick rate is substantially slower than that e.g. every 10 mSec. Or for that matter whether an hypothetical syscall to delay by at least number of ticks- let's call it yield(t)- rounded up or down, i.e. whether yield(1) were guaranteed to delay for at least 10 mSec on a system with 100 ticks per sec or if it might delay for significantly less than that if called just before a tick interrupt. A subsidiary consideration is whether any OSes drift their tick timing to accommodate sleep/yield syscalls, or if it's always guaranteed to stay in sync with the wallclock.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

440bx

  • Hero Member
  • *****
  • Posts: 2618
Re: Synchronize not working
« Reply #29 on: November 26, 2021, 01:27:15 pm »
But it /is/ honouring it.
It isn't and the fact that it consumes 100% of a core proves it.  If the thread was sleeping for _any_ amount of time, it wouldn't be consuming 100% of a core.

More significant is whether Sleep(1) reliably pauses for at least one complete mSec on a system where the tick rate is substantially slower than that e.g. every 10 mSec.
The precision of the time slice given and the amount of time elapsed between time slices are a completely different matter.

The bottom line is: if a thread sleeps then it cannot consume 100% of a CPU.

Sleep(0) is the simplest and fastest way to write a program that is a CPU hog.
FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

 

TinyPortal © 2005-2018