Перейти к содержимому


Фотография

Многопоточность в OpenComputers

Многопоточность OpenComputers

  • Авторизуйтесь для ответа в теме
Сообщений в теме: 44

#1 Оффлайн   Zer0Galaxy

Zer0Galaxy
  • Гуру
  • Сообщений: 1 196
  • Уровень сигнала: 0%
  • В игре: 0 ч. 0 мин.

Награды

5                                 

Отправлено 02 Апрель 2015 - 17:56

*
Популярное сообщение!

Ценою неимоверных усилий удалось портировать уже известную вам библиотеку thread в ОС.

Библиотека доступна для скачивания по команде

 

Установка: pastebin get E0SzJcCx /lib/thread.lua  [код]

 

По сравнению с версией для СС, библиотека имеет еще две функции, вызываемых без параметров:

thread.init() - инициализирует многозадачный режим. Должна вызываться один раз перед вызовом других функций библиотеки.

thread.waitForAll() - ожидает завершения всех дочерних потоков. В отличии от СС-версии, дочерние потоки прерываются при завершении родительского. Поэтому, waitForAll следует вызывать в конце основной программы, чтобы дать возможность дочерним завершиться корректно.

 

Функции create, kill и killAll работают аналогично версии для СС.

thread.create(f , ...) - создает поток, который сразу же начинает выполняться параллельно основному потоку. При желании можно создать серию потоков, вызвав функцию create несколько раз подряд. В качестве параметра f необходимо указать функцию, содержащую тело потока. После  можно указать параметры, передаваемые ей.

Функция create возвращает вновь созданный поток как объект типа нить ("thread"). Значение это может понадобиться если вы захотите прервать принудительно созданный поток.

thread.kill(co) - прерывает выполнение параллельного потока. co - завершаемый поток, значение, полученное при вызове функции create.

thread.killAll() - прекращает выполнение всех параллельных потоков, за исключением основного.

 

Пример работы с библиотекой:

local thread = require("thread")
-- Инициализируем многозадачность
thread.init()
-- Функция, которая выводит строку str несколько раз с интервалом секунда
function foo(str,n)
  for i=1,n do
    print(str)
    os.sleep(1)
  end
end
-- Запускаем два экземпляра функции с разными параметрами
thread.create(foo,"AAA",5)
thread.create(foo,"BBB",7)
-- Ждем завершения
thread.waitForAll()

Результат работы программы

test.png



#2 Оффлайн   Alex

Alex
  • Администраторы
  • Сообщений: 3 510
  • Уровень сигнала: 0%
  • В игре: 0 ч. 0 мин.

Отправлено 02 Апрель 2015 - 22:18

ВOOOOOOOOOOOOOOT!!!! НАКОНЕЦ!!!!! СПАСИБО, ДМИТРИЙ!!!!   ЭТО ЭПИК!!!!

Еще и с параметрами запуск! Могу это только сравнить с полетом Гагарина в космос высадкой американцев на Луну. Дождались. Фуууууух! Это может и маленький шажок для программистов всего человечества , но огромный шаг для работы с модом ОС! Спасибо, Дима, за титаническую работу!

Дима, не знаю, как тебя благодарить даже!



#3 Оффлайн   1Ridav

1Ridav

    Орден К.А.

  • Администраторы
  • Сообщений: 263
  • Уровень сигнала: 0%
  • В игре: 0 ч. 0 мин.

Награды

         2         

Отправлено 02 Апрель 2015 - 22:56

Ценою неимоверных усилий удалось портировать уже известную вам библиотеку thread в ОС.

Библиотека доступна для скачивания по команде

pastebin get E0SzJcCx thread.lua

По сравнению с версией для СС, библиотека имеет еще две функции, вызываемых без параметров:

thread.init() - инициализирует многозадачный режим. Должна вызываться один раз перед вызовом других функций библиотеки.

thread.waitForAll() - ожидает завершения всех дочерних потоков.

Функции create, kill и killAll работают аналогично версии для СС.

 

Пример работы с библиотекой:

local thread = require("thread")
-- Инициализируем многозадачность
thread.init()
-- Функция, которая выводит строку str несколько раз с интервалом секунда
function foo(str,n)
  for i=1,n do
    print(str)
    os.sleep(1)
  end
end
-- Запускаем два экземпляра функции с разными параметрами
thread.create(foo,"AAA",5)
thread.create(foo,"BBB",7)
-- Ждем завершения
thread.waitForAll()

Результат работы программы

attachicon.giftest.png

У меня 2 вопроса:

1 - thread'ы убиваются сами после завершения функции или их надо убивать в ручную?

2 - Можно ли убивать thread'ы вручную не дожидаясь их завершения?



#4 Оффлайн   Zer0Galaxy

Zer0Galaxy
  • Автор темы
  • Гуру
  • Сообщений: 1 196
  • Уровень сигнала: 0%
  • В игре: 0 ч. 0 мин.

Награды

5                                 

Отправлено 02 Апрель 2015 - 23:11

У меня 2 вопроса:
1 - thread'ы убиваются сами после завершения функции или их надо убивать в ручную?
2 - Можно ли убивать thread'ы вручную не дожидаясь их завершения?


1. Насильного убийства не присходит. Когда функция завершается, её поток принимает статус "dead" автоматически, после чего он исключается из списка активных потоков и удаляется сборщиком мусора.
2. Да. Для этого нужно сохранить значение, возвращаемое функцией create, и вызвать kill

#5 Оффлайн   1Ridav

1Ridav

    Орден К.А.

  • Администраторы
  • Сообщений: 263
  • Уровень сигнала: 0%
  • В игре: 0 ч. 0 мин.

Награды

         2         

Отправлено 03 Апрель 2015 - 00:12

Было бы очень хорошо, если бы ты документировал все API в этой теме. Как что называется, что делает и что возвращает. в деталях.

Плюс привел несколько примеров использования

 

Я реально буду её использовать для своей управления с андроида , уже думал, что придется свое писать, но еще не приступил к написанию. Прямо подарок судьбы



#6 Оффлайн   Krutoy

Krutoy
  • Гуру
  • Сообщений: 498
  • Уровень сигнала: 0%
  • В игре: 0 ч. 0 мин.

Награды

                 

Отправлено 03 Апрель 2015 - 07:34

Давным давно пользуюсь либой под СС, чень удобно!



#7 Оффлайн   Zer0Galaxy

Zer0Galaxy
  • Автор темы
  • Гуру
  • Сообщений: 1 196
  • Уровень сигнала: 0%
  • В игре: 0 ч. 0 мин.

Награды

5                                 

Отправлено 03 Апрель 2015 - 09:35

Было бы очень хорошо, если бы ты документировал все API в этой теме. Как что называется, что делает и что возвращает. в деталях.

Плюс привел несколько примеров использования

В первом посте я попытался вкратце рассказать про все функции библиотеки и привел примерчик.

 

Давным давно пользуюсь либой под СС, чень удобно!

Ввиду особенностей программирования событий, либа под ОС несколько отличается, а посему требует дополнительного тестирования.



#8 Оффлайн   NEO

NEO
  • Java
  • Сообщений: 1 669
  • Уровень сигнала: 0%
  • В игре: 0 ч. 0 мин.
  • ГородСолнце

Награды

   2                        

Отправлено 03 Апрель 2015 - 14:17

Документацию пожалуйста.

#9 Оффлайн   Zucker

Zucker
  • Пользователи
  • Сообщений: 48
  • Уровень сигнала: 0%
  • В игре: 0 ч. 0 мин.

Отправлено 17 Сентябрь 2015 - 20:59

В исходном коде я не могу понять, откуда " _timeout " взялось (берется), кто его присваивает или я что-то упустил?



#10 Оффлайн   Zer0Galaxy

Zer0Galaxy
  • Автор темы
  • Гуру
  • Сообщений: 1 196
  • Уровень сигнала: 0%
  • В игре: 0 ч. 0 мин.

Награды

5                                 

Отправлено 17 Сентябрь 2015 - 21:31

Это максимальное время ожидания события. Оно указывается при вызове функций computer.pullSignal, os.sleep или event.pull

#11 Оффлайн   Zucker

Zucker
  • Пользователи
  • Сообщений: 48
  • Уровень сигнала: 0%
  • В игре: 0 ч. 0 мин.

Отправлено 17 Сентябрь 2015 - 21:41

Это максимальное время ожидания события. Оно указывается при вызове функций computer.pullSignal, os.sleep или event.pull

А каким образом оно передает. Как я понял когда "сопрограмма" выполняет os.sleep(), то она каким-то образом переходит в другую программу, но как она передает _timeout ?

 

Имел ввиду, что при вызове computer.pullSignal, os.sleep(), event.pull что происходит дальше? 


Сообщение отредактировал Pavel52: 17 Сентябрь 2015 - 21:45


#12 Оффлайн   Zer0Galaxy

Zer0Galaxy
  • Автор темы
  • Гуру
  • Сообщений: 1 196
  • Уровень сигнала: 0%
  • В игре: 0 ч. 0 мин.

Награды

5                                 

Отправлено 17 Сентябрь 2015 - 21:54

Это вопрос не к библиотеке thread, а к библиотеке coroutin. Когда сопрограмма вызывает os.sleep, фактически вызывается coroutin.yield (см. исходник os). При этом управление передается ядру системы. В качестве параметра передается таймаут. Ядро возвращает управление сопрограмме либо по получению сигнала либо по прошествии таймаута. При использовании thread происходит тоже самое, только роль ядра для дочерних потоков играет основной поток.
  • Zucker и RccHD это нравится

#13 Оффлайн   Zucker

Zucker
  • Пользователи
  • Сообщений: 48
  • Уровень сигнала: 0%
  • В игре: 0 ч. 0 мин.

Отправлено 21 Октябрь 2015 - 21:58

Возникла проблема при попытке сделать поток с «computer.pullSignal()» если не указывать время ожидания, то библиотека выдает ошибку, что я попыталась сравнить string and number. Но можно просто установить таймер на подольше и будет все отлично)


Сообщение отредактировал Pavel52: 21 Октябрь 2015 - 22:09


#14 Оффлайн   Zer0Galaxy

Zer0Galaxy
  • Автор темы
  • Гуру
  • Сообщений: 1 196
  • Уровень сигнала: 0%
  • В игре: 0 ч. 0 мин.

Награды

5                                 

Отправлено 22 Октябрь 2015 - 12:50

Возникла проблема при попытке сделать поток с «computer.pullSignal()» если не указывать время ожидания, то библиотека выдает ошибку, что я попыталась сравнить string and number. Но можно просто установить таймер на подольше и будет все отлично)

Благодарю за багрепорт. Исправлено.

Скачайте либу по той же ссылке.


  • Zucker это нравится

#15 Оффлайн   Zucker

Zucker
  • Пользователи
  • Сообщений: 48
  • Уровень сигнала: 0%
  • В игре: 0 ч. 0 мин.

Отправлено 25 Октябрь 2015 - 19:18

Почему он мертв?)

 

/lib/thread.lua:28: cannot resume dead coroutine

...

 

Какие ошибочные действия могли привести к этому?



#16 Оффлайн   evgkul

evgkul
  • Пользователи
  • Сообщений: 365
  • Уровень сигнала: 0%
  • В игре: 0 ч. 0 мин.

Награды

     

Отправлено 25 Октябрь 2015 - 20:11

Почему он мертв?)
 
/lib/thread.lua:28: cannot resume dead coroutine
...
 
Какие ошибочные действия могли привести к этому?


Походу поток завершится успел, а ты его пытаешься возобновить

#17 Оффлайн   Zucker

Zucker
  • Пользователи
  • Сообщений: 48
  • Уровень сигнала: 0%
  • В игре: 0 ч. 0 мин.

Отправлено 25 Октябрь 2015 - 20:14

Походу поток завершится успел, а ты его пытаешься возобновить

Как это решить?



#18 Оффлайн   Zer0Galaxy

Zer0Galaxy
  • Автор темы
  • Гуру
  • Сообщений: 1 196
  • Уровень сигнала: 0%
  • В игре: 0 ч. 0 мин.

Награды

5                                 

Отправлено 26 Октябрь 2015 - 10:57

Как это решить?

Код в студию


  • Alex это нравится

#19 Оффлайн   Zucker

Zucker
  • Пользователи
  • Сообщений: 48
  • Уровень сигнала: 0%
  • В игре: 0 ч. 0 мин.

Отправлено 26 Октябрь 2015 - 16:26

Код в студию

local thread = require("thread");

thread.init()

local function f1()
  print("hello1");
end;

local function f2()
    thread.create(f2)
    thread.create(f1);
    print("hello2");
end;

thread.create(f2);
thread.waitForAll();

Сообщение отредактировал Pavel52: 26 Октябрь 2015 - 16:42


#20 Оффлайн   Zer0Galaxy

Zer0Galaxy
  • Автор темы
  • Гуру
  • Сообщений: 1 196
  • Уровень сигнала: 0%
  • В игре: 0 ч. 0 мин.

Награды

5                                 

Отправлено 26 Октябрь 2015 - 17:14

local thread = require("thread");

thread.init()

local function f1()
  print("hello1");
end;

local function f2()
    thread.create(f2)
    thread.create(f1);
    print("hello2");
end;

thread.create(f2);
thread.waitForAll();

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

local function f1()
  print("hello1");
end;

local function f2()
    f2()
    f1();
    print("hello2");
end;

f2();

Только по идее вылететь мы должны были по переполнению памяти.



#21 Оффлайн   Zucker

Zucker
  • Пользователи
  • Сообщений: 48
  • Уровень сигнала: 0%
  • В игре: 0 ч. 0 мин.

Отправлено 26 Октябрь 2015 - 17:34

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

local function f1()
  print("hello1");
end;

local function f2()
    f2()
    f1();
    print("hello2");
end;

f2();

Только по идее вылететь мы должны были по переполнению памяти.

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



#22 Оффлайн   Zer0Galaxy

Zer0Galaxy
  • Автор темы
  • Гуру
  • Сообщений: 1 196
  • Уровень сигнала: 0%
  • В игре: 0 ч. 0 мин.

Награды

5                                 

Отправлено 26 Октябрь 2015 - 17:57

Никогда не используй рекурсию с целью создания бесконечного цикла. Для этого существует while true do


  • qwertyMAN и Saintmare это нравится

#23 Оффлайн   Arseniy10

Arseniy10
  • Пользователи
  • Сообщений: 97
  • Уровень сигнала: 0%
  • В игре: 0 ч. 0 мин.
  • ГородКаруселин

Отправлено 19 Август 2016 - 16:24

А как же быть с функциями, которые возвращают что-нибудь?


  • LuaGamer это нравится

#24 Оффлайн   Zer0Galaxy

Zer0Galaxy
  • Автор темы
  • Гуру
  • Сообщений: 1 196
  • Уровень сигнала: 0%
  • В игре: 0 ч. 0 мин.

Награды

5                                 

Отправлено 19 Август 2016 - 17:04

В данном случае, основное назначение функции - содержать тело потока, а не возвращать результат. Если очень нужно, результат можно вернуть через глобальную переменную.

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



#25 Оффлайн   Arseniy10

Arseniy10
  • Пользователи
  • Сообщений: 97
  • Уровень сигнала: 0%
  • В игре: 0 ч. 0 мин.
  • ГородКаруселин

Отправлено 19 Август 2016 - 17:24

В данном случае, основное назначение функции - содержать тело потока, а не возвращать результат. Если очень нужно, результат можно вернуть через глобальную переменную.
Конечно, можно подправить библиотеку и генерировать событие по завершению потока, а параметром события передавать возвращаемое значение.

Я даже не знаю, как это реализовать. Пример event.pull(), которая приостанавливает цикл(в моем случае).

#26 Оффлайн   Zer0Galaxy

Zer0Galaxy
  • Автор темы
  • Гуру
  • Сообщений: 1 196
  • Уровень сигнала: 0%
  • В игре: 0 ч. 0 мин.

Награды

5                                 

Отправлено 19 Август 2016 - 17:47

Я, похоже, не правильно понял вопрос. О каких функциях идет речь и какие значения они должны возвращать? Если можно, пример кода



#27 Оффлайн   Arseniy10

Arseniy10
  • Пользователи
  • Сообщений: 97
  • Уровень сигнала: 0%
  • В игре: 0 ч. 0 мин.
  • ГородКаруселин

Отправлено 19 Август 2016 - 21:02

Я, похоже, не правильно понял вопрос. О каких функциях идет речь и какие значения они должны возвращать? Если можно, пример кода


Ну вот пример. Мне нужно выводить какое-то значение на экран, которое постоянно изменяется. И параллельно принимать сигнал от event.pull(), чтобы можно было взаимодействовать. Ибо во время вызова этой функции приостанавливается программа.

Сообщение отредактировал Arseniy10: 19 Август 2016 - 21:04


#28 Оффлайн   qwertyMAN

qwertyMAN
  • Пользователи
  • Сообщений: 1 384
  • Уровень сигнала: 0%
  • В игре: 0 ч. 0 мин.
  • ГородCity17

Награды

                             

Отправлено 19 Август 2016 - 21:18

Ну вот пример. Мне нужно выводить какое-то значение на экран, которое постоянно изменяется. И параллельно принимать сигнал от event.pull(), чтобы можно было взаимодействовать. Ибо во время вызова этой функции приостанавливается программа.

Используй event.lister() Он обрабатывает сигналы в режиме ожидания os.sleep(). Таким образом можешь что угодно выводить, но поставить хотя бы os.sleep(0) которого будет достаточно, чтобы обработать эвенты.

 

Например так:

function func()
<код>
end

event.lister("key_down",func) --регистрируем эвент и привязываем события "нажатие клавиши" функцию func()

while true do
print(42) --выводим на экран что хотим
os.sleep(1) --обрабатываем эвенты
end

event.ignore("key_down",func) --убираем эвент

Сообщение отредактировал qwertyMAN: 19 Август 2016 - 21:21


#29 Оффлайн   TraerTaer

TraerTaer
  • Пользователи
  • Сообщений: 94
  • Уровень сигнала: 0%
  • В игре: 0 ч. 0 мин.

Награды

           

Отправлено 19 Август 2016 - 21:27

Можешь в вайле тру ду вызывать функцию.



#30 Оффлайн   Arseniy10

Arseniy10
  • Пользователи
  • Сообщений: 97
  • Уровень сигнала: 0%
  • В игре: 0 ч. 0 мин.
  • ГородКаруселин

Отправлено 19 Август 2016 - 21:47

Используй event.lister() Он обрабатывает сигналы в режиме ожидания os.sleep(). Таким образом можешь что угодно выводить, но поставить хотя бы os.sleep(0) которого будет достаточно, чтобы обработать эвенты.
 
Например так:

function func()
<код>
end

event.lister("key_down",func) --регистрируем эвент и привязываем события "нажатие клавиши" функцию func()

while true do
print(42) --выводим на экран что хотим
os.sleep(1) --обрабатываем эвенты
end

event.ignore("key_down",func) --убираем эвент


Благодарю!





Темы с аналогичным тегами Многопоточность, OpenComputers

Количество пользователей, читающих эту тему: 0

0 пользователей, 0 гостей, 0 анонимных