Как передать параметры в задачу?

Обсуждение программ nnCron и nnCron LITE

Как передать параметры в задачу?

Postby Casufi » Mon, 12 May 2008, 13:41

Подскажите пожалуйста
Есть две задачи

Code: Select all
#( hello
\ ...
Action:
   MSG: "Hello, friend!"
)#

#( task2
\ ...
Action:
    hello RUN
)#

Так вот из task2 в задачу hello нужно передать набор переменных, так, чтобы они были локальными и для задачи task2 и для задачи hello,
Casufi
 
Posts: 23
Joined: Tue, 28 Mar 2006, 09:09

Re: Как передать параметры в задачу?

Postby VoidVolker » Mon, 12 May 2008, 22:19

Code: Select all
#( hello
NoActive
\ Глобальные переменные
VARIABLE global-var1
VARIABLE global-var2

\ Локальные переменные 1
USER-VARIABLE local1-var1
USER-VARIABLE local1-var2
Action:
global-var1 @ local2-var1 !  \ Копируем глобальные переменные в локальные
global-var2 @ local2-var2 !
MSG: "local2-var1= %local2-var1 @% %crlf% local2-var1=%local2-var1 @% "
)#

#( task2
NoActive
\ Локальные переменные 2
USER-VARIABLE local2-var1
USER-VARIABLE local2-var2
Action:
local2-var1 @  global-var1 !  \ Копируем локальные переменные в глобальные
local2-var2 @  global-var2 !
hello RUN
)#
95% вопросов уже обсуждались на форуме или ответы на них есть в мануале.        nnCron 1.93 b15.exe
Как правильно задавать вопросы.
User avatar
VoidVolker
Site Admin
 
Posts: 2898
Joined: Tue, 25 Apr 2006, 17:56

Re: Как передать параметры в задачу?

Postby Ilya » Tue, 13 May 2008, 01:13

Может логичнее так: :wink:
Code: Select all
#( hello
NoActive
\ Локальные переменные 1
USER-VALUE local1-var1
USER-VALUE local1-var2
Action:
 TO local1-var2
 TO local1-var1
MSG: "local1-var1= %local1-var1% %crlf% local1-var2=%local1-var2% "
local1-var1 1+ \ Оставляем на стеке данные для возврата их в задачу 'task2'
local1-var2 1+ \ Для примера прибавляем по единице!
)#

#( task2
NoActive
\ Локальные переменные 2
USER-VALUE local2-var1
USER-VALUE local2-var2
Action:
1 TO local2-var1    \ Устанавливаем значения
2 TO local2-var2
local2-var1   \ Оставляем на стеке данные для задачи 'hello'
local2-var2   \
hello RUN
TO local2-var2  \ Получаем данные из задачи 'hello'
TO local2-var1
MSG: "local2-var1= %local2-var1% %crlf% local2-var2=%local2-var2% "
)#
Ilya
 
Posts: 445
Joined: Mon, 07 Aug 2006, 09:51
Location: Санкт-Петербург

Re: Как передать параметры в задачу?

Postby dothen » Mon, 06 Apr 2015, 07:21

Или так.
Code: Select all
<%
0 VALUE par
VARIABLE SEM1
: RUN-1PAR { p t }    \ Принимаем параметры. (для RUN)
   p TO par \ Копируем параметр в глобальную переменную.
   t RUN
;
: LAUNCH-1PAR { p t } \ Принимаем параметры. (для LAUNCH)
   p TO par \ Копируем параметр в глобальную переменную.
   SEM1 OFF \ Внешняя задача продолжит выполнение после включения семафора.
   t LAUNCH \ В запускаемой задаче после копирования глоб. переменной надо включить семафор.
   BEGIN 10 PAUSE SEM1 @ UNTIL \ Ждём включение семафора и выходим из цикла.
;                              \ (без паузы идёт загрузка ЦП)
%>
# Примеры-----
#( task1         \ Можно запускать без параметров.
NoActive
USER-VALUE lpar
Action:
   par TO lpar   \ Копируем глобальную переменную в локальную.
   lpar ASCIIZ> MsgBox
)#
#--------------
#( task2         \ Можно запускать без параметров.
NoActive
USER-VALUE lpar
Action:
   par TO lpar   \ Копируем глобальную переменную в локальную.
   SEM1 ON       \ Включаем семафор.
   lpar N>S MsgBox
)#
#--------------
#( task3         \ Передаём параметры.
NoActive
Action:
   z" Секунд %ss%" TO par task1 RUN   \ Без параметров.
   z" Секунд %ss%" task1 RUN-1PAR     \ С параметрами.
   Hour@ task2 LAUNCH-1PAR
   Year@ TO par task2 LAUNCH \ Задача не "успевает" скопировать глобальную переменную.
   Min@  task2 LAUNCH-1PAR
   Sec@  task2 LAUNCH-1PAR
)#
#--------------
#( task4         \ Передаём параметры в цикле.
NoActive
Action:
5 0 DO
     I task2 LAUNCH-1PAR
    LOOP
)#
dothen
 
Posts: 184
Joined: Mon, 16 Mar 2015, 04:58

Re: Как передать параметры в задачу?

Postby VoidVolker » Mon, 06 Apr 2015, 07:50

Для одного-двух параметров на стеке совсем не нужно создавать локальные переменные.
Code: Select all
: RUN-1PAR   \ ( p t -- )    \ Принимаем параметры. (для RUN)
   SWAP TO par \ Копируем параметр в глобальную переменную.
   RUN
;
: LAUNCH-1PAR   \ ( p t -- ) \ Принимаем параметры. (для LAUNCH)
   SWAP TO par \ Копируем параметр в глобальную переменную.
   SEM1 OFF \ Внешняя задача продолжит выполнение после включения семафора.
   LAUNCH \ В запускаемой задаче после копирования глоб. переменной надо включить семафор.
   BEGIN 10 PAUSE SEM1 @ UNTIL \ Ждём включение семафора и выходим из цикла.
;

Кроме того, любая задача является обычным словом. А значит к ней применимы все те же правила и действия, что к обычным словам. И параметры можно передавать на стеке:
Code: Select all
#( Задача_073906042015
NoActive
SingleInstance
Action:
MsgBox
)#

Далее в консоли или в коде:
Code: Select all
S" test string" Задача_073906042015 RUN

Точно так же можно применять и локальные переменные:
Code: Select all
#( Задача_073906042015
NoActive
SingleInstance
Action: { a b -- }
a b MsgBox
)#

Но в данном случае, задачу не получится запускать автоматически - она будет забирать параметры со стека. А крон об этом знать не знает. Вообще, если надо передать в задачу какие-то параметры - то это значит, что надо сделать рефакторинг и декомпозицию задачи (разбить на более маленькие логические участки кода). Т.е. просто вынести весь код в отдельные слова, а для автоматического запуска сделать задачу с нужными параметрами.
Так что не надо изобретать костыли, если уже есть отлично отлаженный механизм.
95% вопросов уже обсуждались на форуме или ответы на них есть в мануале.        nnCron 1.93 b15.exe
Как правильно задавать вопросы.
User avatar
VoidVolker
Site Admin
 
Posts: 2898
Joined: Tue, 25 Apr 2006, 17:56

Re: Как передать параметры в задачу?

Postby dothen » Tue, 07 Apr 2015, 10:31

VoidVolker wrote:Точно так же можно применять и локальные переменные:
Code: Select all
#( Задача_073906042015
NoActive
SingleInstance
Action: { a b -- }
a b MsgBox
)#

Но в данном случае, задачу не получится запускать автоматически - она будет забирать параметры со стека. А крон об этом знать не знает...

Не знал что так можно, спасибо за подсказку. :? :)

Но и предыдущую задачу не получится запускать автоматически т.е. без параметров.
Code: Select all
#( Задача_073906042015
NoActive
SingleInstance
Action:
MsgBox
)#

Да сама задача не забирает параметры со стека, но забрать их желательно сразу. То есть параметры могут применяться не в начале запуска задачи а в середине или в конце задачи, и при том в не явном виде.

В общем Action: { a b -- } самый тот вариант, но только для RUN
А вот как передать параметры в задачу которая запускается по LAUNCH ?
Есть ли отлаженный механизм и можно ли это сделать без костылей, особенно в цикле?

Так не работает.
Code: Select all
#( task123
NoActive
SingleInstance
Action:
MsgBox
)#

#( task456
NoActive
SingleInstance
Action: { a b -- }
a b MsgBox
)#

#( task911
NoActive
Action:
S" test string" task456 LAUNCH
5 0 DO
     I N>S task123 LAUNCH
    LOOP
)#
dothen
 
Posts: 184
Joined: Mon, 16 Mar 2015, 04:58

Re: Как передать параметры в задачу?

Postby VoidVolker » Tue, 07 Apr 2015, 13:56

Code: Select all
Action:
MsgBox

Code: Select all
Action: { a b -- }
a b MsgBox

Одно и то же.
dothen wrote:Есть ли отлаженный механизм и можно ли это сделать без костылей, особенно в цикле?

Конечно. Например через произвольный буфер памяти (стек/массив/переменные) и свое слово для запуска задачи с установкой флага "задача такая-то, столько-то таких-то параметров" и разбором этого всего в задаче. Но! Как я уже сказал - передача параметров в задачу уже само по себе большой костыль. Достаточно просто сделать декомпозицию задачи и вынести весь код задачи в отдельный лексикон. И сделать отдельное слово для запуска нужных слов с нужными параметрами со стека. А в самой задаче использовать те же слова, но с какими-то данными по умолчанию. Эффективнее сделать два простых механизма, где каждый будет четко выполнять свою функцию, чем сложный мега-комбайн.

А LAUNCH - он просто принудительно инициирует запуск задачи, как если бы сработало условие запуска задачи.
95% вопросов уже обсуждались на форуме или ответы на них есть в мануале.        nnCron 1.93 b15.exe
Как правильно задавать вопросы.
User avatar
VoidVolker
Site Admin
 
Posts: 2898
Joined: Tue, 25 Apr 2006, 17:56

Re: Как передать параметры в задачу?

Postby dothen » Tue, 07 Apr 2015, 16:55

VoidVolker wrote:
Code: Select all
Action:
MsgBox

Action: { a b -- }
a b MsgBox

Одно и то же.

Не совсем.
~nn\lib\locals1.f wrote:{ item1 item2 -- }
Это заставляет СП-Форт автоматически выделять место в стеке возвратов для этих переменных в момент вызова слова и автоматически освобождать место при выходе из него.

Если параметры используются по условию...
Code: Select all
#( task1
NoActive
Action:
FALSE IF MsgBox THEN
2DROP \ надо удалять руками.
)#

#( task2
NoActive
Action: { a b -- } \ место освободится автоматически.
FALSE IF a b MsgBox THEN
)#

#( task3
NoActive
Action:
S" test1 string" task1 RUN
S" test2 string" task2 RUN
)#

Справка wrote:Если же возникает необходимость запустить внешнюю задачу "целиком" (отдельным потоком, асинхронно) - с авторизацией и проверкой условий запуска (за исключением условий времени - Time:, OnceA* и т. д.), то можно воспользоваться словом <task-name> LAUNCH.

VoidVolker wrote: Но! Как я уже сказал - передача параметров в задачу уже само по себе большой костыль. Достаточно просто сделать декомпозицию задачи и вынести весь код задачи в отдельный лексикон. И сделать отдельное слово для запуска нужных слов с нужными параметрами со стека. А в самой задаче использовать те же слова, но с какими-то данными по умолчанию.

Было бы хорошо если бы можно было отдельное слово выполнять отдельным потоком, асинхронно ... :)
dothen
 
Posts: 184
Joined: Mon, 16 Mar 2015, 04:58

Re: Как передать параметры в задачу?

Postby VoidVolker » Tue, 07 Apr 2015, 22:43

dothen wrote:Не совсем.

Cовсем. Результат будет одинаковым. Со стека заберутся два числа (строка, в данном случае) и будет показано сообщение. Подробности внутренней реализации значения не имеют.
Code: Select all
Action:
FALSE IF MsgBox THEN \ ( a u --)
2DROP \ надо удалять руками.

Вот так делать не надо. Если условие будет истинным - произойдет исчерпание стека, т.к. этот вариант не учитывается.

dothen wrote:Было бы хорошо если бы можно было отдельное слово выполнять отдельным потоком, асинхронно ...

Code: Select all
' wordName TASK: TaskName

Code: Select all
:NONAME
    <any code>
; TASK: TaskName

Code: Select all
0 VALUE TaskNameID
TaskName START TO TaskNameID
TaskNameID STOP
95% вопросов уже обсуждались на форуме или ответы на них есть в мануале.        nnCron 1.93 b15.exe
Как правильно задавать вопросы.
User avatar
VoidVolker
Site Admin
 
Posts: 2898
Joined: Tue, 25 Apr 2006, 17:56

Re: Как передать параметры в задачу?

Postby dothen » Wed, 08 Apr 2015, 11:17

VoidVolker wrote:
Code: Select all
Action:
FALSE IF MsgBox THEN \ ( a u --)
2DROP \ надо удалять руками.

Вот так делать не надо. Если условие будет истинным - произойдет исчерпание стека, т.к. этот вариант не учитывается.

Точно, про истину я и забыл, :) правильно будет так:
Code: Select all
Action:
<условие>
IF MsgBox \ ( a u --)
ELSE 2DROP \ надо удалять руками.
THEN

Ну в общем понятно, если нам надо из одной задачи запустить другую задачу или слово в отдельном потоке, то передать им параметры можно только через глобальные переменные/массивы...
dothen
 
Posts: 184
Joined: Mon, 16 Mar 2015, 04:58

Re: Как передать параметры в задачу?

Postby VoidVolker » Wed, 08 Apr 2015, 21:43

Потоку передается один параметр со стека:
Code: Select all
: START ( x task -- tid )
  \ запустить поток task (созданный с помощью TASK:) с параметром x
  \ возвращает tid - хэндл потока, или 0 в случае неудачи

Можно сделать так: кладем на стек число аргументов, далее глобально выделяем кусок памяти, в него копипастим стек по числу параметров и передаем задаче этот адрес. А в задаче из этого адреса выкладываем на стек нужное количество параметров и освобождаем память.
Ну например:
Code: Select all
: >GlobalBuf   \ ( xn...x0 n -- addr )
    CELLS DUP CELL+ GLOBAL-ALLOCATE THROW   \ len addr
    DUP >R
    2DUP + CELL+ SWAP  DO
        I !
    CELL +LOOP
    R>
;

: GlobalBuf>   \ ( addr -- xn...x0 n )
    DUP >R
    CELL+ R@ DUP @ + DO
        I @
    -4 +LOOP
    R@ @ 2 RSHIFT
    R> GLOBAL-FREE THROW
;

Code: Select all
:NONAME
    GlobalBuf> ." Items: " .
    ." Data is: " . . . CR
; TASK: NewTask

10 20 30 3 >GlobalBuf NewTask START DROP CR
95% вопросов уже обсуждались на форуме или ответы на них есть в мануале.        nnCron 1.93 b15.exe
Как правильно задавать вопросы.
User avatar
VoidVolker
Site Admin
 
Posts: 2898
Joined: Tue, 25 Apr 2006, 17:56

Re: Как передать параметры в задачу?

Postby dothen » Fri, 10 Apr 2015, 06:15

Ну вот, теперь всё понятно, спасибо разобрался.
Теперь тут не нужны флаги, семафоры, локальные переменные.

Немного модернизировал ваш пример. :)
Code: Select all
: >GlobalBuf   \ ( xn...x0 n -- addr )
    CELLS DUP CELL+ DUP GLOBAL-ALLOCATE THROW   \ len addr
    DUP >R + R@ DO
        I !
    CELL +LOOP
    R>
;
: GlobalBuf>   \ ( addr -- xn...x0 n )
    DUP 2DUP >R
    @ + DO
        I @
    0 CELL - +LOOP
    CELL /        \ количество параметров.
    R> GLOBAL-FREE THROW
;


Code: Select all
:NONAME
    GlobalBuf> DROP ." Data is: " . . . CR
; TASK: NewTask

30 40 50 3 >GlobalBuf NewTask START DROP CR

:NONAME \ Обрабатываем все параметры в цикле.
    GlobalBuf> 0 DO
    ." Data is: " . CR
               LOOP
; TASK: NewTask2

: zapusk >GlobalBuf NewTask2 START DROP CR ;

10 20 2 zapusk
0 1 zapusk
Last edited by dothen on Fri, 10 Apr 2015, 15:08, edited 1 time in total.
dothen
 
Posts: 184
Joined: Mon, 16 Mar 2015, 04:58

Re: Как передать параметры в задачу?

Postby VoidVolker » Fri, 10 Apr 2015, 09:43

А вот стековые комментарии - штука важная. Их надо всегда писать. Даже если стек не меняется. Поправил пример - теперь возвращается число элементов.
95% вопросов уже обсуждались на форуме или ответы на них есть в мануале.        nnCron 1.93 b15.exe
Как правильно задавать вопросы.
User avatar
VoidVolker
Site Admin
 
Posts: 2898
Joined: Tue, 25 Apr 2006, 17:56

Re: Как передать параметры в задачу?

Postby dothen » Fri, 10 Apr 2015, 15:23

VoidVolker wrote:А вот стековые комментарии - штука важная. Их надо всегда писать. Даже если стек не меняется...

Исправил.

VoidVolker, а может добавить эти слова в "extwords" ? :wink:
dothen
 
Posts: 184
Joined: Mon, 16 Mar 2015, 04:58

Re: Как передать параметры в задачу?

Postby VoidVolker » Fri, 10 Apr 2015, 21:49

А зачем? Я туда добавляю обычно что-то популярное и практичное. А это - штука специфическая. Впрочем, никто не мешает закинуть этот код свой локальный плагин )
95% вопросов уже обсуждались на форуме или ответы на них есть в мануале.        nnCron 1.93 b15.exe
Как правильно задавать вопросы.
User avatar
VoidVolker
Site Admin
 
Posts: 2898
Joined: Tue, 25 Apr 2006, 17:56

Next

Return to nnCron forum (Russian)

Who is online

Users browsing this forum: No registered users and 4 guests