Timers, which one to use ??? Total crash...

Linux specific forum
Joris
Addict
Addict
Posts: 885
Joined: Fri Oct 16, 2009 10:12 am
Location: BE

Timers, which one to use ??? Total crash...

Post by Joris »

Hi,

The code below works nice, but if I include it in my main source it doesn't wont to work.
These are the errors :
[11:29:45] Executable started.
[11:29:45] [WARNING] UB Connect Check.pb (Line: 1)
[11:29:45] [WARNING] GLib-GIO (DEBUG): _g_io_module_get_default: Found default implementation gvfs (GDaemonVfs) for ‘gio-vfs’
[11:30:07] [WARNING] UB Timers.pbi (Line: 53)
[11:30:07] [WARNING] GLib (CRITICAL): Source ID 792 was not found when attempting to remove it
It looks like the timer isn't started but still made, until trying to remove it (as it doesn't run) ???

I wont to have a time function which doesn't get delay by other system things, like moving the window around or so ...
In windows this is done with timeSetEvent_(..., ..., @Timer_Callback(), TimerID, #TIME_PERIODIC)
In Ubuntu (later on the Raspberry PI) I use that g_timeout_add_full_(...), is That the wright one or what else ?

Thanks

Code: Select all

;************************************************************************************************************************
;{***********************************************************************************************************************
; http://library.gnome.org/devel/glib/stable/glib-The-Main-Event-Loop.html#g-timeout-add
;https://www.gtk-server.org/gtk1/glib/glib-the-main-event-loop.html#G-TIMEOUT-ADD-FULL
;https://www.purebasic.fr/english/viewtopic.php?p=235856&hilit=timer#p235856

; Registers a function To be called periodically. The function will be called repeatedly after interval milliseconds 
;Until it returns FALSE at which point the timeout is destroyed And will Not be called again.
; 
; interval : The time between calls To the function, in milliseconds (1/1000ths of a second.)
; function :The function To call periodically.
; Data :  The Data To pass To the function.
; Returns : 	A unique id For the event source. 
#G_PRIORITY_HIGH         = -100
#G_PRIORITY_DEFAULT      = 0
#G_PRIORITY_HIGH_IDLE    = 100
#G_PRIORITY_DEFAULT_IDLE = 200
#G_PRIORITY_LOW	         = 300
;Use this for high priority event sources. It is not used within GLib or GTK+.
;G_PRIORITY_DEFAULT
;Use this for default priority event sources. In GLib this priority is used when adding timeout functions with g_timeout_add(). In GDK this priority is used for events from the X Windows server.
;G_PRIORITY_HIGH_IDLE
;Use this for high priority idle functions. GTK+ uses G_PRIORITY_HIGH_IDLE + 10 for resizing operations, and G_PRIORITY_HIGH_IDLE + 20 for redrawing operations. (This is done to ensure that any pending resizes are processed before any pending redraws, so that widgets are not redrawn twice unnecessarily.)
;G_PRIORITY_DEFAULT_IDLE
;Use this for default priority idle functions. In GLib this priority is used when adding idle functions with g_idle_add().
;G_PRIORITY_LOW
;************************************************************************************************************************
Structure TIMER_SETUP
  res.i                       ;MINIMUM RESOLUTIE VAN DE TIMER (wPeriodMin in TIMECAPS)
  tik.i                       ;RESOLUTIE IN MILLISECONDS VOOR DE TIMER
  index.i                  ;TIMER INDEX
  priority.i              ;DOOR TE GEVEN WAARDE AAN TIMER 
  adr.i                       ;TIMER PROC ADRES
  info_adr.i              ;TIMER PROC ADRES
  running.a              ;TIMER GESTART OF NIET
EndStructure
Global TM.TIMER_SETUP
;}************************************************************************************************************************
;************************************************************************************************************************
Procedure Timer_Setup(*p.TIMER_SETUP,res.i, priority.i, adr.i, info_adr.i=0)
      
      With *p
        \res=res      
        \priority=priority       
        \adr=adr        
        \info_adr=info_adr     
        \index=0
      EndWith
      
EndProcedure
Procedure.i Timer_Remove(*p.TIMER_SETUP)
      
      If *p\index
          If   g_source_remove_( *p\index) 
              *p\index=0
               ProcedureReturn #False
          EndIf
      EndIf
      
EndProcedure
Procedure.i Full_Timer_Start(*p.TIMER_SETUP)      ;timer met priority setting
      
      If *p\index
          Timer_Remove(*p)
      Else
          *p\index=g_timeout_add_full_( *p\priority, *p\res,  *p\adr, *p\info_adr, #Null)
          ProcedureReturn #True
      EndIf
      ProcedureReturn #False
      
EndProcedure
Procedure.i Timer_Start(*p.TIMER_SETUP)              ;timer zonder priority setting, kan door events vertraagd worden
      
      If *p\index
          Timer_Remove(*p)
      Else
          *p\index=g_timeout_add_(*p\res, *p\adr, #Null)
          ProcedureReturn #True
      EndIf
      ProcedureReturn #False
      
EndProcedure

;************************************************************************************************************************
CompilerIf #PB_Compiler_IsMainFile
  
  Procedure MyTimeOutFunction(*pdata)
        Debug "hello"
        If stoptimer = #False
            ProcedureReturn #True
        Else
            ProcedureReturn #False
        EndIf
  EndProcedure
  
  If OpenWindow(0, 0, 0, 300, 50, "TimeOut example...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
      ButtonGadget(1, 10, 10, 280, 30, "Stop timer")
      
      Timer_Setup(@TM, 300,#G_PRIORITY_HIGH,  @MyTimeOutFunction())
      Full_Timer_Start(@TM)
     ;Timer_Start(@TM)
      Repeat
        
        If EventGadget() = 1
            Timer_Remove(@TM)
            Debug TM\index
            DisableGadget(1, 1)
        EndIf
        
      Until WaitWindowEvent()=#PB_Event_CloseWindow
  EndIf
  
CompilerEndIf 
  ;************************************************************************************************************************
  
Last edited by Joris on Fri Feb 25, 2022 11:30 am, edited 1 time in total.
Yeah I know, but keep in mind ... Leonardo da Vinci was also an autodidact.
Joris
Addict
Addict
Posts: 885
Joined: Fri Oct 16, 2009 10:12 am
Location: BE

Re: Timers, which one to use ???

Post by Joris »

Hi,

I included all timer things in one code below.
The timer doesn't run as should, Only one shot and finished.
Often when trying to remove that timer a total crash...

I realy don't know what can be the reason or solution (most probably something very simple :mrgreen: ).

Thanks

Code: Select all

;**************************************************************************
;{
;**************************************************************************
;{
EnableExplicit
IncludePath "/home/joris/Documenten/PB Code/Includes/"
;XIncludeFile "UB Timers.pbi"
Global.i Event, Window_1
;**************************************************************************
Global.i btn_000, btn_001 
;**************************************************************************
;}
;**************************************************************************
;{
;**************************************************************************
;************************************************************************************************************************
#G_PRIORITY_HIGH         = -100
#G_PRIORITY_DEFAULT      = 0
#G_PRIORITY_HIGH_IDLE    = 100
#G_PRIORITY_DEFAULT_IDLE = 200
#G_PRIORITY_LOW	         = 300

;G_PRIORITY_HIGH_IDLE
;Use this for high priority idle functions. GTK+ uses G_PRIORITY_HIGH_IDLE + 10 for resizing operations, and G_PRIORITY_HIGH_IDLE + 20 for redrawing operations. (This is done to ensure that any pending resizes are processed before any pending redraws, so that widgets are not redrawn twice unnecessarily.)
;************************************************************************************************************************
Structure TIMER_SETUP
  res.i                  
  tik.i                       
  index.i                 
  priority.i               
  adr.i                      
  info_adr.i             
  running.a              
EndStructure
Global TM.TIMER_SETUP
Procedure Timer_Setup(*p.TIMER_SETUP,res.i, priority.i, adr.i, info_adr.i=0)
      
      With *p
        \res=res      
        \priority=priority       
        \adr=adr        
        \info_adr=info_adr     
        \index=0
      EndWith
      
EndProcedure
Procedure.i Timer_Remove(*p.TIMER_SETUP)
      
      If *p\index
          If   g_source_remove_(*p\index) 
              *p\index=0
          EndIf
      EndIf
      ProcedureReturn  *p\index
      
EndProcedure
Procedure.i Full_Timer_Start(*p.TIMER_SETUP)      ;timer met priority setting
      
      If *p\index
          Timer_Remove(*p)
      Else
          *p\index=g_timeout_add_full_(*p\priority, *p\res,  *p\adr, *p\info_adr, #Null)
          ProcedureReturn  *p\index
      EndIf
      ProcedureReturn #False
      
EndProcedure
Procedure.i Timer_Start(*p.TIMER_SETUP)              ;timer zonder priority setting, kan door events vertraagd worden
      
      If *p\index
          Timer_Remove(*p)
      Else
          *p\index=g_timeout_add_(*p\res, *p\adr, #Null)
          ProcedureReturn  *p\index
      EndIf
      ProcedureReturn #False
      
EndProcedure
;************************************************************************************************************************
Procedure MyTimeOutFunction()
      Debug "hoi  "+ Str(TM\index)
EndProcedure
Procedure Setup_GUI()
  GadgetToolTip(btn_000, "000")
  GadgetToolTip(btn_001, "001")
  ;**************************************************************************
  ;**************************************************************************
  ;**************************************************************************
  ;**************************************************************************
  ;SetGadgetText(Gadget, "Gadget Example")
  ;SetGadgetState(Gadget, #True)
  ;SetGadgetState(Gadget, #PB_Checkbox_Checked)
  ;SetToolBarButtonState(Gadget, #Tlb_Mode, #True)
  ;SetGadgetState(Gadget, MakeIPAddress(127, 0, 0, 1))
EndProcedure
;**************************************************************************
Procedure Build_Window_1(x = 0, y = 0, width = 230, height = 160)
  Window_1 = OpenWindow(#PB_Any, #PB_Ignore, #PB_Ignore, width, height, "", #PB_Window_SystemMenu |#PB_Window_ScreenCentered)
  btn_000 = ButtonGadget(#PB_Any,  30,  10,  69,  21, "gadget_000")
  btn_001 = ButtonGadget(#PB_Any, 116,  10,  69,  21, "gadget_001")
EndProcedure
;**************************************************************************
Procedure Close_Program()
  ; FreeList(list())
  ; FreeMap(Map())
  ; FreeArray(array())
  ; FreeMemory(memory)
EndProcedure
;**************************************************************************
Procedure EventLoop()
  Build_Window_1()
  Setup_GUI()
  gtk_init_(0,0) 
  
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_Gadget
        Select EventGadget()
          Case btn_000 : 
            Timer_Setup(@TM, 300,#G_PRIORITY_HIGH,  @MyTimeOutFunction())
            TM\index=Full_Timer_Start(@TM)
            ;TM\index=Timer_Start(@TM)
            Debug TM\res
            Debug TM\priority
             Debug  #G_PRIORITY_HIGH
             Debug TM\index
         Case btn_001 : 
               Timer_Remove(@TM)
            Debug TM\index
        EndSelect
      Case #PB_Event_Menu
      Case #PB_Event_CloseWindow
        Close_Program()
        CloseWindow(#PB_All)
        End
    EndSelect
  ForEver
EndProcedure
EventLoop()
Yeah I know, but keep in mind ... Leonardo da Vinci was also an autodidact.
User avatar
mk-soft
Always Here
Always Here
Posts: 5388
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Timers, which one to use ??? Total crash...

Post by mk-soft »

Something very overworked for a change.

If the callback returns 'NULL', the GScoureFunc is automatically removed. Thus one must always return #True (Continue).
With user_data you can always pass a pointer to your own data.

The callback is internally hooked back into the MainScope. So you don't need a ThreadSafe and a PostEvent to change gadget content.

Update v1.02.1

Code: Select all

;-TOP by mk-soft, v1.02.1

#G_PRIORITY_HIGH         = -100
#G_PRIORITY_DEFAULT      = 0
#G_PRIORITY_HIGH_IDLE    = 100
#G_PRIORITY_DEFAULT_IDLE = 200
#G_PRIORITY_LOW	         = 300

#G_SOURCE_CONTINUE = 1

Structure udtTimerHeader
  ; Header
  TimerID.i
EndStructure

PrototypeC GSourceFunc(*UserData)

; ----

Procedure AddTimer(*Timer.udtTimerHeader, Interval, *Callback.GSourceFunc)
  
  If *Timer And *Timer\TimerID = 0
    *Timer\TimerID = g_timeout_add_full_(#G_PRIORITY_HIGH, Interval, *Callback.GSourceFunc, *Timer, 0)
  EndIf
  
  ProcedureReturn *Timer\TimerID
EndProcedure

Procedure RemoveTimer(*Timer.udtTimerHeader)
  Protected r1
  If *Timer And *Timer\TimerID
    r1 = g_source_remove_(*Timer\TimerID)
    *Timer\TimerID = 0
  EndIf
  ProcedureReturn r1
  
EndProcedure

;********

CompilerIf #PB_Compiler_IsMainFile
  
  ;-Example
  
  Structure udtTimerData Extends udtTimerHeader
    UserID.i
    Count.i
  EndStructure
  
  Enumeration Windows
    #Main
  EndEnumeration
  
  Enumeration Gadgets
    #MainList
    #MainButtonStartT1
    #MainButtonStopT1
    #MainButtonStartT2
    #MainButtonStopT2
    #MainButtonStartT3
  EndEnumeration
  
  Enumeration Status
    #MainStatusBar
  EndEnumeration
  
  ; ----
  
  ProcedureC TimerCB(*UserData.udtTimerData)
    Protected text.s
    
    With *UserData
      \Count + 1
      text = "TimerID " + \TimerID + " | UserID " + \UserID + " : Count " + \Count
      AddGadgetItem(#MainList, -1, text)
      SetGadgetState(#MainList, CountGadgetItems(#MainList) - 1)
      SetGadgetState(#MainList, -1)
      ;CallDebugger
    EndWith
    ProcedureReturn #G_SOURCE_CONTINUE
  EndProcedure
  
  ProcedureC TimerOneShutCB(*UserData.udtTimerData)
    Protected text.s
    
    With *UserData
      text = "TimerID " + \TimerID + " | UserID " + \UserID + " : Finished"
      AddGadgetItem(#MainList, -1, text)
      SetGadgetState(#MainList, CountGadgetItems(#MainList) - 1)
      SetGadgetState(#MainList, -1)
      \TimerID = 0
    EndWith
    ProcedureReturn #Null
  EndProcedure
  
  ; ----
  Procedure UpdateWindow()
    Protected dx, dy
    dx = WindowWidth(#Main)
    dy = WindowHeight(#Main) - StatusBarHeight(#MainStatusBar)
    ; Resize gadgets
    ResizeGadget(#MainList, 10, 10, dx - 20, dy - 60)
    ResizeGadget(#MainButtonStartT1, 10, dy - 40, 120, 25)
    ResizeGadget(#MainButtonStopT1, 140, dy - 40, 120, 25)
    ResizeGadget(#MainButtonStartT2,270, dy - 40, 120, 25)
    ResizeGadget(#MainButtonStopT2, 400, dy - 40, 120, 25)
    ResizeGadget(#MainButtonStartT3, 530, dy - 40, 120, 25)
  EndProcedure
  
  Procedure Main()
    Protected dx, dy
    
    Protected timer1.udtTimerData
    Protected timer2.udtTimerData
    Protected timer3.udtTimerData
    
    timer1\UserID = 1
    timer2\UserID = 2
    timer2\Count = 10000
    timer3\UserID = 3
    
    #MainStyle = #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget
    
    If OpenWindow(#Main, #PB_Ignore, #PB_Ignore, 800, 600, "Window" , #MainStyle)
      CreateStatusBar(#MainStatusBar, WindowID(#Main))
      AddStatusBarField(#PB_Ignore)
      
      dx = WindowWidth(#Main)
      dy = WindowHeight(#Main) - StatusBarHeight(#MainStatusBar)
      
      ListViewGadget(#MainList, 10, 10, dx - 20, dy - 60)
      ButtonGadget(#MainButtonStartT1, 10, dy - 40, 120, 25, "Start 1")
      ButtonGadget(#MainButtonStopT1, 140, dy - 40, 120, 25, "Stop 1")
      ButtonGadget(#MainButtonStartT2,270, dy - 40, 120, 25, "Start 2")
      ButtonGadget(#MainButtonStopT2, 400, dy - 40, 120, 25, "Stop 2")
      ButtonGadget(#MainButtonStartT3, 530, dy - 40, 120, 25, "Start 3")
      
      
      BindEvent(#PB_Event_SizeWindow, @UpdateWindow(), #Main)
      
      Repeat
        Select WaitWindowEvent()
          Case #PB_Event_CloseWindow
            Break
            
          Case #PB_Event_Gadget
            Select EventGadget()
              Case #MainButtonStartT1
                AddTimer(timer1, 500, @TimerCB())
                
              Case #MainButtonStopT1
                RemoveTimer(timer1)
                
              Case #MainButtonStartT2
                AddTimer(timer2, 100, @TimerCB())
                
              Case #MainButtonStopT2
                RemoveTimer(timer2)
                
              Case #MainButtonStartT3
                AddTimer(timer3, 2000, @TimerOneShutCB())
                
            EndSelect
            
        EndSelect
        
      ForEver
      
      ; don't forgot -> Crash
      RemoveTimer(timer1)
      RemoveTimer(timer2)
      
    EndIf
    
  EndProcedure : Main()
  
CompilerEndIf
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Joris
Addict
Addict
Posts: 885
Joined: Fri Oct 16, 2009 10:12 am
Location: BE

Re: Timers, which one to use ??? Total crash...

Post by Joris »

Mk-soft thank you very much.
Just a single #True makes all the things.
Yeah, computers is in fact all about true or false. :oops:

Thanks, thanks, thanks.
Yeah I know, but keep in mind ... Leonardo da Vinci was also an autodidact.
Post Reply