April 30, 2024, 10:48:27 PM

News:

Own IWBasic 2.x ? -----> Get your free upgrade to 3.x now.........


Timers

Started by JoaoAfonso, September 23, 2008, 08:47:42 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

JoaoAfonso

Good evening.

I am doing a program based in an old IB code (a chat program via winsock).

Look at the following code:

sub HandlerUser
def event,temp:int
select @class
case @idinitdialog
temp=NULL
CENTERWINDOW d1
SETFONT d1,"Courier New",8,400,0,1
starttimer d1,200,3
case @idclosewindow
ready=0
case @WinsockListenEvent
event=@code
gosub ClientWelcome
case @WinsockClientEvent
event=@code
gosub ClientEvent
case @idtimer
select @code
case 3
temp=temp+1
IF temp=5
temp=NULL
printf("Second")
ENDIF
endselect
endselect
ENDSUB


If a new connection is made, my program runs the ClientWelcome routine. After the socket is open, each time any info packet arrives at my pc, it runs ClientEvent routine. Also, appart from that, I also have a timer running each 0,2 seconds (increments 1 to variable temp).

If a packet is received exactly when the timer must print "Second", which happens first? What takes precedence?
JoÃÆ'ƒÂÃ,£o Afonso
Viriato
-----------------
Iberia MUD
www.iberiamud.com
iberiamud.com:5900

Ionic Wind Support Team

If the thread has already fired off the timer then it will continue executing until the timer routine returns.  The windows message queue isn't multi threaded.

Paul.
Ionic Wind Support Team

JoaoAfonso

What's happening is that if ClientEvent routine is being run, timer routine stops until ClientEvent ends. Is there a way to do the opposite? At the specific time stop ClientEvent routine, make timer routine run, and at the end return to previous clientevent routine (or something similar)?
JoÃÆ'ƒÂÃ,£o Afonso
Viriato
-----------------
Iberia MUD
www.iberiamud.com
iberiamud.com:5900

Ionic Wind Support Team

Not as written.  As I mentioned the queue is single threaded. Your winsock ClientEvent is using the same queue as the timer, Microsoft makes no guarantees concerning the ordering of messages in the queue.

If the ClientEvent subroutine takes longer than your timer interval then multiple timer messages will be waiting in the message queue for your program to continue processing messages.

To get around it don't use window timers, use multimedia timers:

http://msdn.microsoft.com/en-us/library/ms713423(VS.85).aspx

Multimedia timers run in their own thread and can call a subroutine when the timer expires.

Paul.

Ionic Wind Support Team

hugh

hello paul,
Re your Timer Post
That is now obsolete,
New one is , CreateTimerQueueTimerFunction

CreateTimerQueueTimer Function

Creates a timer-queue timer. This timer expires at the specified due time, then after every specified period. When the timer expires, the callback function is called.

Syntax

BOOL WINAPI CreateTimerQueueTimer(
  __out     PHANDLE phNewTimer,
  __in_opt  HANDLE TimerQueue,
  __in      WAITORTIMERCALLBACK Callback,
  __in_opt  PVOID Parameter,
  __in      DWORD DueTime,
  __in      DWORD Period,
  __in      ULONG Flags
);


Parameters
phNewTimer [out]
A pointer to a buffer that receives a handle to the timer-queue timer on return. When this handle has expired and is no longer required, release it by calling DeleteTimerQueueTimer.

TimerQueue [in, optional]
A handle to the timer queue. This handle is returned by the CreateTimerQueue function.

If this parameter is NULL, the timer is associated with the default timer queue.

Callback [in]
A pointer to the application-defined function of type WAITORTIMERCALLBACK to be executed when the timer expires. For more information, see WaitOrTimerCallback.

Parameter [in, optional]
A single parameter value that will be passed to the callback function.

DueTime [in]
The amount of time to elapse before the timer is to be set to the signaled state for the first time, in milliseconds.

Period [in]
The period of the timer, in milliseconds. If this parameter is zero, the timer is signaled once. If this parameter is greater than zero, the timer is periodic. A periodic timer automatically reactivates each time the period elapses, until the timer is canceled.

Flags [in]
This parameter can be one or more of the following values from Winnt.h.
I stand CORRECTED if i am wrong,

regards.

Hugh




Ionic Wind Support Team

Hugh,
Obsolete means nothing, the function is still there and works fine.  Even in Vista.

Paul.
Ionic Wind Support Team

JoaoAfonso

Tried both functions, but as I can get detailed info in windows.inc from the timeSetEvent, I used it.
Something strange happens, though.

Those are my settings:
DECLARE "kernel32", _timeSetEvent ALIAS timeSetEvent(uDelay AS INT,uResolution AS INT,lpFunction AS INT,dwUser AS INT,uFlags AS INT),INT
CONST TIME_ONESHOT = 0  :'  program timer for single event
CONST TIME_PERIODIC = 1  :'  program for continuous periodic event

_timeSetEvent(200,NULL,&teste,NULL,TIME_PERIODIC)


Purpose: each 200 milliseconds, runs subroutine teste.

Result: no errors, program runs. Then runs just one time subroutine teste, and appears a windows error saying a problem was found in my program, and will be shut down. Anyway, if I do not close this error message, program keeps running (but does not run again subroutine teste, the rest works as supposed)
JoÃÆ'ƒÂÃ,£o Afonso
Viriato
-----------------
Iberia MUD
www.iberiamud.com
iberiamud.com:5900

Ionic Wind Support Team

Are the function parameters correct? 

Should be:

sub teste(UINT uTimerID, UINT uMsg, pointer dwUser, pointer dw1, pointer dw2)
...
endsub

Which is mentioned in that MSDN page I gave you. 

Paul.
Ionic Wind Support Team

JoaoAfonso

That way it does not crash, thank you. This is again something new to me in EB.
JoÃÆ'ƒÂÃ,£o Afonso
Viriato
-----------------
Iberia MUD
www.iberiamud.com
iberiamud.com:5900

JoaoAfonso

Hmm... the tested went ok, but when I start editing that subroutine, program just closes.

SUB heartbeattimer(UINT uTimerID, UINT uMsg, pointer dwUser, pointer dw1, pointer dw2)
INT a,x,pos1,pos2,random,tempint
STRING sel$,sel2$,temp
TERRAINTYPE terr
NPCTYPE npc
PCTYPE pc
(...)


It does not close if I let just the first 2 lines, but when he reads the 3rd line, I believe because of the special type, programs crashes. Any idea what can be the problem now?
JoÃÆ'ƒÂÃ,£o Afonso
Viriato
-----------------
Iberia MUD
www.iberiamud.com
iberiamud.com:5900

JoaoAfonso

And a last question: in MSDN site says the following:

QuoteEach call to timeSetEvent for periodic timer events requires a corresponding call to the timeKillEvent function.

I am using a function each time timer time happens. Should I use timeKillEvent at the end of that function routine? Or it is not needed when using functions?

At first sight, this is exactly what I was after, but need to learn it better, it seems :)
JoÃÆ'ƒÂÃ,£o Afonso
Viriato
-----------------
Iberia MUD
www.iberiamud.com
iberiamud.com:5900

Ionic Wind Support Team

How big are these?

TERRAINTYPE terr
NPCTYPE npc
PCTYPE pc

If larger than 32K then you will need to increase the programs stack size, it's in the advanced options.


Quote
Each call to timeSetEvent for periodic timer events requires a corresponding call to the timeKillEvent function.

Just means they have to be paired.  Since your only calling timeSetEvent once, at least I hope you are only calling it once, then you use timeKillEvent when you want the timer to stop, like when you are ending your program.

Paul.
Ionic Wind Support Team

JoaoAfonso

Couldn't come to internet until now.

Tested with different code, and it runs everything normally except accepting those user types. They are bigger than 32k, but still increasing stack size to irracional numbers, still breaks.

About timeKillEvent, my timer will be periodical. This way, I should use it just at the end of my program, right? I mean, it is advisable to do that, thats correct?

Thanks for the help until now, but still scratching my head. I can create new separated variables in order to reduce those type's sizes, but don't want to do that. This code will be always being updated, and will make my life difficult later for sure.
JoÃÆ'ƒÂÃ,£o Afonso
Viriato
-----------------
Iberia MUD
www.iberiamud.com
iberiamud.com:5900

Ionic Wind Support Team

Use new and delete then, with a pointer. 

And yes, kill the timer at the end of your program if you want it to run continuously.

Paul.
Ionic Wind Support Team

JoaoAfonso

Quote from: Paul Turley on September 24, 2008, 06:53:42 PM
Use new and delete then, with a pointer. 

And yes, kill the timer at the end of your program if you want it to run continuously.

Paul.

New and delete worked :) But explain me, please: why that will work and creating the variable at the beginning of routine forces a crash? This means a pointer spend less system resources than calling that variables at the start of each routine (btw, I am assuming at the end of each routine, all variables created there are erased)?

And do you mean kill the timer at the end of my program, or kill the timer at the end of the routine?
JoÃÆ'ƒÂÃ,£o Afonso
Viriato
-----------------
Iberia MUD
www.iberiamud.com
iberiamud.com:5900

JoaoAfonso

You said what it should be, tested and checked and must only kill timer at the end of program (otherwise it won't be periodical :P).

But still amazes me something, which eventually will make me make a revision of the programs I have that I pretend to still develop: if the use of pointers is less consuming than creating the variable, then I should use it always. Is this like a trick everyone should know? When should it be used then?

Figured out already that when user types are big, it's good to use it :) But always is better?

Paul, many told you this before (including me) for sure, but you know alot. I am imagining you popping up in Ionic Wind foruns like 50 times per day, and for each new post you think like 10 seconds and give the exact solution :)

Not only I get a solution for the problem, but also increase knowledge about other things. I wonder how EB/Aurora would be if your day had 30 hours or if you just need to sleep 2 hours per day. Thank you once more.
JoÃÆ'ƒÂÃ,£o Afonso
Viriato
-----------------
Iberia MUD
www.iberiamud.com
iberiamud.com:5900

Ionic Wind Support Team

You start the timer at the beginning of your program and stop it at the end.  Just like any other timer.

You don't need to continually start a periodic timer, you just start it once and it runs.

Stack space is fixed, by the setting in the advanced options.  It defaults at 32K, and if you exceed stack space your program will crash.  When you define a variable in a subroutine it uses stack space.  If making the stack larger didn't solve your problem then your program is corrupting the stack somewhere. new and delete allocate the memory, instead of locating it on the stack.  The stack size isn't per subroutine, it is overall.  So if you have one subroutine calling another calling another then the total amount of stack in use is the total of all variables defined in those subroutines.

A common user mistake that corrupts stack is using a string array instead of an istring.  I've seen it many times where a user will type:

def name[1000] as string

instead of istring.  Put that in a subroutine and your program will attempt to use 255K of stack, causing a crash.

Anyway I would think about redesigning. UDT's over 32K are not unheard of, just unusual, and you should be able to make them much smaller.

Paul.
Ionic Wind Support Team

JoaoAfonso

September 24, 2008, 08:28:24 PM #17 Last Edit: September 24, 2008, 08:34:32 PM by JoaoAfonso
Read variables from stack are faster than reading from memory? I assume, though, that the difference of times is not significant.

Someday, and I believe that until the end of this year, I will post the code of a final version of the game engine I am making (a MUD engine). I want to do it by myself, just asking advices and use other's code to understand things and eventually use it in my own code, because it is a challenge to me. When finished, there is a fair chance of other MUD players check the engine, which already has the Ionic Wind reference, and thus check the code. As most MUD engines are based in Linux and other OS rather than Windows, and use C rather than other language, this will attract for sure coders to Ionic Wind.

After read your last post here, I believe I won't change all my code as I supposed before it. But before assume it 100%, please check one of the types I created and give me your opinion, please, if you think I should change anything (works as a charm to me, very user friendly so I spend less time understanding my own code):

TYPE EQTYPE
STRING id,tipo,tipo_especifico,name_total,name_1,name_2,name_3
ISTRING describe[1000]
STRING price_novo,uso,bulk,weight,frase_wield,frase_remove,bodypart_layer,fase_dia_aparecimento
STRING emote[11],frase_timer[11]
STRING otherlook[11],resposta[11],reaccao[11],tds_veem_resposta[11]
STRING skill[11],skill_p[11]
ENDTYPE


This are all variables I want in a piece of equipment. The ISTRING is there because it can be a long text string (eventually 1000 is too much, but also eventually I may need it). The STRING emote[11], as all other array strings, are there because I want all 10 strings available to be filled, in each equipment. Again, for me this UDT looks like exactly what I need, and in my eyes it can't be better :D But I have short sight in what concerns programming, so when you have some free time, gimme your opinion.

Thank you
JoÃÆ'ƒÂÃ,£o Afonso
Viriato
-----------------
Iberia MUD
www.iberiamud.com
iberiamud.com:5900

Ionic Wind Support Team

stack is memory.  Only faster because you have to allocate with NEW which takes time.  Accessing the memory itself is the same.

What I would look at is if you need an array of 11 x 255 characters for each of those items.  And thats 11 strings, not 10.  Indexes start at 0.

You could change it to use an istring array to save space.  Or just leave it as is.  Up to you.

Ionic Wind Support Team

JoaoAfonso

September 24, 2008, 11:05:06 PM #19 Last Edit: September 24, 2008, 11:06:51 PM by JoaoAfonso
Yes, I know I can use the [ 0 ] variable. And haven't thought about using ISTRING to create strings smaller than 255.

Thanks for all the tips, Paul
JoÃÆ'ƒÂÃ,£o Afonso
Viriato
-----------------
Iberia MUD
www.iberiamud.com
iberiamud.com:5900

JoaoAfonso

Keep having problems with stack size, but slowly I get rid of them.

I have another question, though, about pointers.

SUB routine(name:STRING), EQTYPE
POINTER eq
eq = NEW(EQTYPE,10)

(...)

RETURN #<EQTYPE>eq
DELETE eq
ENDSUB


I create a pointer and I must delete it. This routine seems logic to me: returning the values in pointer first, then deleting it. Anyway, I receive the following error message pointing to the last line of this routine:

Warning: RETURN value expected. - ENDSUB

EB compile and run it, though, and acts as expected (routine returns the expected values), but something must be wrong and I would like to figure out what.

Thanks in advance
JoÃÆ'ƒÂÃ,£o Afonso
Viriato
-----------------
Iberia MUD
www.iberiamud.com
iberiamud.com:5900

JoaoAfonso

Hmm... another 2 questions:

First one is about minimum requirements of timeSetEvent function. It says in MSDN
QuoteRequirements

  Windows XP: Included in Windows XP only.
  Header: Declared in Mmsystem.h; include Windows.h.
  Library: Use Winmm.lib.

This means it won't work in WinServer03? There is another way to make it work in such OS?

Second question:
timer_id[3]=_timeSetEvent(900000,0,&ping_beat,NULL,TIME_PERIODIC):'15 em 15 minutos
I was expecting this timer would just run each 15 minutes, but he runs each 40 seconds.

*scratching my head*
JoÃÆ'ƒÂÃ,£o Afonso
Viriato
-----------------
Iberia MUD
www.iberiamud.com
iberiamud.com:5900

Ionic Wind Support Team

Your delete statement is never being executed, since it is after the return statement.  Be nice if the world worked that way, but it doesn't ;)

The warning is because the compiler is expecting a return after the delete statement, it knows it's backwards.

return the pointer and delete it elsewhere.

Paul.

Quote from: JoaoAfonso on September 25, 2008, 07:03:40 AM
Keep having problems with stack size, but slowly I get rid of them.

I have another question, though, about pointers.

SUB routine(name:STRING), EQTYPE
POINTER eq
eq = NEW(EQTYPE,10)

(...)

RETURN #<EQTYPE>eq
DELETE eq
ENDSUB


I create a pointer and I must delete it. This routine seems logic to me: returning the values in pointer first, then deleting it. Anyway, I receive the following error message pointing to the last line of this routine:

Warning: RETURN value expected. - ENDSUB

EB compile and run it, though, and acts as expected (routine returns the expected values), but something must be wrong and I would like to figure out what.

Thanks in advance
Ionic Wind Support Team

Ionic Wind Support Team

Actually it probably will work with server 2003 as well.  It is also in Windows 9x, as I have used it before.  When Microsoft calls a function "obsolete" they plan on dropping it in the distant future.  If the call it "deprecated" then they drop it in the next version of Windows.  Obsolete functions are usually wrappers for a different function that they want you to start using. Such as the one Hugh mentioned.

As for your time problem...multimedia timers are meant for small time periods with great accuracy, you originally where using it for 200 microsecond intervals so that would be appropriate.  If you want a 15 minute timeout then accuracy isn't that important and you can use a windows timer.  The maximum range of the multimedia timers can be found using this:

http://msdn.microsoft.com/en-us/library/ms713416(VS.85).aspx

Paul.

Quote from: JoaoAfonso on September 25, 2008, 07:47:32 AM
Hmm... another 2 questions:

First one is about minimum requirements of timeSetEvent function. It says in MSDN
QuoteRequirements

  Windows XP: Included in Windows XP only.
  Header: Declared in Mmsystem.h; include Windows.h.
  Library: Use Winmm.lib.

This means it won't work in WinServer03? There is another way to make it work in such OS?

Second question:
timer_id[3]=_timeSetEvent(900000,0,&ping_beat,NULL,TIME_PERIODIC):'15 em 15 minutos
I was expecting this timer would just run each 15 minutes, but he runs each 40 seconds.

*scratching my head*
Ionic Wind Support Team

JoaoAfonso

Got two lessons more (if you say so I must delete pointer in other place, but it will be uglier! :))!
Also figured out after trying other alternatives that I can still use EB timers and have the results I wanted. Own EB commands make programs more stable. You deserve a place in heaven :P

Thank you
JoÃÆ'ƒÂÃ,£o Afonso
Viriato
-----------------
Iberia MUD
www.iberiamud.com
iberiamud.com:5900