Таймер в приложении командной строки

Попытка создать простое приложение командной строки в Haxe с тикающим таймером, но, похоже, это не сработает; Таймер никогда не начинает «тикать».

package;

import haxe.Timer;

class TimerCallback {
    private static inline var CHAR_SPACE : Int = 32;

    public static function main() : Void {
        var myME = new TimerTicker();
        while (Sys.getChar(false) != CHAR_SPACE) {
            //loop until [space] detected, do nothing here
        }
    }
}

class TimerTicker {
    private var myTimer : Timer = null;

    public function new() {
        myTimer = new Timer(20);
        myTimer.run = timer_OnTick;
    }

    private function timer_OnTick() : Void {
        Sys.println ("foobar");
    }
/* destructor?! */
}


А это команда сборки:

>haxe.exe -lib nme -main TimerCallback -cpp .\bin

Если я не добавляю -lib nme, код не компилируется (на основе документации API это нормально, так как таймер не поддерживается для cpp, поэтому доступны только статические функции)

Если я добавляя это, однако, код компилируется, поскольку nme поддерживает таймеры cpp, и создается exe (выигрыш), но timer_OnTick() никогда не вызывается. Итак, exe запускается, ничего не происходит, одно нажатие SPACE и app. выходит.

Дополнительная информация:
- Импортированный файл Timer.hx таков: haxe\lib\nme\5,1,8\haxe. И если я прав, все должно быть в порядке и работать.
— Использование haxe 3.1.3, nme 5.1.8, hxcpp 3.1.39 (и haxelib 3.1.0-rc.4, если имеет значение)

Любая помощь будет высоко оценена.


person Community    schedule 03.09.2014    source источник


Ответы (1)


Хорошо, я получил помощь от сообщества Haxe (список рассылки). Вот решения, если они кому-то понадобятся:

ПСЕВДОКОД (не проверено)

class RunLoop {
   static var queue = new Deque<Void->Void>();
   static var keepAlives:Int; = 1;

static public function release() enque(function () keepAlives--);

static public function retain() enque(function () keepAlives++);

static public function enque(task:Void->Void) queue.add(task);

static function main() { enque(entryPoint); release(); } static function entryPoint() { //code goes here } static function run() while (keepAlives:Int > 0) queue.pop()(); }

//Now you can go an implement a timer like so:

class Timer { var active:Bool = true; public function new(msecs:Int) { RunLoop.retain(); Thread.create(function () while(active) { Sys.sleep(msecs / 1000); if (active) RunLoop.enque(this.run); }); } public dynamic function run() {} public function stop() { active = false; RunLoop.release(); } }

//And a helper for blocking code:

class Task { var task:Void->T; var onDone:T->Void; public function new(task:Void->T, onDone:T->Void) { RunLoop.retain(); Thread.create(function () { var result = task(); RunLoop.enque(onDone.bind(result)); }); } }

//So then the code you want would look roughly like this:

static function entryPoint() { var timer = new Timer(); timer.run = function () trace('foobar'); function waitForSpace() { while (Sys.getChar(false) != CHAR_SPACE) { //loop until [space] detected, do nothing here } return true; } new Task( waitForSpace, function (_) timer.stop() //stop the timer so that the run loop can exit ); }

(solution provided by back2dos)

/*
1. Neko : works
2. C++: works, However, incrementing count in the if statement instead ( if( count++ == 0 ) { ... ) fails to increment count!  Fixed on Git?
3. Flash : works
4. Java : fails using Haxe 3.1.3
*/

### build.hxml ###

-main Main -swf main.swf -swf-version 12

--next

-main Main -neko main.n

--next

-main Main -cpp cpp -cmd cp cpp/Main ./main

--next

-main Main -java java -cmd cp java/Main.jar ./main-jar

### Main.hx ###

class Main { public static function main() { #if sys var count = 0; while( true ) { if( count == 0 ) { Timer.delay(function() trace("doThing1"), 3000); Timer.delay(function() trace("doThing2"), 1000); count++; } } #else Timer.delay(function() trace("doThing1"), 3000); Timer.delay(function() trace("doThing2"), 1000); #end } }

### Timer.hx ###

#if neko import neko.vm.Deque; import neko.vm.Thread; import neko.vm.Mutex; import neko.vm.Lock; #elseif cpp import cpp.vm.Deque; import cpp.vm.Thread; import cpp.vm.Mutex; import cpp.vm.Lock; #elseif java import java.vm.Deque; import java.vm.Thread; import java.vm.Mutex; import java.vm.Lock; #end

class Timer { #if sys static var timerThread : TimerThread; #else static var timers : Array; #end

static function __init__() {
    #if sys
    timerThread = new TimerThread();
    #else
    timers = [];
    #end
}

public static function stop() {
    #if sys
    timerThread.quit();
    #else
    for( t in timers )
        t.stop();
    #end
}

public static function delay( func : Void -> Void, delayMillis : Int ) {
    #if sys
    timerThread.addTimer(delayMillis/1000, func);
    #else
    timers.push( haxe.Timer.delay(func, delayMillis) );
    #end
}

} #if sys typedef TTimerData = { time : Float, func : Void -> Void
}

класс TimerThread { var mutex : Mutex; var queueLock : Блокировка; var очередь : Массив; var работает: Bool; общественная функция new() { очередь = []; queueLock = новая блокировка(); мьютекс = новый мьютекс(); работает = правда; Thread.create(основной цикл); } публичная функция addTimer(delaySec: Float, cb: Void -> Void) { mutex.acquire(); var time = haxe.Timer.stamp() + delaySec; переменный индекс = 0; в то время как (индекс ‹ очередь.длина && время >= очередь[индекс].время) индекс++; queue.insert(index, {time: time, func: cb}); мьютекс.релиз(); очередьLock.релиз(); } публичная функция quit( ?cb : Void -> Void ) { var me = this; addTimer( 0, function() { me.running = false; if( cb != null ) cb(); } ); } function mainLoop() { while(running) { var wake : Null = null; var now = haxe.Timer.stamp(); вар готов = новый массив(); mutex.acquire(); while(queue.length > 0) if(queue[0].time ‹= now) ready.push(queue.shift()); еще { пробуждение = очередь [0]. время; перерыв; } mutex.release(); for(d готово) { d.func(); если( !работает ) перерыв; } if( !работает ) break; if( wake == null ) queueLock.wait(); else { var delay = wake - haxe.Timer.stamp(); если (задержка > 0) queueLock.wait (задержка); } } } } #end

(Решение предоставлено Zjnue, модифицированный код Хью)

person Community    schedule 04.09.2014