![]() |
|
||||||||||
|
|||||||
|
|
« Предыдущая тема | Следующая тема » |
| Опции темы | Опции просмотра |
|
![]() |
![]() |
|
|||||
|
Et cetera
Регистрация: Sep 2002
Сообщений: 30,787
|
WindWalker, swf без сорсов ничего такого своим внешним видом не рассказывает. Если вы реализовали несколько конвееров (которые имеют псевдо одно и то же время старта), то это не многопоточность.
Последний раз редактировалось etc; 08.04.2008 в 20:10. |
|
|||||
|
Цитата:
Цитата:
Последний раз редактировалось miramax; 08.04.2008 в 21:17. |
|
|||||
|
[+1 18.03.08]
Регистрация: Nov 2006
Сообщений: 223
|
Цитата:
А выглядит это просто - достаточно объёмные вычисления (9! = 362880 итераций - для AS2 это достаточно много) не подвешивают плеер, а выполняются постепенно с отображением текущего прогресса. Принцип работы простой: есть метод, который выполняет одну-единственную итерацию. В onEnterFrame засекается время через getTimer(), затем начинает в цикле вызываться метод и после каждого заверешения проверяется, сколько времени прошло. Метод вызывается до тех пор, пока время не превысит 20 миллисекунд. На этом обработка onEnterFrame заканчивается. Продолжение - в следующем кадре. То есть в каждом кадре выполняется столько итераций, сколько успеет выполниться за 20 мс. Основная проблема такого подхода - необходимо вычленить эту самую "одну итерацию". Цитата:
1. А что тогда такое многопоточность? Критерии, пожалуста. 2. Зачем нужна полная и настоящая многопоточность для синхронных вызовов? |
|
|||||
|
Et cetera
Регистрация: Sep 2002
Сообщений: 30,787
|
1. Независимость потоков друг от друга. Цикл на миллион итераций, выполняющийся 100 миллисекунд, никак не влияет на тот же таймер, «тикающий» каждые 10 мс;
2. А как вы сделаете два вызова в один момент времени без многопоточности? |
|
|||||
|
[+1 18.03.08]
Регистрация: Nov 2006
Сообщений: 223
|
Цитата:
Но это условие и не обязательно. В Windows 3.1 форматирование дискетки останавливало все остальные процессы - тут уж ничего не поделаешь, недостатки невытесняющей многозадачности. Но задача-то состоит не в том, чтобы потоки выполнялись плавно. Основная задача - синхронные вызовы. Цитата:
Гарантии, что таймер будет тикать раз в 10мс, а fps будет всегда ровно 30, нам тут совершенно не требуются. |
|
|||||
|
2WindWalker
Суть потока в том, что когда мы пишем код исполняемых им функций мы абстрагируемся от распределения процессорного времени. А здесь вы предлагаете в каждом вызове функции, проверять таймер и писать ещё дофига кода для обрывания "потока" исполнения и запоминания состояния, получается код во время своего исполнения занимается постоянным мониторингом псевдопотока. бууууэээээ.... |
|
|||||
|
[+1 18.03.08]
Регистрация: Nov 2006
Сообщений: 223
|
Нет, я вовсе не предлагаю проверять таймер.
Это просто одна из реализаций - эксперимент на тему "хочу квантование". Но вы правы - действительно для того, чтобы сделать что-то потокообразное - либо для синхронных вызовов, либо (уже другая, но смежная задача) для более плавного выполнения больших вычислений/парсинга xml/обработки битмапов/прочего - необходимо написать оочень много лишнего кода. Более того - код должен иметь особую структуру. Каждая возможная пауза означает создание как минимум одной новой функции. И иногда это может повернуться боком. Вот как раз таки чтобы полностью абстрагироваться, необходимо, чтобы всю рутину взял на себя компилятор. Тогда мы сможем писать чистый и понятный код без всякой мишуры, которую приходиться добавлять сейчас. ------------------- А вообще разговоры про многопоточность меня уже достали. Да, её как таковой нет. Да, её можно эмулировать. Да, это потребует дополнительного кода. Я наконец-то хочу обсудить с кем-нибудь шарящим, какие реальные проблемы могут возникуть при автоматической генерации псевдопотокового кода. Но все почему-то упорно зацикливаются на всякой маловажной ерунде. Последний раз редактировалось WindWalker; 09.04.2008 в 04:14. |
|
|||||
|
Et cetera
Регистрация: Sep 2002
Сообщений: 30,787
|
Куда-нибудь, в светлом будущем, она может быть будет…
|
|
|||||
|
[+1 18.03.08]
Регистрация: Nov 2006
Сообщений: 223
|
Итак, постановка задачи...
Очень часто требуется выполнить несколько действий последовательно. Каждое последущее должно начинать выполняться только после завершения предыдущего. Примеры: 1. Установить сокетное соединение с сервером. Только после того, как соединение установленно, отправить hand-shake запрос. Только после того, как hand-shake подтверждён, начинать дальнейший сетевой обмен. (Вариация: сперва соединиться с login-сервером, отправить имя/пароль, получить id сессии, соединиться с game-сервером, отправить id сессии, получить список комнат, войти в комнату по умолчанию). 2. Загрузить текстуру. Только после того, как текстура загружена, наложить её на объект. 3. Показать пользователю диалоговое окно с кнопкой OK. Только после того, как пользователь нажмёт ОК, выполнять дальнейшие действия (Вариация: окно с Yes/No). Можно привести ещё добрую сотню подобных примеров. В случае, если бы были синхронные вызовы, никаких особых проблем бы не было. Действия выполняются одно за другим, никакой особой параллельности вычислений здесь не требуется. Однако все вызовы в AS только асинхронные. Вызов функции возвращается немедленно, а вот действие можно быть ещё не выполнено. Чтобы узнать, что действие завершено, необходимо подписаться на соответствующее событие. Для каждого события необходимо создать обработчик. Таким образом, вместо одной функции, мы создаём несколько функций, каждая из которых вызывается, когда завершенно предыдущее действие, и инициирует следующее действие. Возникают проблемы: 1. Код разрастается и становится не таким очевидным. Например, другой разработчик, посмотрев на такой код, может не сразу понять, в каком порядке вызываются действия. 2. Вместо локальных переменных приходиться использовать приватные поля для тех данных, которые должны быть общими для разных функций. 3. Некоторые обработчики одноразовые. После срабатывания они должны быть отключены (например, обработчик hand-shake должен сработать один раз. Дальнейший сетевой обмен никак не должен его задействовать). 4. Необходимо заранее задумываться о том, какие действия у нас "мгновенные", а какие "долгоиграющие", чтобы правильно разбивать функции на части. Попробуем всё-таки скомпоновать всё в одну функцию, чтобы частично решить проблемы 1, 2 и 3. Вместо отдельных обработчиков будем использовать вложенные анонимные функции. Для простоты возьмём такой пример: в начальном состоянии приложение ожидает, пока пользователь нажмёт первую кнопку. После нажатия первой кнопки, приложение ожидает, пока пользователь нажмёт вторую кнопку. Очень утрированный пример, но аналогия с предыдущими, думаю, вполне очевидна, зато он более нагляден в визуальном плане. Полный пример кода находиться в аттаче, приведу только самое основное: public function Main()
{
tf.text = "Step 0";
var message1:String = "Step 1";
var message2:String = "Step 2";
btn1.addEventListener(MouseEvent.CLICK, function():void {
tf.text = "Step 1";
btn1.removeEventListener(MouseEvent.CLICK, arguments.callee);
btn2.addEventListener(MouseEvent.CLICK, function():void {
tf.text = "Step 2";
btn2.removeEventListener(MouseEvent.CLICK, arguments.callee);
});
});
}
Достоинства: 1. Действия выполняются строго по порядку. 2. В целом, имеем одну функцию, в которой чётко виден порядок действий. 3. Вложенные функции имеют доступ к локальным переменном основной функции. Недостатки: 1. Очень много "мусорного" кода, который приходиться набирать и который затрудняет чтение. Решение: изменить компилятор таким образом, чтобы весь допольнительный код, необходимый для "прерывания" функции автоматически генерировался компилятором и не присутствовал явно в исходном коде. Чтобы получилось что-то вроде такого: tf.text = "Step 0"; var message1:String = "Step 1"; var message2:String = "Step 2"; bnt1.waitClick() tf.text = "Step 1"; btn2.waitClick(); tf.text = "Step 2"; компилятор сам достраивает весь необходимый код (в частности - цикл для поиска). Мы не заморачиваемся на рутинные действия, код остаётся лаконичным и понятным. Точно так же (теоретически) компилятор может создавать за нас всё необходимое для синхронных вызовов. Но это чисто в теории и на первый взгляд. Интуитивно я чувствую, что здесь скрыто не мало подводных камней. Вот что я вижу на первый взляд: 1. Есть риск, что неособо-локальные переменные (существующие даже после завершения функции, в которой они описаны) могут вызвать утечки памяти. Или наоборот - удаление нужного объекта. 2. Этот подход хорош, когда ожидается только одно событие. Но многие действия могут завершаться с разными событиями (например - если возникает ошибка: не получилось установить соединение, файл не найден, закончился таймаут и т.д.) Поэтому, видимо, придётся сделать более сложное расширение языка. 3. Пока не проверил, как будет вести себя такая система с исключениями. 4. Потребуется разширить существующие классы, чтобы добавить синхронные методы (разумеется, никто не запрещает пользоваться асинхронными). 5. Возможно возникновение проблем, свойственных многопоточным системам. 6. Возможны проблемы с производительностью. И пока не совсем ясно, как осуществлять оптимизацию (например, как определять, когда не следует удалять обработчик, так как он ещё может пригодиться). Вот именно эти проблемы я и хотел бы обсудить. А так же - как покрасивее сделать синтаксис языка. Ну и наконец - что лучше брать за основу: AS3 или HaXe. Последний раз редактировалось WindWalker; 10.04.2008 в 04:08. |
|
|||||
|
Et cetera
Регистрация: Sep 2002
Сообщений: 30,787
|
Сорри, весь пост не читал, вопрос возник сразу: почему сервер шлет какие-то команды клиенту, не дожидаясь реакции пользователя? Результат выполнения чего-либо на клиенте должен быть отправлен на сервер, а тот уже решает, что делать с результатом дальше. Т.е. вот этих вот waitForClick не должно быть в клиенте, клиент логической частью не должен обладать, все решения принимает сервер. Сервер не должен быть тупым и присылать сразу очередью тучу команд логики, он должен их присылать по мере получения результатов выполнения предыдущих.
Команды, приходящие от сервера, должны отправляться в тот контроллер, который их обрабатывает. Контроллер диалогового окна может спокойно ждать реакции пользователя, а контроллер передвижения персонажа, по командам, приходящим от сервера, передвигает этого самого персонажа, совершенно не обращая внимания на то, что открыто диалоговое окно каким-то другим контроллером. На моей практике никаких проблем в реализации подобного плана клиентов на AS3 не было, не говоря уже об отсутствии необходимости реализовывать какой-то движок мультипоточности. Ну вот не вижу я ни одной причины, по которой он должен быть. |
![]() |
![]() |
Часовой пояс GMT +4, время: 03:46. |
|
|
« Предыдущая тема | Следующая тема » |
|
|