![]() |
Модераторы: Daevaorn |
![]() ![]() ![]() |
|
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
Всем привет! Код
Работает! Но, есть несколько вопросов, ответы на которые в принципе можно найти, капнув в дебаггере, предварительно вкурив в низкий уровень (в котором я очень слаб)... в общем, кому не лень уделить время, буду непомерно отблагодарен ![]() * Можно ли утверждать, что отмена Sleep в деструкторе класса Threaded не повлечет за собой трудностей? Конкретизирую - после завершения потока, ОС уничтожает все-про-все и может ли в этот "переходный" момент как то пострадать основной поток при условии что он уже завершается или завершился? * Как я понимаю, статическая функция-член класса является ОБРАЗЦОМ потока, который создает ОС при вызове CreateThread? То есть можно утверждать, что N классов = N потоков? * как себя поведет класс если создать его экземпляр через new? Много там кошмаров будет? Небольшое пояснение - зачем мне это? На данный момент есть такая задача: "написать файлер на подобии стека заданий". То есть, некий класс, который предварительно принимает задания на действия и после вызова Start задания в стеке класса выполняются. Например вот так: 1) QueryRead(&UnsignedInt, sizeof(unsigned int)); 2) QueryRead(&AnsiString, &UnsignedInt); 3) QueryStart(&Percent); где прототип QueryRead позволяет использовать в качестве первого аргумента указатель на данное В которое надо прочитать данное из файла, в качестве второго аргумента либо размер читаемого данного, либо указатель на значение размера (который может указывать на ранее прочитанное данное). А так же и QueryRead(???) который может по результату чтения, как то преобразовывать данные и тутже записывать их куда то. И еще-еще QueryPosition(unsigned long long *Pos, bool Direction)... в общем вот такая увлекательная механика ![]() ![]() * Стек заданий - размещает через new структурку в которой описывается задание. Стек является порядком заданий. * Поток, который - "один объект, один поток", являющийся членом-функцией класса. В итоге должен получится вот такой вот объект, которых можно было бы сделать например штук пять в одной функции и пока выполняются потоки, функция оценивала бы процент выполнения заданий для всех ИЗВЕСТНЫХ пяти потоков + возможно выполняла бы какие то дополнительные расчеты, например обращалась бы к БД блин или чонить типо того. (?) В будущем, если все это месиво из кода окажется минимально правильным, я смогу сделать что то вроди ПАЗЛА между объектами класса и что то на подобии пула этих объектов потока, что бы как то более-менее контролировать эту массу зомбо-потоков. Реализация на данный момент не интересует, пока что важны исключительно те моменты которые в списке выше ![]() Заранево благодарствую всем уделившим время! ![]() Это сообщение отредактировал(а) NYX - 13.7.2012, 21:23 --------------------
'long long long' is too long for GC |
|||
|
||||
borisbn |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 4875 Регистрация: 6.2.2010 Где: Ростов-на-Дону Репутация: 22 Всего: 135 |
Sleep там просто не нужен. Есть Же функции WaitFor... т.к. в конструкторе вызывается CreateThread - то, в принципе, можно
изобретаешь велосипед, ИМХО. Я не очень силён в бусте, но там есть такая штука - asio - судя по тому, что я про неё читал, ты пытаешься сделать её жалкое подобие. Надеюсь boostcoder подключится к обсуждению и более внятно и аргументировано расскажет про азио -------------------- Женщины отличаются от программистов тем, что у них чары состоят из стрингов |
||||
|
|||||
Randajad |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 295 Регистрация: 15.3.2012 Репутация: 8 Всего: 8 |
asio::io_service это называется из буста. Занятная штука, плюс, оно само может использовать столько потоков, сколько вы ему дадите. Довольно удобно. Когда-то давно сталкивался с ней для своих нужд, но уже все потерялось и примеров не приведу.
![]() |
|||
|
||||
borisbn |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 4875 Регистрация: 6.2.2010 Где: Ростов-на-Дону Репутация: 22 Всего: 135 |
ага.... я, конечно, его имел в виду, а не весь asio -------------------- Женщины отличаются от программистов тем, что у них чары состоят из стрингов |
|||
|
||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
Эт да, велосипед. Но велосипед изобрести хочется
![]() Это сообщение отредактировал(а) NYX - 14.7.2012, 00:51 --------------------
'long long long' is too long for GC |
|||
|
||||
boostcoder |
|
|||
![]() pattern`щик ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5458 Регистрация: 1.4.2010 Репутация: 49 Всего: 110 |
разумеется =) "ох и не легкая это работа, из болота тащить бегемота" (с) |
|||
|
||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
C WaitForSingleObject должно быть так?
или тот же ВаитФор в if с ожиданием напр. 1 секунды и если что либо кроме нуля, то уже валить поток принудительно перед завершением главного процесса? Опять таки, не планируется прежде временное завершение... оно нужно скорее на случай подвишивания главного потока во время выхода из программы. иного случая просто не планируется. --------------------
'long long long' is too long for GC |
|||
|
||||
boostcoder |
|
|||
![]() pattern`щик ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5458 Регистрация: 1.4.2010 Репутация: 49 Всего: 110 |
||||
|
||||
Dem_max |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1780 Регистрация: 12.4.2007 Репутация: 4 Всего: 39 |
я бы добавил следующие функции
bool StartThread(сюда передаем указатель на функцию которую нужно выполнять в потоке); запускает поток. ExitThread(void); // послать сигнал пользовательской функции на завершение потока. bool Terminate(void); // завершить поток принудительно. bool WaitForExitThread(int WaitTime); // функция ожидания завершения потока, вызывается после ExitThread(); int GetExitCode(void); // Возвращает код завершения функции потока. bool IsStarted(void); // проверяет запущен ли поток -------------------- Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte") |
|||
|
||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
А значение для GetExitcodeThread где хранится? Есть какой либо риск потерять возвращаемое данное? Напр. в случае разрушения потока каким либо нежелательным образом? Ну, что нибудь рядовое... бывает? Пока что проблем вроди бы не наблюдается у меня, вызываю взятие результа сразу после того как ВэитФор укажет что поток иссяк
![]() Это сообщение отредактировал(а) NYX - 15.7.2012, 01:37 --------------------
'long long long' is too long for GC |
|||
|
||||
Dem_max |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1780 Регистрация: 12.4.2007 Репутация: 4 Всего: 39 |
Кстати забыл сказать, крайне не рекомендую создавать поток в конструкторе класса, а то ты можешь в одном классе объявить несколько объектов Threaded, то при создании класса у тебя создадутся несколько нитей(потоков) и будут сразу выполнять действия, хотя эти действия должны допустим выполняться по нажатию кнопки пользователем.
-------------------- Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte") |
|||
|
||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
А если создавать в конструкторе в замороженном состоянии и размораживать поток по вызову Start например? В таком случае, выполнение потока будет более резвым, нежели "пока создастся, пока туда-сюда...". А как бы подготовить поток к запуску... и сам запуск делать только по принуждению? Я принципе на данный момент я так и реализовал. Кстати, столкнулся с некой траблой... не буду погружать в глубины, возник только один вопрос. Деструктор, он же может в своем теле использовать данные-методы-функции своего класса? Просто у меня такая фишка... в деструкторе оттягивается уничтожение объекта само собой до момента пока поток рабочий (жив или заморожен).... но в конструкторе поток заморожен, и если не вызвать Start, прога само собой виснет в ожидании завершения потока. Я в деструкторе повесил Start если поток не запущен (проверяется флаг, состояние которого выставляется в самом потоке) и если флаг false, то он ставится в true вызывается Start и сам поток в момент УСТАНОВКИ флага так же проверяет его состояние и если он ранее установлен в true то поток сразу же завершается. Если false, то ставит true и продолжает выполнение с подвызовом. Это предотвращает выполнение подвызова потока - та самая юзерская функция которая вызывается объектом-потока. В общем механизм вроди бы рабочий, однако Start не срабатывает O_O я вот думаю, может в деструкторе дело? ОллиДбг показывает что поток в момент деструктора еще заморожен и есть.. .не убит. Но пощему то чот не срабатывает.
Это сообщение отредактировал(а) NYX - 15.7.2012, 15:31 --------------------
'long long long' is too long for GC |
|||
|
||||
Dem_max |
|
||||||||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1780 Регистрация: 12.4.2007 Репутация: 4 Всего: 39 |
собственно так и сделано у Borland
все может использовано что объявлено в классе
Для деструктора: Проверяй валиден ли хэндл потока, если да посылай сигнал завершения потока, дожидайся заврешение потока по конкретному таймауту, если таймаут истек делай Terminate потока. Это сообщение отредактировал(а) Dem_max - 15.7.2012, 16:21 -------------------- Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte") |
||||||||
|
|||||||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
Де жути пугают использования TerminateThread, боюсь как бы потом не было таких ошибок... которые непойми откудасыпятся. Начитался ужасов про все виды завершения кроме естественного выхода из потока по завершению. А еще вопрос, вот полчуается как.... если распаралелить и пустить все потоки в разнобой, они ведь будут быстрее выполняться чем если их сонхронизировать? И прирост производительности, навскидку будет невысоким если синхронизировать ВСЕ потоки включая главный?
--------------------
'long long long' is too long for GC |
|||
|
||||
Randajad |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 295 Регистрация: 15.3.2012 Репутация: 8 Всего: 8 |
Зависит от частоты синхронизаций. Если они у вас все делать синхронно будут - прироста нет.
Не вижу проблемы для создания потоков. На их создание уходит не такое уж и большое время. Если использовать std:: или boost::thread, то никаких termitate не нужно. Это сообщение отредактировал(а) Randajad - 15.7.2012, 18:27 |
|||
|
||||
Dem_max |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1780 Регистрация: 12.4.2007 Репутация: 4 Всего: 39 |
Да ну ???? и что же случается с зависшим потоком ???? он так и остается висеть в памяти ??? -------------------- Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte") |
|||
|
||||
Randajad |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 295 Регистрация: 15.3.2012 Репутация: 8 Всего: 8 |
Почему он зависнет? Есть thread::join, которое и нужно юзать.
|
|||
|
||||
Dem_max |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1780 Регистрация: 12.4.2007 Репутация: 4 Всего: 39 |
Ну потому что например в потоке бесконечный цикл запущен.
-------------------- Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte") |
|||
|
||||
Randajad |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 295 Регистрация: 15.3.2012 Репутация: 8 Всего: 8 |
Ну запущен - пусть делает себе бесконечный цикл, раз надо. Что такого?
|
|||
|
||||
Dem_max |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1780 Регистрация: 12.4.2007 Репутация: 4 Всего: 39 |
Ну поток должен быть завершен, если это требуется.
Вопрос как его завершить ??? -------------------- Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte") |
|||
|
||||
borisbn |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 4875 Регистрация: 6.2.2010 Где: Ростов-на-Дону Репутация: 22 Всего: 135 |
вот был (и остаюсь) точно такого же мнения.... но, когда увидел boost::/std:: thread - был немного удивлён. Там как раз наоборот - запускают поток в конструкторе (и мало того - в деструкторе - не ожидают завершения работы потока)... странно... -------------------- Женщины отличаются от программистов тем, что у них чары состоят из стрингов |
|||
|
||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
В будущем конечно я уже буду использовать готовые реализации объектов-потоков. Но пока что надо разобраться в тонкостях этих потоков. В любооом случае, это надо знать
![]() ... Все, разобрался с деструктором. Все арбайтен! Там с помощью флагов теперь поток размораживется и если подвызов потока не произошел, то поток завершается без подвызова. Если поток по каким либо причинам завис, то деструктор не даст удалить объет до того момента пока поток не развиснет. Так что поток вечен в этом плане. Если надо предотвратить работу потока (возможно принудительно) то через Stop в аргументе которого указывает интервал ожидания ![]() Это сообщение отредактировал(а) NYX - 15.7.2012, 20:44 --------------------
'long long long' is too long for GC |
|||
|
||||
NYX |
|
||||||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
Прототип
Реализация Функция _Format это аналог sprintf тока возвращающий string, вместо аргумента указателя результирующей строки str Функция IternalShellError это функция которая выводит ошибку либо в консоль, либо в MessageBox и завершает приложение ExitProccess Оповещение об ошибке на скорую руку ![]()
Добавлено @ 20:58 Там в Pause используется Sleep. Дело неблагодарное, так как заснет все, не только замораживаемый поток ![]() main
Это сообщение отредактировал(а) NYX - 16.7.2012, 01:49 --------------------
'long long long' is too long for GC |
||||||
|
|||||||
Randajad |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 295 Регистрация: 15.3.2012 Репутация: 8 Всего: 8 |
atomic_bool и в бесконечном цикле в потоке ее проверять. Разве не так? Или вы хотите с помощью Termonate его жестоко убить?
![]() |
|||
|
||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
атомарный флаг.... эммм... а куда его пихать то? В перерывах выполнения пользовательской функции-потока? Не, я понял.... но почему атомарный? Кто еще будет читать\писать флаг?
![]() Это сообщение отредактировал(а) NYX - 16.7.2012, 00:12 --------------------
'long long long' is too long for GC |
|||
|
||||
Alca |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3993 Регистрация: 14.6.2006 Репутация: 7 Всего: 50 |
https://bitbucket.org/skynowa/xlib/src/7091...Sync/CxThread.h https://bitbucket.org/skynowa/xlib/src/7091...nc/CxThread.cpp Это сообщение отредактировал(а) Alca - 16.7.2012, 00:17 |
|||
|
||||
Randajad |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 295 Регистрация: 15.3.2012 Репутация: 8 Всего: 8 |
Это был на вопрос участника выше: что делать в бесконечном цикле.
![]() Проверять эту атомарную переменную и завершать выполнение цикла, если она, например, == true. Зачем атомарную? Компилятор может ее выкинуть из цикла, ибо посчитает, что она не изменяется. Хотя. Можно сделать не атомарную, а volatile. |
|||
|
||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
На GCC нет _beginthread :(
Но для общего принципа исходники интересны. Гранд рахмад за писчу для ума! Да и ваще всем спасибо за помосч ![]() КСТАТИ! Об указании на НЕОБХОДИМОСТЬ ПРИСУТСТВИЯ! Надо и это мне тоже учесть... таааак. http://alenacpp.blogspot.com/2006/04/volatile.html Это сообщение отредактировал(а) NYX - 16.7.2012, 01:05 --------------------
'long long long' is too long for GC |
|||
|
||||
Dem_max |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1780 Регистрация: 12.4.2007 Репутация: 4 Всего: 39 |
Бесконечный цикл это к примеру. Ну в коде с большой вероятностью может присутствовать такая строчка WaitForSingleObject(hHandle, INFINITE); Ну и если событие по каким то причинам никогда не наступит, то все поток весит. Никакие флаги не спасут отца русской демократии. -------------------- Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte") |
|||
|
||||
Randajad |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 295 Регистрация: 15.3.2012 Репутация: 8 Всего: 8 |
Говнокодить не надо, чтобы оно по каким-то причинам не наступило.
![]() Добавлено через 25 секунд Это к сабжу уже не относится, кстати. ![]() |
|||
|
||||
Dem_max |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1780 Регистрация: 12.4.2007 Репутация: 4 Всего: 39 |
Ну в сабже есть такой как раз момент.
Если эта функция будет в потоке, который породил еще один поток.
-------------------- Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte") |
|||
|
||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
В реальности врядли будет вообще использоваться эта функция
![]() ![]() ![]() Это сообщение отредактировал(а) NYX - 16.7.2012, 13:24 --------------------
'long long long' is too long for GC |
|||
|
||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
Расковырял инфы про критические секции. Собстно вот статья http://www.rsdn.ru/article/baseserv/critsec.xml
Стало быть: * Критическая секция это объект, размещение которого определяется функциями EnterCriticalSection и LeaveCriticalSection в параметрах которых принимается указатель на объект секции. Далее, перед оперированием какого либо данного, делается ентер, по завершению оперирования лив. Соответственно можно использовать вложенные ентеры и ливы, если например поток может обращаться ЛИБО - ЛИБО соответственно. так же выходит, область критической секции не начнет свое выполнение и не прервется по середине. Весч прикольная. Но почему тогда такие лакомые плюшки мало где используются? Напр. сервера, где почти во всех как в одном юзаются мьютексы или симафоры. В сильно взрослых серверах типо апача (мельком просмотрел) тоже вроди бы мьютексы, в микросервере null httpd... А что стоило бы, например, внутренние данные объекта потока защитить критсекциями... плюс, дать возможность объекту-потоку принимать объект критсекции, или более того... если имеется подвызов, то просто обуславливать его вызовами ентер и лив. Тогда ВСЕ используемое в потоках- потомках коллектора будет (типо)атомарным. А в случае если например используется связка коллекторов... то можно использовать нечто вроди массива (стека?) объектов критических секций. Довести до автоматизма опрос списка секций в выполнении определенных задач (ну типо не все элементы объекта, а зависимые от выполнимой задачи). Ух! Сколько всего придется погрызть и попробовать на зуб. --------------------
'long long long' is too long for GC |
|||
|
||||
Dem_max |
|
||||||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1780 Регистрация: 12.4.2007 Репутация: 4 Всего: 39 |
Типо атомарным не будет никак, атомарнось подразумевает выполнение чего либо за один такт процессора.
Используются
-------------------- Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte") |
||||||
|
|||||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
Ну да но я и написал ТИПО
![]() ![]() ![]() ![]() ![]() --------------------
'long long long' is too long for GC |
|||
|
||||
bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 63 Всего: 196 |
![]() Может все-таки стоит почитать определение атомарности? |
|||
|
||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
Типо конвеерность все такое
![]() Это сообщение отредактировал(а) NYX - 17.7.2012, 15:32 --------------------
'long long long' is too long for GC |
|||
|
||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
Все! Я Запутался.
--------------------
'long long long' is too long for GC |
|||
|
||||
bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 63 Всего: 196 |
||||
|
||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
Да в ней акаянной! Вот, критические секциии ваще вынесли мне мозг. Ступор произошел еще в самом начале, когда была попытка как то изолировать данные класса-потока от множественных обращений к ним из:
1) внутренней реализации потока 2) внешних вызовов других потоков в т.ч. главного потока процесса Путаница началась с вложенностью критических секций, а так же возможность дедлока в случае витиеватых возможностей класса. В какой то момент он может получиться, в какой то - нет. ООООЙ БОЖЕ!!! Это какой то АД! Вот логически потоки понять реально. А вот как сделать наиболее примитивную - простую автомарность. Пусть даже код будет избыточным, но его понимание было бы простым. Я уже подумываю сделать реализацию потоков и атомарности с помощью низкого уровня. Мне кажется что такая реализация даже будет лушче. Например, привязка данного к потоку. В случае если от коллектора ответвлено более одного потока, коллектор не опзволит обратиться к подключенным к нему данным. Это всего то лишь надо сделать подобие встроенных типов данных, а точнее дополнить POD парочкой флагов и полей под идентификатор коллектора. В общем решить на низком уровне будет от части и сложнее и проще... но блин опять же гемор, это все будет делаться ВНЕ реализации какого либо проекта и если надо будет подызменить реализацию, надо будет пересобирать например ту же DLL работающую с потоками и переподключать.... в общем пипец. Может есть какая то стандартная схема гарантирующая атомарность данных? что бы можно было бы буквально просто указывать, -> вот тебе внешние данные товарищь поток, читай там оверхед (или какой нибудь объект рядом с ними) и смотри, не балуй с чтением\записью. Да, кстати, в критических секциях я запутался в силу того, что не понял как они работают в низах. Вот допустим, выделил я внутри реализации потока блок кода и работы с данными. Окей. Второй, дублирующий этот код в своем потоке - поток, не может обратиться до тех пор пока ЭТА СЕКЦИЯ кем -то занята. Окей. с этим все ясно. А если допустим, я хочу изолировать вызовы printf для двух потоков в двух областях кода? Это надо писать и там и там EnterCriticalSection. Окей, а если рядом с вызовом printf используется инициализация какого то обхекта, и делается в одном из двух экземпляре. Но опять же может использоваться другими двумя потоками. Надо делать опять очередную критсекцию? Обобщаться все эти блоки, для выявления общих секций, которые не нарушили бы данные... блин это просто АД! ![]() Это сообщение отредактировал(а) NYX - 19.7.2012, 16:57 --------------------
'long long long' is too long for GC |
|||
|
||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
![]() мои мозги в кофемолке ![]() --------------------
'long long long' is too long for GC |
|||
|
||||
bsa |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 63 Всего: 196 |
думаю, это вообще мало кто представляет. ![]()
просто Microsoft назвала критической секцией то, что обычно называют захватом мьютекса. Так как они мьютекс сделали ядерным. Так вот, забудь про ядерный мьютекс. Речь идет о межпоточных мьютексах (фьютексах). Реализуются они через простейший атомарные операции процессора. При захвате мьютекса происходит изменение целочисленной переменной. При одном значении мьютекс считается успешно захваченным, при других значениях он считается захваченным другим процессом, в итоге текущий поток передает управление ядру. При возврате управления происходит еще одна попытка захвата... Если интересуют детали, то см. http://locklessinc.com/articles/mutex_cv_futex/ |
||||
|
|||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
Стало быть сложность критических секций заключается в том, что нет ЯВНОСТИ указания "кто ваще кого чо?". Фьютекс является "Сходным образом оптимизированы объекты CRITICAL_SECTION в Win32 API, а также FAST_MUTEX в ядре Windows" по словам википедии. Сейчас более менее начал вникать в назначение мутексов и семафоров, благодаря какому то документу из НГУ на тему "Аспекты параллелизма", который описывает аспекты и реализации для Win\Linux после основополагающей теории. Буквально спас меня этот документ. Он был послан богами свыше, однозначно
![]() Я решил поставить для себя такую задачу, которая не относится к реальным требованиям или реальным мирским потребностям. Выучить потоки на примере сервера, где модель сервера примерно такая: 1) поток который обрабатывает входящие данные и формироует очередь сообщений (подразумевается логика писатель-читатель) 2) множество потоков которым отведена ЧАСТЬ очереди (группировка и разнообразие потоков может диктоваться например скоростью соединения) 3) поток который производит рассылку обработанных данных по клиентам. Как можно реализовать такую модель? Какие средства обеспечения атомарности данных необходимы для реализации. Попробую налету сформировать подзадачи. 1) Поток принимающий данные от пользователя, позволяет засыпать\просыпаться потоку 2го пункта. Это важно! На случай если клиентов очень много но все они в разных категориях. Так, получится что для медленных клиентов с нечастыми запросами поток будет засыпать чуть чаще, но приоритет таких потоков (на уровне выполнения ОС) будет немного выше других. 2) потоки обрабатывающие данные, должны учитывать определенные условия. Например, поступившие данные от U1 на загрузку файла. Но, в процессе загрузки файла, U2 изменил пару байт. Варианта два - 1) прекратить закачку, дождаться обновления и самовозобновить закачку ( эгоизм среди потоков! О да, рекомендуемо). 2) Дождаться закачки - обновить данные (не рекомендуемо в силу больших потреблений ресурсов ЦП и трафика, так как более новое данное один шишъ придется закачивать по новой, но юзверь может и не знать о том, что данное было обновлено!!!!! ЭТО ВАЖНО!). 3) Потоки рассылки, являются чем то вроди дублирующего усилителя (аля РЭА). Где например, находящиеся в ОДНОМ ЗАЛЕ ОБМЕНА ФАЙЛАМИ учитываются такие условия описанные в пункте 2. То есть, грубо говоря, сервер и потоки могут быть уверены, что U1 не нарушит данные обрабатываемые в другом ЗАЛЕ для U234-517. Сами по себе потоки, могут пробуждаться в случае если очередь не пустая. Опять же, потоки могут обрабатывать отдельные части очередей. ХОТЯ! Все эти области очередей можно представить в виде множества стеков ![]() ДАДАДА! Что я еще заметил! У пользователя можно установить мин-макс ( 0 < ?) пунктов очереди, и уже ранее сконфигурированный сервер при авторизации пользователя, создал бы болванку пустой очереди! Хотя в представлении очереди как СТЕКА это очень сложно... представить... маллок и реаллок и прочее что ли? В общем это второстепенно уже наверно. Это образно. Но я думаю что выполнив такую задачу, потоки будут для меня семечками. Хочется додуматься самому, но сейчас понимаю, что на это надо время, поэтому взываю о помощи опытных людей ![]() Как вы думаете? Вот навскидку, без кода и примеров, сугубо на пальцах, как такое реализовать используя мьютексы-семафоры-критсекции? Что будет избыточным? Что будет необходимым? ![]() стало быть имеется получается вот что: U1 -\_ QS1 ~ TI -> TC -> TO (thread in -> thread calc -> thread out) U2 -/ U3 - QS2 ~ TI -> TC -> TO U4 -\ U5 - |_ QS3 ~ TI -> TC -> TO U6 -/ То есть в своем начале, каждый юзер имеет 3 потока Вход -> обработка -> выход, и в случае (ухахаха ИНТИМНОЙ) близости юзверей, их потоки сливаются в едином экстазе обрабатывая ВСЕ их запросы по некой событийности. Значит, общими данными могут явиться данные, у которых более 1го владельца. Вроди бы логично получается. Чего стоит указать потоку с каким мьютексом из множества он имеет дело.. допустим так. Далее, отделиться от очереди и перейти в свою... может означать копирование не обработанных данных СТАРОЙ ОЧЕРЕДИ, ровно таким же образом как и слияние очередей... но можно сделать очередь для множества, как массив очередей, где i оперируемая поток очередь на данный момент времени. Очередь является атомарным данным (ну или для корректности, множеством атомарных данных. Хотя первое наверно точнее, так как элементы в целом и есть неделимое для потоков данное). Окей, с этим более менее разобрались. Но как внутри этой всей схемы, идентифицировать юзверей например по категории скорости соединения? Так как -> * Пользователи со скоростью соединения ОТ и ДО принадлежат одной группе, а те что от ДО и ДО-ДО ко второй.... * Те кто в группе с низким пропускным каналом обрабатываются приоритетнее чем те у кого канал быстрее. Если в очереди стоят 3-4 потока на группу быстрых клиентов и появляется медленный, то после НЫНЕШНЕГО клиента сразу идет медленный, после чего обслуживаются те 3-4 быстрых, если более нет медленных. ДА! Только так. Сервер можно будет допустим конфигурировать низший порог скорости + кол-во низших скоростных клиентов, дабы не приводить к обработке ТОЛЬКО низших клиентов. Это уже иная задача и в целом это дело можно контролировать например вручную, админам! Иначе, для чего они тогда нужны админы, как если не для этого ![]() ДАЛЕЕ! Уже вроди бы более менее мне ясно что да как.... но вот вопрос ![]() Это сообщение отредактировал(а) NYX - 20.7.2012, 01:25 --------------------
'long long long' is too long for GC |
|||
|
||||
Dem_max |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1780 Регистрация: 12.4.2007 Репутация: 4 Всего: 39 |
кстати почитай
http://wm-help.net/books-online/book/59464/59464-27.html#h8 http://wm-help.net/books-online/book/59464/59464-28.html#h9 http://wm-help.net/books-online/book/59464/59464-3.html#h10 http://wm-help.net/books-online/book/59464/59464-4.html#h11 -------------------- Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte") |
|||
|
||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
Спасибо! Читаю. Вот только что нарвался на эту серию статей еще http://www.sofmos.com/lyosha/Articles/multithreading1.html
Затарился пищей для ума. Читаю ![]() --------------------
'long long long' is too long for GC |
|||
|
||||
bsa |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 63 Всего: 196 |
NYX, код под Windows:
Семафоры имеет смысл использовать когда у тебя типичная схема из m производителей и n потребителей. Производители что-то делают, добавляют в очередь и сигнализируют семафором. Потребители ждут сигнала, берут из очереди и обрабатывают. Мьютексы нужны тогда, когда несколько потоков что-то делают с одними и теми же данными, при этом как минимум один из них их меняет. В этом случае, каждый поток перед каждым обращением к общим данным должен захватить мьютекс, выполнить операцию и освободить его. Естественно, что для каждого блока данных должен быть свой мьютекс (общий для всех потоков, конечно). |
||||
|
|||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
Ясно. А как быть с приоритетами? Допустим если поток записи более приоритетный, то есть его надо протиснуть в очередь сразу после ВЫПОЛНЯЮЩЕОСЯ не смотря на имеющуюся очередь из читателей? Вот везде описывается что такая возможность допустима... но никак не пойму, как это сделать. Это решается на уровне приоритетов ОС? То есть как вот приоритет для процесса устанавливается....
Это сообщение отредактировал(а) NYX - 20.7.2012, 19:04 --------------------
'long long long' is too long for GC |
|||
|
||||
bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 63 Всего: 196 |
Процессы - это исполняющиеся экземпляры программ. А потоки - это составные части одного процесса. Не путай понятия.
Время блокировки нужно делать минимальным. Т.е. на время выполнения простейших операций добавления/извлечения данных из очереди. Поэтому в большинстве случае проблем не будет. Если же у тебя все так сильно нагружено, то копай в сторону lockless. |
|||
|
||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
Да, на счет процессов и потоков я знаю, процесс это своего рода набор потоков, где есть первичный поток и возможность создания дополнительных. По сути процесс это набор данных (оверхед). На счет нагрузки даже примерно сказать не могу
![]() ![]() ![]() ![]() 1) Удаление старого пункта задачи для пользователя и присабачивание нового 2) Если напор уж очень сильный, то просто напросто игнорировать. Кроме того FILO не будет замедлять работу сервера в случае если в очереди имеется от 2х заданий. Так как непосредственный доступ к отдельным данным он наверно всеж допустим. Если использовать ВСЮ очередь как целое данное, то думаю ваще смысла нет FILO оно или FIFO. А на счет приоритетов потоков... Sleep(0) пока не найдется нужный поток? ![]() Это сообщение отредактировал(а) NYX - 21.7.2012, 02:07 --------------------
'long long long' is too long for GC |
|||
|
||||
bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 63 Всего: 196 |
Есть у меня подозрение, что ты путаешь FIFO и FILO. FILO - это стек (first in last out - первым пришел, последним уйдешь). Т.е. ты читаешь самые свежие данные, а самые старые могут лежать до скончания века. Стек нет смысла использовать в качестве очереди.
|
|||
|
||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
вот в том то и дело, что что это даже не стек, а фиксированная очередь, обслуживаемая несколькими потоками, для каждого отведена определенная часть очереди. Очередь фиксированная, ее размер позволяет определить степень загаженности, и если кол-во запросов от пользователя превышает очередь, следующие запросы игнорируются. На например, пользователь сломал мышку, она лаганула и 50 раз нажала кнопку ОТПРАВИТЬ
![]() ![]() А кто нибудь может что-то сказать про TLS (тот что Thread Local Storage)? Что это такое ваще? ![]() Это сообщение отредактировал(а) NYX - 23.7.2012, 22:07 --------------------
'long long long' is too long for GC |
|||
|
||||
xvr |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 7046 Регистрация: 28.8.2007 Где: Дублин, Ирландия Репутация: 60 Всего: 223 |
Могу сказать - забудьте про них пока ![]() У вас задача (про потоки и обслуживание пользователей) от поста к посту видоизменяется быстрее, чем размножаются кролики ![]() ![]() |
|||
|
||||
bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 63 Всего: 196 |
|
|||
|
||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
вот что я имел ввиду ->
(новый) in -> ||||||||| -> out (старый) Как бы поступает с начала и обслуживается с конца (или наоборот. Смысл один получаетсо ![]() ![]() ![]() Это сообщение отредактировал(а) NYX - 25.7.2012, 01:37 --------------------
'long long long' is too long for GC |
|||
|
||||
volatile |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2107 Регистрация: 7.1.2011 Репутация: 37 Всего: 85 |
||||
|
||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
Блин, ну вот последовательность алгоритмическая:
1) Добавили новый элемент A 2) (возможно параллельно) Извлекли старый элемент Д ![]() ![]() вот допустим, есть у нас цепочка тэ динамических элементов, где 0 элемент имеет указатель на следующий и предыдущий. Новым будет элемент тот, на который указывает element[0].pprev а старым будет element[9].pnext и вот пока один поток цепляет [0].pprev второй поток отцепляет [9].pnext (индексы элементов я поставил для условности чоб яснее было) ![]() ![]() ![]() ![]() ![]() Это сообщение отредактировал(а) NYX - 25.7.2012, 02:14 --------------------
'long long long' is too long for GC |
|||
|
||||
volatile |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2107 Регистрация: 7.1.2011 Репутация: 37 Всего: 85 |
||||
|
||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
Черт побери, я был уверен что это нечто иное. Ну да ладно, главно суть теперь ясна. А что вы можете сказать о такой методе очереди для серверного ПО, в тех условиях где нет выделеного потока для каждого клиента, а клиенты делятся по группам, которые обслуживают потоки и на один поток приходится массив клиентов? Да и ваще, может я как неопытный, не вижу каких то подвохов в таком подходе?
Получается как... * клиент приконнектилсо, ему выделилась очередь обладающая счетчиком контролирующим кол-во элементов очереди * если клиент попадает в некую группу, его очередь располагается в потоке ГРУППЫ * если клиент единственный для своей группы, или является грубо говоря нераспределенным пользователем, его очередь пихается в поток для непонятных клиентов (ну грубо говоря так). Если находится еще один клиент такой же группы, его к нему туда.. к первому АБСТРАКТНОМУ клиенту в поток, и поток уже обслуживает массив из двух очередей. в цикле из двух итераций пробегается по очередям, обрабатывает сначала 1го клиента, размещает в очередь на отдачу результата, потом второго клиента... и так далее. Это не веб сервер это ваще хз чо за сервер... ну будем считать что это пусть будет допустим чат с залами для конференции. Блин наверно такое даже больше подходит. * В контексте одного потока, данные очереди не могут обрабатываться другими, сторонними потоками. Это будет уже нелогично, если человек из конференции А напишит в конференцию Б ![]() ![]() вот собственно я уже и представляю как все это примерно выглядит. Я могу немного не адекватно выражаться, можете меня не понять... просто я не очень силен в терминах и ухахаха не всегда правильно трактую то что имею ввиду, так как всегда тороплюсь ![]() А пугает меня такая вещь как масштабирование такого сервера ![]() есть разве что идея режимности сервера. Как например: * режим 1 - сервер выполняет все три потока для группы * режим 2 - сервер выполняет только прием \ отдачу * режим 3 - сервер выполняет только калькуляцию (сердце формирования очереди отдачи + допустим фильтрация мата в чате) И если надо наростить мощность... сервер 1го режима принимает в качестве определенной команды (может даже по удаленному терминалу) нечто вроди "rembind 192.168.1.2" и это делает следующее: * очередь опустошается * формируется новая очередь уже на новом калькуляторном сервере * элегантно завершаются потоки калькуляции на первом сервере * далее все дело функционирует на двух серверах, где время калькуляции обуславливается скоростью второго физического сервера который в свою очередь так же может давать запросы на сервер с БД Какое ваще мнение на такую модельку? Даже пусть сложно, фиг с ним я не тороплюсь никуда, это просто эксперемент для себя ![]() Это сообщение отредактировал(а) NYX - 25.7.2012, 02:56 --------------------
'long long long' is too long for GC |
|||
|
||||
volatile |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2107 Регистрация: 7.1.2011 Репутация: 37 Всего: 85 |
NYX, ну очень сумбурно...
![]() По возможности переполненя имхо, вообще по-барабану какой тип очереди. (FIFO или FILO) Все зависит от соотношения помещающих и извлекающих потоков. Защиту от переполнения нужно вводить в любом случае. По быстродействию, тоже вобщем-то по барабану. Накладные расходы по организации очереди, (в вашем случае) будут ничтожны по сравнению с обработкой данных. Так что тип очереди и здесь не имеет особого значения. По здравому смыслу, конечно, нужно использовать FIFO. т.е. обслуживание в порядке поступления, как в очереди за сосисками. Вообще, общий совет: думайте больше о логичности, а не о быстродействии. Ясно устроенный механизм, легче будет и оптимизировать. Но это уже потом, если будет на то необходимость. |
|||
|
||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
Ну я тоже думаю что слишком уж заморочился. Просто как то диковато воспринимать факт динамической ячейки для очереди
![]() точнее переодического распределения памяти. А если допустим создать 10 ячеек, и оперировать как то может быть индексом (указателем элемента), может быть было бы быстрее ![]() ![]() ![]() А на счет переполнения, я не ставил акцент на контроль переполнения ![]() ![]() ![]() Это сообщение отредактировал(а) NYX - 25.7.2012, 14:17 --------------------
'long long long' is too long for GC |
|||
|
||||
Alca |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3993 Регистрация: 14.6.2006 Репутация: 7 Всего: 50 |
||||
|
||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
Спасибо. Читаю. Начало угнетающее
![]() --------------------
'long long long' is too long for GC |
|||
|
||||
bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 63 Всего: 196 |
Вот только откуда старый элемент Д взялся? Надо рассматривать с самого начала: 1. очередь пуста 2. в очередь добавлен элемент А 3. в очередь добавлен элемент Б 4. из очереди извлечен элемент А и добавлен В 5. из очереди извлечен элемент Б ... Элемент А встал в очередь первым. И первым же ее покинул. |
|||
|
||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
Да именно так и есть
![]() ![]() --------------------
'long long long' is too long for GC |
|||
|
||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
Ребят, допустимо ли такое использование критической секции?
Не будет ли трудностей если два потока одновременно вызовут одну функцию одного объекта, при условии что внутри функции автоматически используется критическая секция? Это сообщение отредактировал(а) NYX - 29.7.2012, 21:46 --------------------
'long long long' is too long for GC |
|||
|
||||
bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 63 Всего: 196 |
NYX, собственно именно для этого критические секции и существуют.
Рекомендую тебе использовать RAII для организации критических секций:
|
|||
|
||||
SVN74 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 740 Регистрация: 5.5.2008 Где: Комсомольск на Дн епре Репутация: 1 Всего: 18 |
Простите, если я не правильно понял схему желаемого сервера, но я бы сделал так:
Создал класс в котором прикрепил 1 - "map" - для базы клиентов, 2 - сокетный протокол (сервер, клиент), 3 - сохранения баз данных. Затем это все размножил бы класс по количеству групп, - дав каждой группе свой порт ожидания. В итоге получиться независимые группы со своими серверами и базами данных без необходимости синхронизаций... Добавлю: Тоже самое можно создать и на одном ожидающем порту, только потом разбрасывать каждому классу отдельно его клиента, но тут уже надо будет одну синхронизужку делать.. Это сообщение отредактировал(а) SVN74 - 29.7.2012, 22:22 |
|||
|
||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
Можно было бы вообще группы клиентов разбить на процессы отдельные. Но, допустим челу надо скаконуть из одноу группы, чонить написать и смотаться в другую.... группы динамические и основной акцент на скорость их формирования. Можно было бы выделять например 2-4 пустые группы, в случае чего юзвери туда могли бы прошмыгнуть создав новую. Переход в уже готовую группу (где есть участники, не темперную) производился бы просто под средством присваивания пары указателей
![]() А) нераспределенные пользователи (общий чат) Б) группа (конференция) Группа А всего одна и из нее юзвери переводятся в любую из множества групп Б. Сам переход обуславливается присваиванию указателей на ЧАСТЬ очереди, которую надо обработать в потоках группы. То есть переход, есть не что иное как "ткнуть поток носом в миску, откуда лакать.". Если речь идет о новой группе... она как бы и есть но ее как бы и нет. То есть, создание группы условно говоря это когда боле 1го собеседника находятся в общей комнате. Сама общая комната разумеется делается по запросу. Запрос выглядит примерно так "отцепи меня от нераспределенной группы и сделай отдельной группой вон с тем чуваком". Создается новых трипотока куда заведомо посылаются указатели на область очереди 2х собеседников. Очередь есть не что иное как глобальный массив стеков. Он есть до тех пор, пока есть пользователь. То есть основная нагрузка падает только на создание потоков обслуживания: * вход. трафик * калькуляция * выход. трафик Но блин я хз как масштабируемость делать. Как можно с такой схемой распределить нагрузку. Пока что на заметке у меня memory-maped file, но я еще не знаю можно ли использовать удаленно их и вообще выгодно ли это. Если это не выгодно, то кирдык-бабай. Если авалибл, то тогда шаровый мемори-мэпед файл, деление сервера на 2 составляющих 1) обработка i\o очередей (стеков) 2) калькуляция -> 3) база данных (ну это еще хз нужна ли она для чата, но пусть будем считать что нужна для хранения последних нцати сообщений, что бы вновь прибывшие смогли прочитать их при джоинте) каждый из пунктов является отдельным VPS (наверно на физическом уровне). Блин а еще вот я так думаю, сколько еще ждать до момент MinGW в стандарте С++11 ![]() Это сообщение отредактировал(а) NYX - 29.7.2012, 22:38 --------------------
'long long long' is too long for GC |
|||
|
||||
SVN74 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 740 Регистрация: 5.5.2008 Где: Комсомольск на Дн епре Репутация: 1 Всего: 18 |
![]() И все же какова тогда выгода от группирования, если клиенту необходимо давать доступ к другой группе. Может тогда и клиента размножить на несколько групп одновременно? По моему мнению, - группы на то и группы, чтобы не контактировать... Это сообщение отредактировал(а) SVN74 - 29.7.2012, 22:48 |
|||
|
||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
Про RAII - я мальца сократил код. Ваще где то подглядел обертку для критсекций, там в конструкторе делается инициализация, в дуструкторе соответственно... публики лок, трайлок, анлок. В реальном счас исходнике у меня эта обертка трудится. Создается некий объект, пусть это будет отображение чего-то там где то в консольке и к этому объекту имеется доступ с двухнцати потоков. И внутри потока уже нет необходимости делать эти постоянные вызовы. В пространстве объекта уже есть обертка которая используется во всех потенциально-потокововызываемых функциях. Но меня немного смутило (Опять таки я дуб в низкоуровневом, постепенно вникаю по мере возможности, но отдельно изучению отладке время не уделяю) то что функция объекта одна и вызов функции двойной, а вот тело функции уже лок-анлок. (очень коротко сказал). просто в случае критсекций в потоке, получается как, не выполняется тело потока (потоки ведь разные экземпляры функций и тел или один и тот же тел?) и именно тело лочится. А в случае функции объекта, это уже ... одна и та же получается. Я только в этом усомнился. В целом, если я предполагаю что использовать такие возможности допустимо, то наверно я вкурил в эту тему
![]() Добавлено @ 22:49 Клиента размножать?... ну ваще длительность потоков она наверно более высока нежели длительность многоликости клиента. Хотя... Я ваще не хочу создавать много потоков. Блин это отстой. Но я пока не подкован в потоках и не знаю какие сложности в производительности возникнут. Я еще краем уха слышал что потоки можно привязать к N процессору. Так ли это? Реализуемо ли это на WinAPI? Я так и не понял. Буду искать. Если размножать клиента, то тогда ваще можно использовать от силы несколько потоков, для групп и нераспределенных юзверей. Тогда все будет диктоваться объектом очереди, где уже будет указано кто есть who ![]() Это сообщение отредактировал(а) NYX - 29.7.2012, 22:55 --------------------
'long long long' is too long for GC |
|||
|
||||
SVN74 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 740 Регистрация: 5.5.2008 Где: Комсомольск на Дн епре Репутация: 1 Всего: 18 |
Дело в том, что эффективность потоков заключается в самостоятельности выполнения задачи каждым потоком индивидуально...
В Вашем случае, при большом количестве пересекающихся ожиданий (общих ресурсов) - теряется смысл и скорость работы всей программы, может тогда вообще все создать на одном потоке. |
|||
|
||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
На одном потоке тоже было бы круто, но... мне не принципиальны потоки. Я так опнимаю самое главное это масштабируемость сервера и грамотное распределение нагрузки и лучше ваще автоматизированное. Если это возможно на одном потоке? Хм, быть одному потоку. Просто если потоков много, и юзвери допустим молчат, поток замораживается. В этом и прелесть. А однопоточное ПО оно будет безконца парсить очереди на предмет наличия. Либо так же создавать флаги наличия позиций очереди...
Это сообщение отредактировал(а) NYX - 29.7.2012, 22:58 --------------------
'long long long' is too long for GC |
|||
|
||||
SVN74 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 740 Регистрация: 5.5.2008 Где: Комсомольск на Дн епре Репутация: 1 Всего: 18 |
А сколько будет предположительное количество клиентов одновременно работать? |
|||
|
||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
Пальцем в небо - тысяща кляентоф :] но опять же, что делать с наплывом зомбочатеров? Вдруг народу захочется поболтать, куда их посылать? Мимо или на размножаемые серверы с логин-сервера? или как васче делать то? Если бы я знал как организовать шаровые ресурсы между двумя физическими серверами при условие что шаровые данные будут под треды и разделяемыми... знать-бы вот...
--------------------
'long long long' is too long for GC |
|||
|
||||
SVN74 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 740 Регистрация: 5.5.2008 Где: Комсомольск на Дн епре Репутация: 1 Всего: 18 |
![]() Та Вы что ? Забудьте о многопотоковости, это для Вас убийство, только неблокирующий сокет и общая база... Максимум 200 клиентов можно гонять по потокам, а если выше, только через один неблокирующий поток... Это сообщение отредактировал(а) SVN74 - 29.7.2012, 23:10 |
|||
|
||||
bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 63 Всего: 196 |
причем тут RAII?
Молодец. Теперь подсмотри где-нибудь обертку, которая производит таким же образом еще и захват с освобождением мьютекса. Например, в бусте. |
|||
|
||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
Если так, стиснув зубы... VPS и размножение на многих провах оно как бы, ну платное что ли. И допустим изначально гонять несколько отдельных серверов накладно, при том что кол-во пользователей может снижаться и варьироваться. А если бы например сделать на трех потоках для групп, то тогда можно было бы ОДНО И ТО ЖЕ ПО запускать уже в трех режимах.
1) как у же помоему писал - полноценный сервер 2) сервер в режиме прием-отдача 3) сервер калькуляций (операция с БД, проверка на содержание мата и прочее прочее) В этом случае, получается цепь TI - thread in TC - thread calc TO - thread out QI - queue in QO - queue out 1) TI -> QI -> TC -> OQ -> TO 2) TI -> QI ... ... ... OQ -> TO 3) ... ... QI -> TC -> OQ ... ... тогда скорость калькуляции была бы быстрее. Для пунктов 2 и 3 очереди были бы шаровыми, может и по экземпляру очереди на сервак, а может располагались бы например QI на 2, а OQ на 3. Но это единственное до чего я смог догадаться ![]() Добавлено @ 23:12 bsa,
Брр. В смысле? не, ну мьютек принципиально... ща-ща. Неявным образом захват мьютекса это будет создание объекта и деструктор уже будет выполняться по итогу выполнения функции. Окей... моя обертка работает так же ![]() Я понял в чем смысил. Если честно это очень здоровски использовать такие пряники. Так как можно создать весьма не сложные потокобезопасные объекты. А может даже и вообще сделать так, что бы все разделяемости делались закулисами. Это сообщение отредактировал(а) NYX - 29.7.2012, 23:23 --------------------
'long long long' is too long for GC |
|||
|
||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
А в бусте в каком направлении смотреть?
Это сообщение отредактировал(а) NYX - 29.7.2012, 23:38 --------------------
'long long long' is too long for GC |
|||
|
||||
bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 63 Всего: 196 |
boost::thread. Там есть класс mutex (ты его называешь критической секцией, - очень жаль, что ты меня так и не понял и пытаешься использовать везде термины windows). |
|||
|
||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
да я уже глянул исходники, я понял смысл. передается объект в конструктор и по завершению работы функции срабатывает деструктор который этот самый мутекс и освобождает
![]() В плане не понял? Про критсекции? Я знаю что это не мутексы и ваще это некий гибрид. У критсекций минус есть, они не могут быть доступны из других процессов. Поэтому критсекции удобно использовать для каких то внутренних атомарностей объектов. Если речь идет о шаровых данных, то мутексы \ семафоры удобнее, так как с их помощью можно добиться немного более лучшего эффекта, нежели выстраивание потоков в ряд. Это сообщение отредактировал(а) NYX - 30.7.2012, 17:49 --------------------
'long long long' is too long for GC |
|||
|
||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
концептуально читатели-писатели на мьютексахЪ
Это сообщение отредактировал(а) NYX - 30.7.2012, 19:01 Присоединённый файл ( Кол-во скачиваний: 2 ) ![]() --------------------
'long long long' is too long for GC |
|||
|
||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
Семафоры, мониторы и синхронные сообщения
Присоединённый файл ( Кол-во скачиваний: 1 ) ![]() --------------------
'long long long' is too long for GC |
|||
|
||||
bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 63 Всего: 196 |
Ты опять меня не понимаешь. Такое ощущение, что ты не читаешь что я тебе пишу. А видишь только ряд ключевых слов, но смысл предложений до тебя не доходит. Читай внимательно: В WINDOWS КРИТИЧЕСКОЙ СЕКЦИЕЙ НАЗЫВАЕТСЯ ТО, ЧТО ВЕЗДЕ НАЗЫВАЕТСЯ МЬЮТЕКСОМ. Именно поэтому, термин "критическая секция" лучше вообще не употреблять, кроме как в контексте WinAPI (именно на уровне реализации, а на уровне обсуждения стратегий и алгоритмов следует использовать mutex). Это сообщение отредактировал(а) bsa - 30.7.2012, 22:06 |
|||
|
||||
NYX |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 165 Регистрация: 9.1.2007 Где: Россия, Москва Репутация: нет Всего: нет |
bsa, вот всегда так. Я тебя прекрасно понял и написал аж несколько раз что критсекция в моем понимании это гибрид и что изначально есть мьютексы, семафоры дейкстры и многое другое
![]() ![]() ![]() ![]() Это сообщение отредактировал(а) NYX - 31.7.2012, 10:54 --------------------
'long long long' is too long for GC |
|||
|
||||
![]() ![]() ![]() |
Правила форума "С++:Общие вопросы" | |
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |