Multi-threading to live preview

I am attempting to use multithreading to accomplish this live preview functionality in my library, but I have only ever done multithreading in C# and I am unsure where to begin. Some people have been posting me libraries on Twitter, none of which I am ideally looking for.

By using the the cpp.vm.Thread class, I need to loop and check the status of the modified timestamp of any live previewing file until it changes. When it changes, it should send a message back to the main thread, where the main thread reads this message and updates the interface with the newly parsed data.

Of the libraries that have been suggested to me are:

  1. tink_runloop
  2. Golems

Golems requires the need to create a separate project, which is not what I’m looking for. It’s also licensed under LGPL which is a death sentence to the license I’m using for my project (MIT). Tink Runloop is licensed under MIT which is nice, but the README reads like documentation for the internal classes and not an actual tutorial on how to use it, which makes it very difficult to read.

It’s taking me a while to understand tink runloop, I may get there in the end but it’s not easy.

Nevertheless, is there any solid solution that would just simply create a background thread that does the task I need it to do, send a message to the main thread that I then read and then update the interface? Perhaps some sample code in Tink Runloop?

I was originally thinking of implementing a non-blocking timer that does the necessary function calls to get the live previewing to work, then realised that OpenFL has it’s own timer system. Unfortunately you still need to call __checkTimers() perhaps every time you can.

I’m not sure what the best solution is.

cpp.vm.Thread and neko.vm.Thread actually do just that.

How would you do it so that you check the message in a non-blocking manner? Can you just do a simple if statement without using while, that’s the one thing I can’t get my head around.

class Task
{

    private var result:Dynamic;
    private var _count:Int;
    private var _maxCount:Int;
    
    public function new(func:Void -> Void)
    {
        callback = func;
    }
    
    dynamic public function callback() {
        
    }
    
    public function startTask(repeat:Int = 0)
    {
        _count = repeat;
        
        if (_count > 0)
            _maxCount = _count;
        
        while (_maxCount > 0 || _maxCount == -1)
        {
            var _backThread:Thread = Thread.create(callback);
            
            if (_maxCount > 0)
                _maxCount--;
        }
    }
    
    public function sendMessage(msg:Dynamic)
    {
        result = msg;
    }
    
}

Obviously the main thread needs to know what the message is, but how would you read it without blocking it? I tried using Thread.readMessage(false) == 'update' but that results in a blank screen I’m assuming because I haven’t given the background thread enough time to execute to send a message to the main thread.

I found this tutorials, mostly code examples, and tried to implement them but found that my Live class is a bit more complicated than I thought it was, and I may need to send a lot of data to and from threads to really get something done.

I tried to implement the example for a “Background Thread” but then I realised that hxWidgets doesn’t like anything that blocks, it just crashes.

Its pretty straight forward, ive added a quick example in the hxWidgets repo that kicks off a thread and the frame intercepts the IDLE event and updates a text field with the number thats incremented by the thread. You could also use a timer of course, and if you are monitoring file changes maybe thats the better way to go, but you can see the idea here: https://github.com/ianharrigan/hxWidgets/commit/b8c994663d7267788094339f11d78360d074f511

Also, the ITC isnt particularly clever in the example (in fact there isnt really any) but it shouldnt crash any gui thread and thats the point. :wink:

PS: i also just added a timer example which is better in some ways as it doesnt stop when the UI is updating. Ie, the IDLE event stops when you scroll something or open a menu. TIMER even doesnt, so depends on what you are after really.

Mmm… For now, I’ve just added a Button that you click on that updates the GUI when you click on it. I’m not hugely concerned about the “immediate effect”, although now that you mention the “timer” I may look into it.

I may opt for completely redesigning the HaxeLive library to make it more macro-based. Generate the Live, SceneGen and Exporter class based on the backend you would use, making it a lot more extensible than what it currently is. I’m not an expert on macros but I may give it a go, regardless.