Shop OBEX P1 Docs P2 Docs Learn Events
General question about Objects — Parallax Forums

General question about Objects

DRMorrisonDRMorrison Posts: 81
edited 2014-07-04 18:15 in Propeller 1
I have a small program that has need to time some events differently that other events, so I created the code below to do just that. I can call on it to start a timer, and then set a
flag when it finishes. My main program checks the status of the flag at its convenience. I can also stop the timer, reset the timer, pause and resume the timer. This all happens
in another cog. Most of the calls that are made to this are no less than 30 seconds in length, so timing isn't critical.

My question is this: Do I need to do the init that I set up here? considering that this does nothing until the start method is sent anyway? After all, the cog isn't even running
until I call the start method.

Thanks for looking
[COLOR=#000000][/COLOR][B][COLOR=#000000]VAR                           ''6 Vars, 1 Stack[/COLOR]
[COLOR=#000000] long TimerStack[50]          [/COLOR]
[COLOR=#000000] long ThisCog, RunStatus, TimeOutFlag, TimerPause, ResetTime, Re_set    [/COLOR]
[COLOR=#000000]'-------------------------- PUBlic methods -------------------------[/COLOR]
[COLOR=#000000]PUB Init                      ''Call for Initial setup, and a good way to reset all[/COLOR]
[COLOR=#000000] RunStatus := 0[/COLOR]
[COLOR=#000000] TimeOutFlag := 0[/COLOR]
[COLOR=#000000] TimerPause := 0[/COLOR]
[COLOR=#000000] Re_set := 0[/COLOR]

[COLOR=#000000]PUB Start(InputTime)          ''Call to Start the timer with input (seconds)[/COLOR]
[COLOR=#000000] if InputTime > 0 AND RunStatus == 0[/COLOR]
[COLOR=#000000]   ThisCog := cognew(Timer(InputTime), @TimerStack)[/COLOR]

[COLOR=#000000]PUB Reset(RstTime)            ''Call to Reset the timer with input parameter: RstTime [/COLOR]
[COLOR=#000000] if RstTime > 0 AND RunStatus == 1[/COLOR]
[COLOR=#000000]   ResetTime := RstTime        'Previous timer is re-set to RstTime[/COLOR]
[COLOR=#000000]   Re_set := 1[/COLOR]
[COLOR=#000000] else[/COLOR]
[COLOR=#000000]   return 0[/COLOR]

[COLOR=#000000]PUB Pause                     ''Call to Pause the timer[/COLOR]
[COLOR=#000000] TimerPause := 1[/COLOR]
[COLOR=#000000]
[/COLOR]
[COLOR=#000000]PUB Resume                    ''Call to Resume the timer[/COLOR]
[COLOR=#000000] TimerPause := 0[/COLOR]
[COLOR=#000000]
[/COLOR]
[COLOR=#000000]PUB Stop                      ''Call to Stop the timer and cog...[/COLOR]
[COLOR=#000000] if RunStatus == 1             'if it is running[/COLOR]
[COLOR=#000000]   RunStatus := 0[/COLOR]
[COLOR=#000000]   TimeOutFlag := 0  [/COLOR]
[COLOR=#000000]   cogstop(ThisCog)[/COLOR]
[COLOR=#000000] else[/COLOR]
[COLOR=#000000]   return 0                     'or else indicate that the timer is not running[/COLOR]

[COLOR=#000000]PUB Status                    ''Call for Status of timer i.e. running/not[/COLOR]
[COLOR=#000000] return RunStatus[/COLOR]

[COLOR=#000000]PUB TimeOut                   ''Call to determine if the timer has run out[/COLOR]
[COLOR=#000000] return TimeOutFlag[/COLOR]

[COLOR=#000000]'-------------------------- PRIvate methods --------------------------   [/COLOR]
[COLOR=#000000]PRI Timer(InputTime)|t        'Timer: runs in another cog[/COLOR]
[COLOR=#000000] TimeOutFlag := 0[/COLOR]
[COLOR=#000000] RunStatus := 1    [/COLOR]
[COLOR=#000000] t := cnt[/COLOR]

[COLOR=#000000] repeat while InputTime > 0[/COLOR]
[COLOR=#000000]   InputTime -= 1    [/COLOR]
[COLOR=#000000]   waitcnt(t += clkfreq)   [/COLOR]
[COLOR=#000000]    if Re_set              [/COLOR]
[COLOR=#000000]     InputTime := ResetTime    'InputTime gets reset with a Reset(x) call[/COLOR]
[COLOR=#000000]     Re_set := 0[/COLOR]
[COLOR=#000000]   repeat while TimerPause     'if Pause is called, timer waits here for a Resume call[/COLOR]
[COLOR=#000000]    waitcnt(t += clkfreq/100) [/COLOR]

[COLOR=#000000] TimeOutFlag := 1[/COLOR]
[COLOR=#000000] RunStatus := 0     [/COLOR]
[COLOR=#000000] cogstop(ThisCog)[/COLOR]
[/B]

Comments

  • MagIO2MagIO2 Posts: 2,243
    edited 2014-07-02 00:25
    Clean programming guidelines do one very usefull thing: they avoid bugs!

    Yes, in the special case where the program is in a correct (definded) state, it does not make a difference. But software usually get's changed and somewhen there could be a change which only works fine most time, but some race condition makes it fail - just sometimes.

    In your example it would be a bad thing to call Stop without having initialized the ThisCog variable before. Or calling Status would simple give you an undefined result.

    2 more comments:
    1. in Timer you call cogstop. This is not an error, but I would not do that. Cogstop is usefull if a COG needs to be stopped from within another COG (in Stop function), but it is not needed for a COG to stop itself.
    2. It is very common to set ThisCog to the value of cognew(..) + 1 which allows to do this:
    if ThisCog
    ThisCog := 0
    cogstop(ThisCog-1)

    This would prevent errors in case that Stop is called more than one time.

    Maybe it would also be a good idea to return ThisCog in the Start-function. So a caller can check wheather the propeller ran out of COGs.

    To answer your question: Yes, I think something like an Init-function makes sense. For general purpose libraries even more than for some specialized code. If your project runs out of HUB-RAM, the Init-code or any other code added to make the program more failsafe can be stripped down at this point of time as a special solution.
  • DRMorrisonDRMorrison Posts: 81
    edited 2014-07-02 08:31
    MagIO2 wrote: »
    In your example it would be a bad thing to call Stop without having initialized the ThisCog variable before. Or calling Status would simple give you an undefined result.

    This answers my question--I think. So the variables are set up in the init call, and then is retained for later use--if I understand correctly? And the only time it gets wiped out is if the
    power is lost? That sort of thing?
    MagIO2 wrote: »
    in Timer you call cogstop. This is not an error, but I would not do that. Cogstop is usefull if a COG needs to be stopped from within another COG (in Stop function), but it is not needed for a COG to stop itself.

    The TimerObj runs in another Cog, and gets called to stop only if the method that called it needs to stop it; otherwise, it stops itself once the timer runs down. It sets the TimeOutFlag flag to indicate that this has happened.

    Are you saying that if cogstop is called, and there is no cog running, an error will occur?
    So the following won't work, in general?
    PUB stop_all | index
     repeat index from 1 to 7
       cogstop(index)
    



    Thank you, Daniel
  • MagIO2MagIO2 Posts: 2,243
    edited 2014-07-04 10:21
    What I mean is, that the cogstop in the function timer is not needed. If the function that's being started in a COG comes to the end, that COG is stopped by 'nature'.
    A cogstop is only needed in the stop function, as this function is running in a separate COG which shall stop the timer-COG if called.

    And to make the object more failsafe, your start function could call stop just to make sure that there is no forgotten timer running.
  • DRMorrisonDRMorrison Posts: 81
    edited 2014-07-04 18:15
    Great ideas. I'll use them.
    Thanks.
    Daniel
Sign In or Register to comment.