Inducing delay with out a blocking wait

13 posts / 0 new
Last post
tekmage
tekmage's picture
Offline
Last seen: 2 years 3 weeks ago
Joined: 2011-10-09 03:19
Inducing delay with out a blocking wait

Hi All,

I'm trying to induce a pause in an application that renders to the screen. Currently I'm using IDos->Delay(1) but I'd like to have more then 50'th of a second and I'd prefer not to use a Delay. I'd love some tips!

Cheers,
Bill

trixie
trixie's picture
Offline
Last seen: 6 months 3 weeks ago
Joined: 2011-02-03 13:58
Re: Inducing delay with out a blocking wait

You might try waiting for IDCMP_INTUITICK messages. Intuiticks are generated about every 1/10 of a second. The solution would require going into a Wait() IDCMP loop, counting the required number of intuiticks, and acting accordingly.

AmigaOne X5000-020 / 2GB RAM / Sapphire Pulse Radeon RX 560 / AmigaOS 4.1 Final Edition Update 2

tekmage
tekmage's picture
Offline
Last seen: 2 years 3 weeks ago
Joined: 2011-10-09 03:19
Thanks Trixie, I'll take a

Thanks Trixie,

I'll take a look at the docs for IDCMP_INTUITICK and see how that works.

Cheers,
Bill

tekmage
tekmage's picture
Offline
Last seen: 2 years 3 weeks ago
Joined: 2011-10-09 03:19
Hi trixie, Where are the new

Hi trixie,

Where are the new laws posted?

hypex
hypex's picture
Offline
Last seen: 3 months 3 weeks ago
Joined: 2011-09-09 16:20
You could also use

You could also use timer.device. Not as easy as a library but it is the standard Amiga way of doing it. We could use an alarm or timer function for OS4 right now!

You are right to look for a better way than Delay(). Internally this opens timer.device on every call so not very efficient! Still not fixed in OS4.

trixie
trixie's picture
Offline
Last seen: 6 months 3 weeks ago
Joined: 2011-02-03 13:58
Re: Inducing delay with out a blocking wait

@tekimage

Hi trixie,

Where are the new laws posted?

What laws??? :-)

AmigaOne X5000-020 / 2GB RAM / Sapphire Pulse Radeon RX 560 / AmigaOS 4.1 Final Edition Update 2

salass00
salass00's picture
Offline
Last seen: 6 months 2 weeks ago
Joined: 2011-02-03 11:27
@tekmage Open and close

@tekmage

Open and close timer.device:

  1. struct MsgPort *TimerPort = NULL;
  2. struct TimeRequest *TimerIO = NULL;
  3. BOOL TimerInUse = FALSE;
  4.  
  5. BOOL OpenTimerDevice (void) {
  6. TimerPort = IExec->AllocSysObject(ASOT_PORT, NULL);
  7. TimerIO = IExec->AllocSysObjectTags(ASOT_IOREQUEST,
  8. ASOIOR_ReplyPort, TimerPort,
  9. ASOIOR_Size, sizeof(struct TimeRequest),
  10. TAG_END);
  11. if (TimerIO) {
  12. if (IExec->OpenDevice("timer.device", UNIT_MICROHZ,
  13. (struct IORequest *)TimerIO, 0) == IOERR_SUCCESS)
  14. {
  15. return TRUE;
  16. }
  17. TimerIO->Request.io_Device = NULL;
  18. }
  19. return FALSE;
  20. }
  21.  
  22. void CloseTimerDevice (void) {
  23. if (TimerIO && TimerIO->Request.io_Device) {
  24. if (TimerInUse) {
  25. IExec->AbortIO((struct IORequest *)TimerIO);
  26. IExec->WaitIO((struct IORequest *)TimerIO);
  27. }
  28. IExec->CloseDevice((struct IORequest *)TimerIO);
  29. }
  30. IExec->FreeSysObject(ASOT_IOREQUEST, TimerIO);
  31. IExec->FreeSysObject(ASOT_PORT, TimerPort);
  32. }

Start a timer request:

  1. TimerIO->Request.io_Command = TR_ADDREQUEST;
  2. TimerIO->Time.Seconds = seconds;
  3. TimerIO->Time.Microseconds = microseconds;
  4. IExec->SendIO((struct IORequest *)TimerIO);
  5. TimerInUse = TRUE;

Then in your event loop:

  1. signals_received = IExec->Wait((1 << TimerPort->mp_SigBit)|other_signals_to_wait_for);
  2. if (signals_received & (1 << TimerPort->mp_SigBit)) {
  3. IExec->WaitIO((struct IORequest *)TimerIO);
  4. TimerInUse = FALSE;
  5. Printf("Timer request is finished\n");
  6. }

Of course if you just need a more accurate version of IDOS->Delay() you can just use IExec->DoIO() (returns when the specified time has elapsed):

  1. TimerIO->Request.io_Command = TR_ADDREQUEST;
  2. TimerIO->Time.Seconds = seconds;
  3. TimerIO->Time.Microseconds = microseconds;
  4. IExec->DoIO((struct IORequest *)TimerIO);
tekmage
tekmage's picture
Offline
Last seen: 2 years 3 weeks ago
Joined: 2011-10-09 03:19
Thanks salass00. AlexC had a

Thanks salass00.

AlexC had a simpler example:

  1. #include <proto/exec.h>
  2. #include <proto/timer.h>
  3. #include <proto/dos.h>
  4.  
  5. int main(int argc,char **argv)
  6. {
  7. int32 result = 0;
  8. ITimer->MicroDelay(1000);
  9. return(result);
  10. }

To compile the above lib auto is used to open the device:

gcc -o microdelay microdelay.c -lauto

Stuck on trying to figure out the least amount of stuff to get the above to compile without libauto. Looking at timer.xml everything looks like a library but OpenLibrary does not seam to do it.

salass00
salass00's picture
Offline
Last seen: 6 months 2 weeks ago
Joined: 2011-02-03 11:27
Don't use MicroDelay() in

Don't use MicroDelay() in general code as it's polling (ties up the CPU while it waits). MicroDelay() should only ever be used for very small delays in places where multitasking is disabled or in interrupt code. As stated in the AutoDocs MicroDelay() is only really useful for driver writers that may need to use it for the simple reason that it doesn't need multitasking in order to work.

salass00
salass00's picture
Offline
Last seen: 6 months 2 weeks ago
Joined: 2011-02-03 11:27
If you need an usleep() type

If you need an usleep() type function you can just use:

  1. void USleep (uint32 microseconds) {
  2. TimerIO->Request.io_Command = TR_ADDREQUEST;
  3. TimerIO->Time.Seconds = microseconds / 1000000;
  4. TimerIO->Time.Microseconds = microseconds % 1000000;
  5. IExec->DoIO((struct IORequest *)TimerIO);
  6. }

Or of course if you're not concerned about writing using AmigaOS API functions you can just use usleep() from newlib (works same as MicroDelay() only it doesn't use a polling loop, instead it uses timer.device in more or less the same way as I wrote above).

  1. #include <unistd.h>
  2.  
  3. int main(int argc,char **argv)
  4. {
  5. int result = 0;
  6. usleep(1000);
  7. return(result);
  8. }
hypex
hypex's picture
Offline
Last seen: 3 months 3 weeks ago
Joined: 2011-09-09 16:20
Does newlib usleep() also

Does newlib usleep() also open up timer.device and required resources when it is called every time like Delay()O or is it cleaner?

salass00
salass00's picture
Offline
Last seen: 6 months 2 weeks ago
Joined: 2011-02-03 11:27
@hypex Does newlib usleep()

@hypex


Does newlib usleep() also open up timer.device and required resources when it is called every time like Delay()O or is it cleaner?

You do know that AmigaOS since version 1.0 caches libraries and devices so that they aren't reloaded every time there is an OpenDevice() or OpenLibrary()?

When a library or device is already in memory (timer.device is always in memory since it's in Kickstart) it's pretty much only a quick list lookup for "timer.device" and incrementing some open counters so there really isn't much overhead, plus opening/closing libraries/devices only when they are needed has the advantage that the OS can expunge them when they are not needed if it needs to create free memory for something else.

hypex
hypex's picture
Offline
Last seen: 3 months 3 weeks ago
Joined: 2011-09-09 16:20
Yes I do know they are

Yes I do know they are resident and maybe that's a big problem with AmigaOS. I have seen applcations call OS functions and use a snopping tool to watch hundreds of fonts being opened and devices. Delay() is one for this. It looks unnecessary and not very efficient to always allocate memory for these structures and open these resources when ever a function is called. Everything should be cached for futher use, not just a library.

I think this sort of thing would contribute to AmigaOS slowing down and in real use AmigaOS isn't fast any more. It can and will choke at a simple mouse move these days.

Log in or register to post comments