<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title><![CDATA[QUIK -> DDE &mdash; LUA Coroutines Tutorial]]></title>
		<link>https://quik2dde.ru/viewtopic.php?id=131</link>
		<atom:link href="https://quik2dde.ru/extern.php?action=feed&amp;tid=131&amp;type=rss" rel="self" type="application/rss+xml" />
		<description><![CDATA[Недавние сообщения в теме «LUA Coroutines Tutorial».]]></description>
		<lastBuildDate>Sun, 11 Oct 2015 13:29:41 +0000</lastBuildDate>
		<generator>PunBB</generator>
		<item>
			<title><![CDATA[Re: LUA Coroutines Tutorial]]></title>
			<link>https://quik2dde.ru/viewtopic.php?pid=1675#p1675</link>
			<description><![CDATA[<div class="quotebox"><cite>Dr. Robotnik пишет:</cite><blockquote><p>kalikazandr, спасибо за совет! С нулевым транс ид при первом коллбеке не сталкивался, но теперь буду иметь это ввиду.</p></blockquote></div><p>Не за что, надо помнить, что поле CLIENTCODE составное и 20-ти символьное, если в сумме clientcode + sep + trans_id больше 20 символов - заявка не пройдет проверку на стороне терминала.</p>]]></description>
			<author><![CDATA[null@example.com (kalikazandr)]]></author>
			<pubDate>Sun, 11 Oct 2015 13:29:41 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?pid=1675#p1675</guid>
		</item>
		<item>
			<title><![CDATA[Re: LUA Coroutines Tutorial]]></title>
			<link>https://quik2dde.ru/viewtopic.php?pid=1674#p1674</link>
			<description><![CDATA[<p>kalikazandr, спасибо за совет! С нулевым транс ид при первом коллбеке не сталкивался, но теперь буду иметь это ввиду.</p>]]></description>
			<author><![CDATA[null@example.com (Dr. Robotnik)]]></author>
			<pubDate>Sat, 10 Oct 2015 10:47:22 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?pid=1674#p1674</guid>
		</item>
		<item>
			<title><![CDATA[Re: LUA Coroutines Tutorial]]></title>
			<link>https://quik2dde.ru/viewtopic.php?pid=1666#p1666</link>
			<description><![CDATA[<div class="quotebox"><cite>Dr. Robotnik пишет:</cite><blockquote><p>Спасибо за комментарий. Как я понял по ссылке упрощённый пример, т.е. вся логика останавливается просто потому, что была поставлена такая задача. Сам пользуюсь костылём для сведения нескольких событий, очерёдность которых может меняться в виде создания элемента массива (в случае отсутствия такового) с ключом соответствующим номеру или транс ид перед попыткой обращения к нему, и обновлением его значений в случае получения обновлённых данных. Просто подумалось, что стоит заменить это вышеописанным подходом, но раз от этого никаких преимуществ, а по быстродействию только проигрыш, оставлю как есть.</p></blockquote></div><p>Конечно, так быстрее.<br />Дополнительно можно сделать проверку в колбеке не активных заявок и по ним не принимать данные, в случае смены сервера и т.п., когда заново приходят все колбеки.<br />Кстати транс ид может быть 0 при первом колбеке, даже если вы ему присваивали не 0, дублируйте в brokerref и считывайте оттуда:<br /> </p><div class="codebox"><pre><code> local id = 0--ручные заявки
  local ref = order.brokerref
  if string.len(ref) &gt; 0 then
     local _, b = string.find(ref, &#039;/+&#039;)
     id = tonumber(string.sub(ref, b + 1)) or 0
  end</code></pre></div><p>sep = &quot;/&quot;--для фортс<br />sep = &quot;//&quot;--ммвб<br />в транспарам:<br />TRANS_ID = trans_id<br />CLIENTCODE = clientcode..sep..trans_id</p>]]></description>
			<author><![CDATA[null@example.com (kalikazandr)]]></author>
			<pubDate>Thu, 08 Oct 2015 18:54:40 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?pid=1666#p1666</guid>
		</item>
		<item>
			<title><![CDATA[Re: LUA Coroutines Tutorial]]></title>
			<link>https://quik2dde.ru/viewtopic.php?pid=1665#p1665</link>
			<description><![CDATA[<div class="quotebox"><cite>kalikazandr пишет:</cite><blockquote><div class="quotebox"><cite>Dr. Robotnik пишет:</cite><blockquote><p>Вот пример использования в торговле: [url]http://smart-lab.ru/blog/239078.php[/url] . Есть ли у Вас замечания к такому использованию coroutines ?</p></blockquote></div><p>Замечаний нет, если человек не знает как получить данные из таблиц (не nil) или не может связать между собой пару тройку потоков без &quot;костылей&quot;, то конечно, такой способ пойдет.<br />Пока его первая корутина получит ответ,&nbsp; у меня робот успеет еще заявок 20 выставить и спокойно обработать все.<br />Цитата:<br /> &quot;...Таким образом вызов placeStopOrder() остановит выполнение основной логики до тех пор, пока стоп-приказ не будет выставлен на 100%. Основной код при этом не страдает из-за лишних проверок, отслеживания событий и т.п...&quot;</p><p>Асинхронность для человека написавшего такое - пустой звук. Бред вообще, стиснув зубы не буду матерится.</p><p>Не убедительно.</p></blockquote></div><p>Спасибо за комментарий. Как я понял по ссылке упрощённый пример, т.е. вся логика останавливается просто потому, что была поставлена такая задача. Сам пользуюсь костылём для сведения нескольких событий, очерёдность которых может меняться в виде создания элемента массива (в случае отсутствия такового) с ключом соответствующим номеру или транс ид перед попыткой обращения к нему, и обновлением его значений в случае получения обновлённых данных. Просто подумалось, что стоит заменить это вышеописанным подходом, но раз от этого никаких преимуществ, а по быстродействию только проигрыш, оставлю как есть.</p>]]></description>
			<author><![CDATA[null@example.com (Dr. Robotnik)]]></author>
			<pubDate>Thu, 08 Oct 2015 17:59:28 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?pid=1665#p1665</guid>
		</item>
		<item>
			<title><![CDATA[Re: LUA Coroutines Tutorial]]></title>
			<link>https://quik2dde.ru/viewtopic.php?pid=1664#p1664</link>
			<description><![CDATA[<div class="quotebox"><cite>Dr. Robotnik пишет:</cite><blockquote><p>Вот пример использования в торговле: [url]http://smart-lab.ru/blog/239078.php[/url] . Есть ли у Вас замечания к такому использованию coroutines ?</p></blockquote></div><p>Замечаний нет, если человек не знает как получить данные из таблиц (не nil) или не может связать между собой пару тройку потоков без &quot;костылей&quot;, то конечно, такой способ пойдет.<br />Пока его первая корутина получит ответ,&nbsp; у меня робот успеет еще заявок 20 выставить и спокойно обработать все.<br />Цитата:<br /> &quot;...Таким образом вызов placeStopOrder() остановит выполнение основной логики до тех пор, пока стоп-приказ не будет выставлен на 100%. Основной код при этом не страдает из-за лишних проверок, отслеживания событий и т.п...&quot;</p><p>Асинхронность для человека написавшего такое - пустой звук. Бред вообще, стиснув зубы не буду матерится.</p><p>Не убедительно.</p>]]></description>
			<author><![CDATA[null@example.com (kalikazandr)]]></author>
			<pubDate>Thu, 08 Oct 2015 17:32:10 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?pid=1664#p1664</guid>
		</item>
		<item>
			<title><![CDATA[Re: LUA Coroutines Tutorial]]></title>
			<link>https://quik2dde.ru/viewtopic.php?pid=1662#p1662</link>
			<description><![CDATA[<div class="quotebox"><cite>kalikazandr пишет:</cite><blockquote><div class="quotebox"><cite>CyberTrader пишет:</cite><blockquote><p>А есть примеры, где бы это использовалось в реальных скриптах под QUIK?</p></blockquote></div><p>нет ни примеров, ни конкретного смысла использования корутин в торговле</p></blockquote></div><p>Вот пример использования в торговле: [url]http://smart-lab.ru/blog/239078.php[/url] . Есть ли у Вас замечания к такому использованию coroutines ?</p>]]></description>
			<author><![CDATA[null@example.com (Dr. Robotnik)]]></author>
			<pubDate>Thu, 08 Oct 2015 13:56:38 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?pid=1662#p1662</guid>
		</item>
		<item>
			<title><![CDATA[Re: LUA Coroutines Tutorial]]></title>
			<link>https://quik2dde.ru/viewtopic.php?pid=1429#p1429</link>
			<description><![CDATA[<p>-</p>]]></description>
			<author><![CDATA[null@example.com (sam063rus)]]></author>
			<pubDate>Tue, 30 Jun 2015 07:47:00 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?pid=1429#p1429</guid>
		</item>
		<item>
			<title><![CDATA[Re: LUA Coroutines Tutorial]]></title>
			<link>https://quik2dde.ru/viewtopic.php?pid=1411#p1411</link>
			<description><![CDATA[<p>-</p>]]></description>
			<author><![CDATA[null@example.com (sam063rus)]]></author>
			<pubDate>Wed, 24 Jun 2015 18:35:09 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?pid=1411#p1411</guid>
		</item>
		<item>
			<title><![CDATA[Re: LUA Coroutines Tutorial]]></title>
			<link>https://quik2dde.ru/viewtopic.php?pid=1410#p1410</link>
			<description><![CDATA[<div class="quotebox"><cite>CyberTrader пишет:</cite><blockquote><p>А есть примеры, где бы это использовалось в реальных скриптах под QUIK?</p></blockquote></div><p>нет ни примеров, ни конкретного смысла использования корутин в торговле</p>]]></description>
			<author><![CDATA[null@example.com (kalikazandr)]]></author>
			<pubDate>Wed, 24 Jun 2015 18:21:12 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?pid=1410#p1410</guid>
		</item>
		<item>
			<title><![CDATA[Re: LUA Coroutines Tutorial]]></title>
			<link>https://quik2dde.ru/viewtopic.php?pid=1409#p1409</link>
			<description><![CDATA[<p>А есть примеры, где бы это использовалось в реальных скриптах под QUIK?</p>]]></description>
			<author><![CDATA[null@example.com (CyberTrader)]]></author>
			<pubDate>Wed, 24 Jun 2015 11:11:58 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?pid=1409#p1409</guid>
		</item>
		<item>
			<title><![CDATA[Re: LUA Coroutines Tutorial]]></title>
			<link>https://quik2dde.ru/viewtopic.php?pid=1408#p1408</link>
			<description><![CDATA[<p>-</p>]]></description>
			<author><![CDATA[null@example.com (sam063rus)]]></author>
			<pubDate>Tue, 23 Jun 2015 14:41:32 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?pid=1408#p1408</guid>
		</item>
		<item>
			<title><![CDATA[Re: LUA Coroutines Tutorial]]></title>
			<link>https://quik2dde.ru/viewtopic.php?pid=1015#p1015</link>
			<description><![CDATA[<p>-</p>]]></description>
			<author><![CDATA[null@example.com (sam063rus)]]></author>
			<pubDate>Sun, 15 Feb 2015 15:18:06 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?pid=1015#p1015</guid>
		</item>
		<item>
			<title><![CDATA[Re: LUA Coroutines Tutorial]]></title>
			<link>https://quik2dde.ru/viewtopic.php?pid=965#p965</link>
			<description><![CDATA[<p>-</p>]]></description>
			<author><![CDATA[null@example.com (sam063rus)]]></author>
			<pubDate>Thu, 05 Feb 2015 01:11:47 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?pid=965#p965</guid>
		</item>
		<item>
			<title><![CDATA[LUA Coroutines Tutorial]]></title>
			<link>https://quik2dde.ru/viewtopic.php?pid=962#p962</link>
			<description><![CDATA[<p><strong>Coroutines Tutorial</strong></p><p><strong>Что есть ко-рутины?</strong></p><p>&nbsp; Ко-рутины или сопрограммы, позволяют нам выполнять несколько задач одновременно. В любом месте и в любое время, мы можем прервать любую функцию (в данном случае, ко-рутину), передать управление другой, а потом вернуться, как ни в чём не бывало в прерванную ко-рутину и продолжать с того места откуда она была прервана. Таким образом, достигается псевдо-многозадачность в рамках LUA-кода одной виртуальной машины.</p><p><strong>Multi-Threading</strong></p><p>&nbsp; Каждая задача выполняется в потоке, который является отдельным от других потоков. Под многопоточностью (Multi-Threading) часто подразумевают одновременное выполнение нескольких задач.</p><p>&nbsp; Есть разные способы, с помощью которых многопоточность может быть реализована. Некоторые системы выделяют определенное количество времени для каждого потока, по прошествии которого передают управление на следующий поток и т.д. Это называется pre-emptive multi-threading (или упреждающая многопоточность). В этом случае каждому из потоков не нужно беспокоиться о том, как много времени он занимает, он больше озабочен своей функцией.</p><p>&nbsp; В других системах, наоборот, поток знает сколько он должен выполняться. Это называется cooperative, или collaborative multi-threading. Здесь все потоки сотрудничают вместе, чтобы разрешить приложению работать должным образом. Это тип многозадачности, который используют сопрограммы Lua.</p><p>&nbsp; Не стоит путать потоки операционной системы и потоки и сопрограммы (ко-рутины) LUA. Сопрограммы - блоки Lua-кода, которые создаются в Lua, и имеют свой собственный поток управления, также как и потоки ОС. Только одна сопрограмма работает в одно и то же время, пока не будет активирована другая подпрограмма, или пока не будет возврата к той подпрограмме, которая её вызвала. Сопрограммы - способ дать возможность псевдо-одновременного исполнения многим другим сопрограммам удобным и естественным образом, однако, это нельзя назвать чистым параллелизмом, и, таким образом, нет никакого выигрыша в производительности при использовании нескольких процессоров. Однако, поскольку сопрограммы переключаются намного быстрее, чем потоки в операционной системе&nbsp; и обычно не требуют сложных, а иногда и дорогих механизмов блокировки, применение сопрограмм, как правило, быстрее, чем эквивалентные программы, использущие полноценные потоки ОС.</p><p><strong>Yielding</strong></p><p>Чтобы осуществить вышесказанное несколько сопрограмм должны прекратить выполнение (после выполнения разумного объема обработки) и передать управление другому потоку. Это называется &quot;yielding&quot;. Сопрограммы явно должны вызвать функцию Lua <strong>coroutine.yield()</strong> , которая похожа на использование return-функции. Однако, в отличии от return - мы можем снова вернуться в прерванную функцию и продолжить с того места где мы остановились. При выходе же по return мы безвозвратно теряем все локальные переменные в той функции из которой вышли.</p><p>Довольно слов, несколько примеров:</p><p>Чтобы создать сопрограмму, мы должны иметь функцию, которая её представляет, например,</p><div class="codebox"><pre><code>&gt; function foo()
&gt;&gt;   print(&quot;foo&quot;, 1)
&gt;&gt;   coroutine.yield()
&gt;&gt;   print(&quot;foo&quot;, 2)
&gt;&gt; end
&gt;</code></pre></div><p>Мы создаем подпрограмму с помощью <strong>coroutine.create(fn)</strong> функции. Мы передаем ей точка входу для потока, который является функцией Lua. Объект, возвращаемый Lua является поток:</p><div class="codebox"><pre><code>&gt; co = coroutine.create(foo) -- create a coroutine with foo as the entry
&gt; = type(co)                 -- display the type of object &quot;co&quot;
thread</code></pre></div><p>Мы можем узнать, в каком состоянии находится поток, используя для этого функцию <strong>coroutine.status()</strong>, например,</p><div class="codebox"><pre><code>&gt; = coroutine.status(co)
suspended</code></pre></div><p>&nbsp; Состояние&nbsp; &quot;<strong>suspended</strong>&quot; означает, что поток жив, и, как и следовало ожидать, ничего не делает. Обратите внимание, что, когда мы создали поток - он НЕ начинает выполнение. Чтобы начать выполнение, мы используем функцию&nbsp; <strong>coroutine.resume()</strong>. После её вызова Lua будет входить в поток и выходить из него по <strong>coroutine.yield()</strong>.</p><div class="codebox"><pre><code>&gt; = coroutine.resume(co)
foo     1
true</code></pre></div><p>&nbsp; функция <strong>coroutine.resume()</strong> возвращает статус ошибки после своего вызова. Выше показано, что мы вошли в функцию foo , а затем вышел без ошибок. Интересный момент: с функцией такой бы номер не прошёл, но с сопрограммами мы сможем возобновить выполнение снова:</p><div class="codebox"><pre><code>&gt; = coroutine.resume(co)
foo     2
true</code></pre></div><p>&nbsp; Видно, что мы выполнили строку после выхода в foo и снова вернулся без ошибок. Тем не менее, если мы посмотрим на status мы можем видеть, что мы покинули функцию foo и сопрограмма прекращается.</p><div class="codebox"><pre><code>&gt; = coroutine.status(co)
dead</code></pre></div><p>Если мы попытаемся провернуть этот номер снова - мы получим сообщение об ошибке:</p><div class="codebox"><pre><code>&gt; = coroutine.resume(co)
false   cannot resume dead coroutine</code></pre></div><p>&nbsp; После того, как сопрограмма закончила свою работу - она не может быть возобновлена.</p><p><strong>Подробнее</strong></p><p>&nbsp; Ниже более сложный пример демонстрирует некоторые важные особенности сопрограмм.</p><div class="codebox"><pre><code>&gt; function odd(x)
&gt;&gt;   print(&#039;A: odd&#039;, x)
&gt;&gt;   coroutine.yield(x)
&gt;&gt;   print(&#039;B: odd&#039;, x)
&gt;&gt; end
&gt;
&gt; function even(x)
&gt;&gt;   print(&#039;C: even&#039;, x)
&gt;&gt;   if x==2 then return x end
&gt;&gt;   print(&#039;D: even &#039;, x)
&gt;&gt; end
&gt;
&gt; co = coroutine.create(
&gt;&gt;   function (x)
&gt;&gt;     for i=1,x do
&gt;&gt;       if i==3 then coroutine.yield(-1) end
&gt;&gt;       if i % 2 == 0 then even(i) else odd(i) end
&gt;&gt;     end
&gt;&gt;   end)
&gt;
&gt; count = 1
&gt; while coroutine.status(co) ~= &#039;dead&#039; do
&gt;&gt;   print(&#039;----&#039;, count) ; count = count+1
&gt;&gt;   errorfree, value = coroutine.resume(co, 5)
&gt;&gt;   print(&#039;E: errorfree, value, status&#039;, errorfree, value, coroutine.status(co))
&gt;&gt; end
----    1
A: odd  1
E: errorfree, value, status     true    1       suspended
----    2
B: odd  1
C: even 2
E: errorfree, value, status     true    -1      suspended
----    3
A: odd  3
E: errorfree, value, status     true    3       suspended
----    4
B: odd  3
C: even 4
D: even         4
A: odd  5
E: errorfree, value, status     true    5       suspended
----    5
B: odd  5
E: errorfree, value, status     true    nil     dead
&gt;</code></pre></div><p>В основном у нас есть цикл for, который вызывает две функции: odd() , когда он сталкивается с нечетным числом, и even() на четных чисел.</p><p>Оригинал на англ.: [url]http://lua-users.org/wiki/CoroutinesTutorial[/url]<br />Перевод: <strong>sam063rus</strong><br /><em><span style="color: #FF5555">за что ему большое спасибо! <strong>admin</strong></span></em></p>]]></description>
			<author><![CDATA[null@example.com (admin)]]></author>
			<pubDate>Wed, 04 Feb 2015 19:30:44 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?pid=962#p962</guid>
		</item>
	</channel>
</rss>
