maxmods / wx.mod

wxMax - wxWidgets binding for BlitzMax
Other
7 stars 5 forks source link

wxTimer breaks brl.timerDefault #34

Open GWRon opened 5 years ago

GWRon commented 5 years ago

I am not sure what is exactly happening there but:

I have a ng-generated DLL which utilizes brl.TimerDefault (and AddHook EmitEventHook, _myTimerHook). When importing this DLL file into a new project I get the "run" printed which _myTimerHook outputs.

But if the new project utilizes a "wx.wxtimer" to periodically update its gui (independent from the DLL's repeat-every-x-mechanism) then only a single "run" is printed - and _myTimerHook is only called once.

Does this mean that the functionality of the DLL is interfered by it's calling program? I thought it is "separated" ? Means I could never be sure if a 3rd party using the DLL will "bork" the brl.timerDefault by using eg a wxTimer instance.

GWRon commented 5 years ago

portion of the dll:

SuperStrict

Framework brl.standardIO
Import Brl.EventQueue
Import Brl.TimerDefault

Global timer:TTimer = CreateTimer(5) '5 times a second
Function _MyTimerHook:Object(id:Int, data:Object, context:Object)
    If TEvent(data) And TEvent(data).source = timer
        print "dll tick"
    EndIf
    Return data
End Function
AddHook EmitEventHook, _MyTimerHook

For an WX sample use wx.mod/samples/timer.bmx and then load in the DLL there.

woollybah commented 5 years ago

There's nothing obviously wrong anywhere, that I can see. If you use brl.timer and wxTimer in the same code, does it also break? (I can test that later)

GWRon commented 5 years ago

I am not at the computer now. But regardless of "breaking or not when used in the same code/file" it should not happen at all... As the DLL is separate from the .exe

woollybah commented 5 years ago

Maybe.

woollybah commented 5 years ago

In your dll do you have something like a WaitEvent loop?

woollybah commented 5 years ago

I tested in the same app, and it works as expected - because the app is polling in the background.

Will need to try to set up a test with a dll now...

GWRon commented 5 years ago

Hmm... the DLL actually did not use any loop (except when I tested it as ".exe"). I just created a timer and hooked into the event loop when the timer triggers. Dunno why I have no loop in there - maybe because it just "worked" in the initial tests.

I assume a DLL is "killed" once the main app unloads it? So something like

repeat
  WaitEvent()
forever

should work as "mainloop" of the DLL?

GWRon commented 5 years ago

So if a loop was needed ... was the prior "working state" a bug then? The DLL initialized a "brl.timer" and added a hook to listen to incoming events. When the timer was the source of the event the DLL called a custom function (to eg. run something). There was no loop keeping the "dll alive".

Still the output of the DLL's timer-ticks were readable in the application. So the timer kept "ticking" albeit there was - as said - no loop. If a loop was needed than this should not happen. Somehow the "timer" is not collected as long as the DLL is "loaded". Is that correct behaviour?

GWRon commented 5 years ago

To answer my question: If I added a loop then the DLL will never finished loading. So the "main" part of the DLL is executed upon loading of the DLL. This is the reason why I added a timer to tick ;-)

GWRon commented 5 years ago

On my Windows 10 box the timer keeps ticking (did not update to the newest brl.mod yet!). The issue of the DLL not "ticking" when using wxTimer appeared on the Windows 7 box (which I have no access to now - holiday in my federal state today, thanks to Martin Luther).

So in my Windows 10 box the DLL timer happily "ticks" while the wxTimer of the application ticks too (fetching current values of the DLL on each wxtimer-tick while the "brl.timer-tick" in the DLL measures new values). Won't be at work until next monday so I can only try it out in a Win7 VM.

GWRon commented 5 years ago

@ Loop I tried

Function LoopThread:Object(data:Object)
    Print "thread"
    Delay(200)
End Function
Local thread:TThread = CreateThread(LoopThread, "none")

as a loop but after loading the DLL the "DLL using application" EAV'd (did so without the "print" too - in case it cannot print to the stdio). Adding "WaitThread()" or so wont work, as the DLL then never finishes "loading".

woollybah commented 5 years ago

When you say, "as a loop", you mean that the code inside your LoopThread function was a loop?

Also, you'd want to make a Global thread variable rather than Local, because the thread will be GC'd otherwise.

I tested a dll/wxtimer combo on Windows 10, and it seemed to be running as expected. (Well, the first two times I built it, it generated two prints from the dll and stopped, and no timer tick prints. Then I recompiled stuff just to be sure, and now it's working as intended, printing from both "events" as they happen)

I don't quite understand what is generating the Polls for the DLL events to process - other than from the host application. If I had a C program that loaded the DLL and didn't do anything other than wait for a while, would the DLL generate events still?

You have ventured into areas far outside the realms of a typical BlitzMax app. We may need to add a "very advanced topics" section to the documentation...

GWRon commented 5 years ago

Hmm I might have forgotten to have a loop inside of the thread. Nonetheless it got gc'd or so...before it was called once.

@ poll I thought about the same and always assumed a DLL is handled similar to an externally called process - with the extra of being able to call functions from the outside. If that was that way then it would poll on its own (addemitevent?). But hmm hmm... Seems best bet is to use a thread and time stuff in it on its own.

Will try that when back on the computer

GWRon commented 5 years ago
Global timer:TTimer = CreateTimer(4) '4 times a second
Function _MyHook:Object(id:Int, data:Object, context:Object)
    If TEvent(data) And TEvent(data).source = timer
        Print "tick"
    EndIf
    Return data
End Function
AddHook EmitEventHook, _MyHook

Function LoopThread:Object(data:Object)
    Repeat
        Print "thread"
        Delay(500)
        If finishThread Then Exit
    Forever
End Function
Global thread:TThread = CreateThread(LoopThread, "none")
Global finishThread:Int = False

This EAV's after done loading the DLL. Debug is not of help for now - highlights this in my wxapp:

Global app:MyApp = New MyApp
app.Run() '<---
End

I assumed a thread won't need a "poll", it just needs to run ...and run ... and run. and when enough time is gone, it should do something.