Jump to content


llHTTPRequest - многопоточность


  • Please log in to reply
6 replies to this topic

#1 djalex777

djalex777

    Новичок на форуме

  • Пользователи
  • PipPip
  • 41 posts
  • Пол:М
  • Основной цех:Скриптеры
  • Второй цех:Строители
  • SL Status: 

Posted 04.01.09 - 13:54

Есть код.
integer main_listen;
key req;
key avatar_id;
default
{
	state_entry()
	{
		main_listen=llListen(2000,"",NULL_KEY,"");
	}

	touch_start(integer total_number)
	{

	}

	listen(integer channel, string name, key id, string message)
	{
		if(channel==2000)
			if(message=="test")
			{
				avatar_id=id;
				req=llHTTPRequest("http://www.ya.ru",[HTTP_METHOD,"GET"],"");
			}
	}

	http_response(key request_id, integer status, list metadata, string body)
	{
		if(request_id==req)
		{
			if(status==200)llInstantMessage(avatar_id,body);
		}
	}
}
Пользователь вводит "/2000test", вызывается функция llHTTPRequest. Далее наступает событие http_response.
Вопрос такой - а если, например, сразу 10 пользователей введут "/2000test". Что произойдет? Сработает llHTTPRequest только для одного пользователя? И вобще как правильно такой нюанс учитывать?

#2 SOb Zemlja

SOb Zemlja

    Активный участник

  • Главные администраторы
  • PipPipPipPip
  • 801 posts
  • Пол:М
  • Откуда:Россия, Москва
  • Основной цех:Строители
  • Второй цех:Скриптеры
  • SL Status: 

Posted 04.01.09 - 17:58

Сработает для всех, запросы запустятся в порядке поступления, а ответ придёт как получится (с учётом таймаута для llHTTPRequest). Для связывания запроса и ответа используется ID запроса, в данном примере это req и request_id (если совпадают, то это ответ на наш запрос).

Вероятно имеет смысл построить очередь запросов в виде списка, добавлять туда запросы пользователей при поступлении и удалять при обработке. В списке может храниться ID аватара, ID запроса (для проверки соответствия ответа) и текст запроса.
  • объявление
    list requests_list = [];
  • добавление
    requests_list += [avatar_id, request_id, text];
  • поиск: llListFindList
  • удаление: llDeleteSubList
Но тут есть высокая вероятность столкнуться с тем, что пока мы очищаем очередь в обработчике http_response, в неё попытаются писать из listen. В этом случае имеет смысл вынести логику «слушалки» и «обработчика» в разные скрипты (в пределах одного прима). Это то, что я называл в другом посте «работой на шине».

Выглядит это так, что мы слушаем чат (llListen) но при приёме сообщения не вызываем llHTTPRequest, а транслируем сообщение на «шину» с помощью llMessageLinked, причём в строку с данными имеет смысл поместить ID аватара, который сделал запрос, как-нибудь так:

llMessageLinked(LINK_THIS, 777, (string) avatar_id + "," + text, NULL_KEY);
В другом скрипте (обработчике) слушаем «шину», в обработчике link_message проверяем, наш ли это канал и вызываем llHTTPRequest, как-нибудь так:

link_message(integer sender_number, integer number, string message, key id)
{
	if(number == 777)
	{
		// превращаем строку в список, разделитель — запятая, см. как объединяли
		list message_as_list = llParseString2List(message, [","], []);
		// рассчёт идёт с 0, на 0-й позиции ID
		string avatar_id = llList2String(message_as_list, 0);
		// на 1-й — текст
		string text = llList2String(message_as_list, 1);
		request_id = llHTTPRequest("http://www.ya.ru",[HTTP_METHOD,"GET"],"")
		requests_list += [avatar_id, request_id, text];
	}
}
Т.к. скрипты у нас работают асинхронно, а обработчик link_message имеет буфер (не помню точно, но 10 сообщений вроде держит), то мы получаем почти совсем многопоточность.

#3 djalex777

djalex777

    Новичок на форуме

  • Пользователи
  • PipPip
  • 41 posts
  • Пол:М
  • Основной цех:Скриптеры
  • Второй цех:Строители
  • SL Status: 

Posted 04.01.09 - 21:14

Спасибо за помощь. Хм.. Я тут задумался, а в пределах одного скрипта события выполняются асинхронно? Или последовательно?
Это я к тому, что может ли возникнуть такая ситуация, что я работаю с переменной в одном событии и в этот момент запускается другое событие и тоже пытается получить доступ к этой переменной?

#4 SOb Zemlja

SOb Zemlja

    Активный участник

  • Главные администраторы
  • PipPipPipPip
  • 801 posts
  • Пол:М
  • Откуда:Россия, Москва
  • Основной цех:Строители
  • Второй цех:Скриптеры
  • SL Status: 

Posted 05.01.09 - 01:02

View Postdjalex777, on 4.1.2009, 21:14, said:

Спасибо за помощь. Хм.. Я тут задумался, а в пределах одного скрипта события выполняются асинхронно? Или последовательно?
Это я к тому, что может ли возникнуть такая ситуация, что я работаю с переменной в одном событии и в этот момент запускается другое событие и тоже пытается получить доступ к этой переменной?
События (Events) собираются в очередь и выполняются в порядке очереди. Т.е. между ними не может быть конфликта.
А ответы типа http_response, dataserver, remote_data обрабатываются асинхронно и являются потенциальным источником проблем.
Вроде так. :(

#5 djalex777

djalex777

    Новичок на форуме

  • Пользователи
  • PipPip
  • 41 posts
  • Пол:М
  • Основной цех:Скриптеры
  • Второй цех:Строители
  • SL Status: 

Posted 05.01.09 - 16:42

View PostSOb_Zemlja, on 5.1.2009, 1:02, said:

События (Events) собираются в очередь и выполняются в порядке очереди. Т.е. между ними не может быть конфликта.
А ответы типа http_response, dataserver, remote_data обрабатываются асинхронно и являются потенциальным источником проблем.
Вроде так. :(
Спасибо ещё раз. Но это не совсем так. Разобрался я наконец-то :) Все без исключения события выполняются в порядке очереди (и http_response в том числе и т.д.). Скрипт выполняется в одном потоке THREAD (что-то наподобие языка Visual Basic). Конфликта в обработке переменных быть не может. Может быть ошибка переполнения стека, но она никак не связана с выполнением операций над переменными. По-поводу асинхронности. Асинхронность заключается в том, что вызывающая функция не ждет получения результата, а вызывает событие с результатом своего выполнения. Отдельный поток для этого не создается.

#6 SOb Zemlja

SOb Zemlja

    Активный участник

  • Главные администраторы
  • PipPipPipPip
  • 801 posts
  • Пол:М
  • Откуда:Россия, Москва
  • Основной цех:Строители
  • Второй цех:Скриптеры
  • SL Status: 

Posted 05.01.09 - 17:12

View Postdjalex777, on 5.1.2009, 16:42, said:

Спасибо ещё раз. Но это не совсем так. Разобрался я наконец-то :) Все без исключения события выполняются в порядке очереди (и http_response в том числе и т.д.).
Перечитал документацию. Да, описанно именно так, я ошибался, рассуждая о возможном конфликте при обращении к переменным, потому, что не относил некоторые события к событиям и считал, что они могут обрабатываться между командами.

View Postdjalex777, on 5.1.2009, 16:42, said:


По-поводу асинхронности. Асинхронность заключается в том, что вызывающая функция не ждет получения результата, а вызывает событие с результатом своего выполнения. Отдельный поток для этого не создается.
Вот этого не понял: это теория асинхронности в общем, реализация в LSL или желаемый результат?

#7 djalex777

djalex777

    Новичок на форуме

  • Пользователи
  • PipPip
  • 41 posts
  • Пол:М
  • Основной цех:Скриптеры
  • Второй цех:Строители
  • SL Status: 

Posted 05.01.09 - 23:03

Это и в second life и в любом другом скрипте. Может отличаться только многопоточностью. Все равно огромное спасибо за помощь. В вопросах с sl я новичок. Спасибо за ответы на все мои вопросы.




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users