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


Фотография

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

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

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

#1 Оффлайн   Zer0Galaxy

Zer0Galaxy

    The Lord of the Pings

  • Пользователи
  • PipPipPipPipPipPipPip
  • 1 062 сообщений

Награды

                             

Отправлено 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

    Орден К.А.

  • Администраторы
  • 2 921 сообщений

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

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

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

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



#3 Оффлайн   1Ridav

1Ridav

    Орден К.А.

  • Администраторы
  • 242 сообщений

Награды

                    

Отправлено 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

    The Lord of the Pings

  • Автор темы
  • Пользователи
  • PipPipPipPipPipPipPip
  • 1 062 сообщений

Награды

                             

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

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


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

#5 Оффлайн   1Ridav

1Ridav

    Орден К.А.

  • Администраторы
  • 242 сообщений

Награды

                    

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

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

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

 

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



#6 Оффлайн   Krutoy

Krutoy

    Свой человек

  • Пользователи
  • PipPipPipPipPipPipPip
  • 493 сообщений

Награды

                 

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

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



#7 Оффлайн   Zer0Galaxy

Zer0Galaxy

    The Lord of the Pings

  • Автор темы
  • Пользователи
  • PipPipPipPipPipPipPip
  • 1 062 сообщений

Награды

                             

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

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

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

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

 

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

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



#8 Оффлайн   NEO

NEO

    Java

  • Пользователи
  • PipPipPipPipPipPipPip
  • 1 473 сообщений
  • ГородСолнце

Награды

                             

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

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

#9 Оффлайн   Zucker

Zucker

    Читатель

  • Пользователи
  • PipPip
  • 48 сообщений

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

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



#10 Оффлайн   Zer0Galaxy

Zer0Galaxy

    The Lord of the Pings

  • Автор темы
  • Пользователи
  • PipPipPipPipPipPipPip
  • 1 062 сообщений

Награды

                             

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

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

#11 Оффлайн   Zucker

Zucker

    Читатель

  • Пользователи
  • PipPip
  • 48 сообщений

Отправлено 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

    The Lord of the Pings

  • Автор темы
  • Пользователи
  • PipPipPipPipPipPipPip
  • 1 062 сообщений

Награды

                             

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

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

#13 Оффлайн   Zucker

Zucker

    Читатель

  • Пользователи
  • PipPip
  • 48 сообщений

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

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


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


#14 Оффлайн   Zer0Galaxy

Zer0Galaxy

    The Lord of the Pings

  • Автор темы
  • Пользователи
  • PipPipPipPipPipPipPip
  • 1 062 сообщений

Награды

                             

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

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

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

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


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

#15 Оффлайн   Zucker

Zucker

    Читатель

  • Пользователи
  • PipPip
  • 48 сообщений

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

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

 

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

...

 

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



#16 Оффлайн   evgkul

evgkul

    Свой человек

  • Пользователи
  • PipPipPipPipPipPipPip
  • 364 сообщений

Награды

     

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

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


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

#17 Оффлайн   Zucker

Zucker

    Читатель

  • Пользователи
  • PipPip
  • 48 сообщений

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

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

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



#18 Оффлайн   Zer0Galaxy

Zer0Galaxy

    The Lord of the Pings

  • Автор темы
  • Пользователи
  • PipPipPipPipPipPipPip
  • 1 062 сообщений

Награды

                             

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

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

Код в студию


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

#19 Оффлайн   Zucker

Zucker

    Читатель

  • Пользователи
  • PipPip
  • 48 сообщений

Отправлено 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

    The Lord of the Pings

  • Автор темы
  • Пользователи
  • PipPipPipPipPipPipPip
  • 1 062 сообщений

Награды

                             

Отправлено 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

    Читатель

  • Пользователи
  • PipPip
  • 48 сообщений

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

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

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

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

f2();

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

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



#22 Оффлайн   Zer0Galaxy

Zer0Galaxy

    The Lord of the Pings

  • Автор темы
  • Пользователи
  • PipPipPipPipPipPipPip
  • 1 062 сообщений

Награды

                             

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

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


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

#23 Оффлайн   Arseniy10

Arseniy10

    Пользователь

  • Пользователи
  • PipPipPip
  • 70 сообщений
  • ГородКаруселин

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

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


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

#24 Оффлайн   Zer0Galaxy

Zer0Galaxy

    The Lord of the Pings

  • Автор темы
  • Пользователи
  • PipPipPipPipPipPipPip
  • 1 062 сообщений

Награды

                             

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

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

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



#25 Оффлайн   Arseniy10

Arseniy10

    Пользователь

  • Пользователи
  • PipPipPip
  • 70 сообщений
  • ГородКаруселин

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

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

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

#26 Оффлайн   Zer0Galaxy

Zer0Galaxy

    The Lord of the Pings

  • Автор темы
  • Пользователи
  • PipPipPipPipPipPipPip
  • 1 062 сообщений

Награды

                             

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

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



#27 Оффлайн   Arseniy10

Arseniy10

    Пользователь

  • Пользователи
  • PipPipPip
  • 70 сообщений
  • ГородКаруселин

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

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


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

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


#28 Оффлайн   qwertyMAN

qwertyMAN

    Свой человек

  • Пользователи
  • PipPipPipPipPipPipPip
  • 1 019 сообщений
  • Город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

    Пользователь

  • Пользователи
  • PipPipPip
  • 94 сообщений

Награды

           

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

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



#30 Оффлайн   Arseniy10

Arseniy10

    Пользователь

  • Пользователи
  • PipPipPip
  • 70 сообщений
  • ГородКаруселин

Отправлено 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 анонимных


Яндекс.Метрика