<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
	<channel>
		<title>Форум QUIK [тема: Функция criticalSection() для выполнения произвольного кода в потокобезопасном режиме]</title>
		<link>http://forum.quik.ru</link>
		<description>Новое в теме Функция criticalSection() для выполнения произвольного кода в потокобезопасном режиме форума  на сайте Форум QUIK [forum.quik.ru]</description>
		<language>ru</language>
		<docs>http://backend.userland.com/rss2</docs>
		<pubDate>Sat, 02 May 2026 16:53:55 +0300</pubDate>
		<item>
			<title>Функция criticalSection() для выполнения произвольного кода в потокобезопасном режиме</title>
			<description><![CDATA[<b><a href="http://forum.quik.ru/messages/forum10/message28196/topic3272/">Функция criticalSection() для выполнения произвольного кода в потокобезопасном режиме</a></b> в форуме <a href="http://forum.quik.ru/forum10/">Программирование на языке Lua</a>. <br />
			В примере, конечно, не 
====code====
<pre>t1.insert(v1)</pre>
=============
 а
====code====
<pre>table.insert(t1, v1)</pre>
=============
Но вы это поняли... <br />
			<i>14.12.2017 09:53:20, kroki.</i>]]></description>
			<link>http://forum.quik.ru/messages/forum10/message28196/topic3272/</link>
			<guid>http://forum.quik.ru/messages/forum10/message28196/topic3272/</guid>
			<pubDate>Thu, 14 Dec 2017 09:53:20 +0300</pubDate>
			<category>Программирование на языке Lua</category>
		</item>
		<item>
			<title>Функция criticalSection() для выполнения произвольного кода в потокобезопасном режиме</title>
			<description><![CDATA[<b><a href="http://forum.quik.ru/messages/forum10/message28194/topic3272/">Функция criticalSection() для выполнения произвольного кода в потокобезопасном режиме</a></b> в форуме <a href="http://forum.quik.ru/forum10/">Программирование на языке Lua</a>. <br />
			Пока в <noindex><a href="https://forum.quik.ru/forum10/topic3270/" target="_blank" rel="nofollow">соседней ветке</a></noindex> пытаюсь выяснить, как использовать <B>table.ssort()</B> по назначению, придумал ей применение во благо: функция <B>criticalSection() </B>ниже выполняет переданную ей функцию, предварительно заблокировав другой поток.<br /><br /><B>Важно:</B> в своей функции, которую вы передаете в <B>criticalSection()</B>, ни в коем случае не вызывайте потокобезопасные функции, а используйте их стандартные версии. &nbsp;Ваша функция может &quot;бросать исключения&quot; - финальный вариант это поддерживает.<br /><br />Сама функция ниже, пример использования:<br />
====code====
<pre>local t1, t2 = {}, {}
local function insert(v1, v2)
&nbsp;&nbsp; if v1 &#62; v2 then error("v1 &#62; v2") end

&nbsp;&nbsp; t1.insert(v1)
&nbsp;&nbsp; t2.insert(v2)

&nbsp;&nbsp; return v1 + v2, v1 - v2
end

-- далее где-то в разных потоках "атомарно" вставляем оба значения
local r1, r2 = criticalSection(insert, a1, a2)
</pre>
=============
Функция (вам нужны первые две строки и финальный (последний) вариант, остальные в целях объяснения):<br />
====code====
<pre>-- В Lua 5.1 нет table.unpack, но есть unpack.
if not table.unpack then table.unpack = unpack end


-- Понятная версия.&nbsp;&nbsp;На входе функция и ее аргументы (ноль или более),
-- переданная функция вызывается со своими аргументами под
-- блокировкой, на выходе все ее возвращаемые значения.
local function criticalSection(func, ...)
&nbsp;&nbsp; -- Запаковываем аргументы для переданной функции в table.
&nbsp;&nbsp; local args = {...}
&nbsp;&nbsp; local res
&nbsp;&nbsp; -- Функция "сравнения" для table.ssort() (передаваемые элементы
&nbsp;&nbsp; -- упорядочиваемого массива игнорируются).
&nbsp;&nbsp; local less = function()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-- Распаковываем аргументы обратно в список, вызываем с ними
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-- переданную функцию, запаковываем результаты в table.
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;res = { func(table.unpack(args)) }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-- Говорим, что первый элемент упорядочиваемого массива меньше
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-- второго, то есть менять элементы местами не нужно.
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return true
&nbsp;&nbsp; end
&nbsp;&nbsp; -- "Упорядочиваем" массив из двух элементов (то есть наша функция
&nbsp;&nbsp; -- "сравнения" вызовется ровно один раз), при этом во время вызова
&nbsp;&nbsp; -- удерживается блокировка.
&nbsp;&nbsp; table.ssort({ 0, 0 }, less)
&nbsp;&nbsp; -- Распаковываем результаты обратно в список и возвращаем его.
&nbsp;&nbsp; return table.unpack(res)
end


-- Слегка оптимизированная версия: массив { 0, 0 } создается только один
-- раз, функции unpack и ssort ищутся в модуле table также только один раз.
local criticalSection = (function()
&nbsp;&nbsp; local unpack, ssort = table.unpack, table.ssort
&nbsp;&nbsp; local array = { 0, 0 }
&nbsp;&nbsp; return function(func, ...)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local args = {...}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local res
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local less = function()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; res = { func(unpack(args)) }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ssort(array, less)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return unpack(res)
&nbsp;&nbsp; end
end)()


-- Финальная версия: если внутри функции, переданной пользователем,
-- возникнет ошибка, то table.ssort() вылетит, не сняв блокировку (по
-- крайней мере так происходит в моей версии 7.5.0.72 - знаю, что
-- старая, но других брокер не дает).&nbsp;&nbsp;Ниже код, решающий проблему -
-- на всякий случай именно его и следует использовать.
local criticalSection = (function()
&nbsp;&nbsp; local unpack, ssort = table.unpack, table.ssort
&nbsp;&nbsp; local array = { 0, 0 }
&nbsp;&nbsp; local function pack(ok, ...) return ok, {...} end
&nbsp;&nbsp; return function(func, ...)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local args = {...}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local ok, res
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local less = function()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ok, res = pack(pcall(func, unpack(args)))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ssort(array, less)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ok then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return unpack(res)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; error(unpack(res), 0)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp; end
end)()
</pre>
============= <br />
			<i>14.12.2017 09:38:20, kroki.</i>]]></description>
			<link>http://forum.quik.ru/messages/forum10/message28194/topic3272/</link>
			<guid>http://forum.quik.ru/messages/forum10/message28194/topic3272/</guid>
			<pubDate>Thu, 14 Dec 2017 09:38:20 +0300</pubDate>
			<category>Программирование на языке Lua</category>
		</item>
	</channel>
</rss>
