nemerle: макрос limit_time
От: PhantomIvan  
Дата: 24.09.06 23:09
Оценка:
хотелось мне для синхронного console.readkey() ограничить время его действия
Автор: PhantomIvan
Дата: 23.09.06

чтобы юзер, легший спать, не просыпался каждые 5 минут нажать кнопку
для этого я написал макрос
    public macro limit_time (expression, time, default)
    {
        def invoke =
        <[ {
            mutable result;
            def thread = Thread(() => result = $expression);
            thread.Start();
            if (thread.Join($time))
                result
            else
            {
                thread.Abort();
                //thread.Join();
                $default
            }
        } ]>;
        
        <[ $invoke ]>
    }

на самом деле, для консоли мне там подсказали более правильный вариант
но вдруг кому макрос понадобится
у этого способа есть недостатки: обратите внимание на
                //thread.Join();

у меня с моим вызовом по типу
                def pressed = limit_time (ReadKey(), AutoInterval, ConsoleKeyInfo(Auto, ConsoleKey.A, false, false, false));

плодятся треды в количестве 1 штука на вызов, и я понял почему
thread.Abort() вызывает исключение в треде, и его можно даже обработать
но рантайм пошлет это исключение только после того, как управление вернется из unmanaged-блока, если оно в нем находится
а в console.readkey() по сути вызов к функции winapi, поэтому тред терпеливо ждет нажатия клавиши, и не закрывается даже после аборта
thread.Join, если его раскомментировать, обязательно дождется разрушения потока, но макрос limit_time() (иногда) работать не будет, т.к. когда поток соизволит закрыться — это не определено, и макрос может вместо ограничения времени подвесить программу (что в моем случае и происходило)
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>

30.01.07 18:13: Перенесено модератором из 'Декларативное программирование' — IT
Re: nemerle: макрос limit_time
От: VladD2 Российская Империя www.nemerle.org
Дата: 24.09.06 23:57
Оценка:
Здравствуйте, PhantomIvan, Вы писали:

Не понял, зачем и прием тут макросы?

А что до самой задачи, то я бы просто завел таймер и тупо посылал некую клавиатурную комбинацию по истечении интервала. Или импортировал бы консольное API и использовал функции проверки наличия ввода (думаю, такие есть).
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: nemerle: макрос limit_time
От: PhantomIvan  
Дата: 25.09.06 00:15
Оценка:
VD>Не понял, зачем и прием тут макросы?

ну как причем
тут как раз тот случай, когда функцией, например, не обойтись
если expression по смыслу синхронный, то вызов функции limitTime(expression, ...) сначала передаст управление expression-у, и там застрянет надолго (возможно застрянет)
надо значит, вызвать expression асинхронно, вот я собственно, посмотрел на concurrency.n и сделал макрос

VD>А что до самой задачи, то я бы просто завел таймер и тупо посылал некую клавиатурную комбинацию по истечении интервала. Или


ну так ты просто мои мысли читаешь вот, цитирую себя
Автор: PhantomIvan
Дата: 23.09.06
:

может, какой-то код можно повесить на таймер, чтобы он отправил на консольный input символ?
какой это должен быть код?


VD> импортировал бы консольное API и использовал функции проверки наличия ввода (думаю, такие есть).


но импортировать winapi некрасиво и нудно, тем более, что есть уже в дотнете Console.KeyAvailable, который и проверяет ввод
таким образом, от макроса в моей программе я избавлюсь, но тем не менее, в других случаях он может понадобится
вдруг кому-то покажется полезным, вот я его и опубликовал
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: nemerle: макрос limit_time
От: Кодт Россия  
Дата: 25.09.06 00:49
Оценка:
Здравствуйте, PhantomIvan, Вы писали:

VD>>Не понял, зачем и прием тут макросы?


PI>ну как причем

PI>тут как раз тот случай, когда функцией, например, не обойтись
PI>если expression по смыслу синхронный, то вызов функции limitTime(expression, ...) сначала передаст управление expression-у, и там застрянет надолго (возможно застрянет)
PI>надо значит, вызвать expression асинхронно, вот я собственно, посмотрел на concurrency.n и сделал макрос

Аааа... Тебе хочется писать
//не
key = limit_time_func ( () => console.readkey(), 3000, 'y' );
//а
key = limit_time_macro(       console.readkey(), 3000, 'y' );

Немножко из пушки по воробьям получается... ради такого макрос писать.

Тем более, что (впрочем, тут лучше Влад подскажет и разберётся) твой макрос порождает разные коды invoke на все случаи жизни. Негуманненько (хотя кто вам килобайты считает? )

Кстати, уж на то пошло: можно было сделать отдельно функцию (принимающую одним из аргументов ()->T) и отдельно — макрос-украшение, оборачивающий выражение в функцию.
def limit_time_func(func, timeout, default) =
{
  mutable result;
  def thread = Thread(() => result=func());
  thread.Start();
  if(thread.Join(timeout))
    result
  else
    default
};

def limit_time_macro(expr, timeout, default) = <[ limit_time_macro( () => $expr, timeout, default ) ]>
Перекуём баги на фичи!
Re[4]: nemerle: макрос limit_time
От: PhantomIvan  
Дата: 25.09.06 01:45
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Аааа... Тебе хочется писать

К>
К>//не
К>key = limit_time_func ( () => console.readkey(), 3000, 'y' );
К>//а
К>key = limit_time_macro(       console.readkey(), 3000, 'y' );
К>

К>Немножко из пушки по воробьям получается... ради такого макрос писать.

все, до меня дошло
я ошибался всем спасибо

К>Тем более, что (впрочем, тут лучше Влад подскажет и разберётся) твой макрос порождает разные коды invoke на все случаи жизни. Негуманненько (хотя кто вам килобайты считает? )


вот здесь не понял, можно подробней?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: nemerle: макрос limit_time
От: Кодт Россия  
Дата: 26.09.06 06:37
Оценка:
Здравствуйте, PhantomIvan, Вы писали:

К>>Тем более, что (впрочем, тут лучше Влад подскажет и разберётся) твой макрос порождает разные коды invoke на все случаи жизни. Негуманненько (хотя кто вам килобайты считает? )

PI>вот здесь не понял, можно подробней?

Ну если ты напишешь
def make_foo( expr )
{
  def invoke = <[ ..... $expr ..... ]>;
  <[$invoke]>
}

x = make_foo( 123 );
y = make_foo( 456 );

То получишь
x = {
  def invoke_123 = ..... 123 .....;
  invoke_123;
}
y = {
  def invoke_456 = ..... 456 .....;
  invoke_456;
}


На каждый вызов макроса порождается свой код. Причём код умеренно-громоздкий.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[6]: nemerle: макрос limit_time
От: PhantomIvan  
Дата: 26.09.06 07:54
Оценка:
Здравствуйте, Кодт, Вы писали:

К>На каждый вызов макроса порождается свой код. Причём код умеренно-громоздкий.


а, так в этом же и прелесть макросов
сколько кил (мег) занимает код — это ведь ничто по сравнению, например, с увеличением производительности
(конечно, я не про этот конкретный макрос говорю)
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.