Доброго времени суток...
Есть такой вопросик...
Сеществует несколько потоков (чистый WinAPI) которым нужно обмениваться некоторыми структурами (причем
структуры могут быть не фиксированного размера) необходимо создать что то наподобие очереди этих структур (с функциями Pop и Push).
до этого делал все на std::queue<> но раньше структура была фиксированная. Теперь же если в структуре реализовать поле (char* name) не будедет ли проблем с указателями? ведь поток выставивший в очередь
одну структуру может сразу выставить и вторую причем используя теже локальные переменные для ее формирования что и для первой.. ..сумбурно получилось.
С уважением....
24.05.04 03:23: Перенесено модератором из 'C/C++'. Flamer (22) в WIN API adontz (19) в WIN API — ПК
Здравствуйте, merlinJap, Вы писали:
J>Доброго времени суток... J>Есть такой вопросик... J>Сеществует несколько потоков (чистый WinAPI) которым нужно обмениваться некоторыми структурами (причем J>структуры могут быть не фиксированного размера) необходимо создать что то наподобие очереди этих структур (с функциями Pop и Push). J>до этого делал все на std::queue<> но раньше структура была фиксированная. Теперь же если в структуре реализовать поле (char* name) не будедет ли проблем с указателями? ведь поток выставивший в очередь J>одну структуру может сразу выставить и вторую причем используя теже локальные переменные для ее формирования что и для первой.. ..сумбурно получилось.
J>С уважением....
не надо в структуры очереди записывать указатели на локальные переменные(например вместо char* использовать std::string), вот что могу сказать в ответ на ваше
сообщение, хотя это вы и сами наверное знаете знаете.
Здравствуйте, merlinJap, Вы писали:
J>Доброго времени суток... J>Есть такой вопросик... J>Сеществует несколько потоков (чистый WinAPI) которым нужно обмениваться некоторыми структурами (причем J>структуры могут быть не фиксированного размера) необходимо создать что то наподобие очереди этих структур (с функциями Pop и Push). J>до этого делал все на std::queue<> но раньше структура была фиксированная. Теперь же если в структуре реализовать поле (char* name) не будедет ли проблем с указателями? ведь поток выставивший в очередь J>одну структуру может сразу выставить и вторую причем используя теже локальные переменные для ее формирования что и для первой.. ..сумбурно получилось.
J>С уважением....
Недавно решал подобную задачу.
Я не использовал std::queue<> — написал свою.
для поля char* Name выделяй память динамически. Эта указатель! Т.е твоя очередь должна нсти не
структуру, а указатель на структуру. В другом потоке твоя структура будет доступна по указатель
из очереди. Поэтому естественно нужно не забыть освободить память и делать это будет уже поток-приёмник.
У меня всё это работал без каких либо проблем.
Пример кинуть?
Здравствуйте, achmed, Вы писали:
A>Здравствуйте, merlinJap, Вы писали:
J>>Доброго времени суток... J>>Есть такой вопросик... J>>Сеществует несколько потоков (чистый WinAPI) которым нужно обмениваться некоторыми структурами (причем J>>структуры могут быть не фиксированного размера) необходимо создать что то наподобие очереди этих структур (с функциями Pop и Push). J>>до этого делал все на std::queue<> но раньше структура была фиксированная. Теперь же если в структуре реализовать поле (char* name) не будедет ли проблем с указателями? ведь поток выставивший в очередь J>>одну структуру может сразу выставить и вторую причем используя теже локальные переменные для ее формирования что и для первой.. ..сумбурно получилось.
J>>С уважением.... A>не надо в структуры очереди записывать указатели на локальные переменные(например вместо char* использовать std::string), вот что могу сказать в ответ на ваше A>сообщение, хотя это вы и сами наверное знаете знаете.
А я считаю, что лучше именно указатели Если строка длинючая, то ИМХО гораздо проще передать указатель на неёё
чем копировать всё по байтам. По крайней мере мне показалось это более эффективным. У меня работало без проблем (главное не допустить утечки памяти).
Здравствуйте, Red Line, Вы писали:
RL>Недавно решал подобную задачу. RL>Я не использовал std::queue<> — написал свою.
RL>для поля char* Name выделяй память динамически. Эта указатель! Т.е твоя очередь должна нсти не RL>структуру, а указатель на структуру. В другом потоке твоя структура будет доступна по указатель RL>из очереди. Поэтому естественно нужно не забыть освободить память и делать это будет уже поток-приёмник.
RL>У меня всё это работал без каких либо проблем. RL>Пример кинуть?
Да пожалуйста...буду очень признателен....зарание спасибо
merlin2000@hotmail.ru
Если ты делаешь new то проблем быть не должно (только скомпилируй с multithreaded CRT), а если указываешь адрес локального массива, то ляжет в любом случае.
ЗЫ: Я бы Windows Messages задействовал. Они шутрые, а std::queue не факт, что потокобезопасен. Окна по идее не объязательны, можно PostThreadMessage использовать. TranslateMessage DispatchMessage в таком случае заменяются на непосредственную обработку (switch)
RL>А я считаю, что лучше именно указатели Если строка длинючая, то ИМХО гораздо проще передать указатель на неёё RL>чем копировать всё по байтам. По крайней мере мне показалось это более эффективным. У меня работало без проблем (главное не допустить утечки памяти).
не надо в структуры очереди записывать указатели на локальные переменные, если строка располагается
в динамической памяти, то указатель будет не на локальную переменную.
Здравствуйте, adontz, Вы писали:
A>Здравствуйте, merlinJap, Вы писали:
A>Если ты делаешь new то проблем быть не должно (только скомпилируй с multithreaded CRT), а если указываешь адрес локального массива, то ляжет в любом случае.
A>ЗЫ: Я бы Windows Messages задействовал. Они шутрые, а std::queue не факт, что потокобезопасен. Окна по идее не объязательны, можно PostThreadMessage использовать. TranslateMessage DispatchMessage в таком случае заменяются на непосредственную обработку (switch)
Если потоки насыщеные (т.е скорость накачки очереди высока) то я считаю что виндовую очередь использовать нельзя.
Лучше использовать очередь винды только для оповещения потоков о возникновении определённых событий и не более.
Если система перегружена (например юзер запустил что) то сообщения будут скапливаться в очереди, очередь будет
распухать как снежный ком, вобщем очередь вещь не надёжная. Я сам видёл как чувак читал данные с COM-порта — есть\нет
кабель а данные идут вот тебе и очереди.
Для потоков интенсивно обменивающихся данными в реальном времени нужно использовать мютексы и события а данные копировать
не пополям структуры, а при помощи memcpy() так она работает намного быстрее.
И никаких сообщений не нужно.
Вот моё ИМХО!
Здравствуйте, Red Line, Вы писали:
RL>Если потоки насыщеные (т.е скорость накачки очереди высока) то я считаю что виндовую очередь использовать нельзя.
ну-ну это громко сказано. Использовать можно, просто это будет не самый эффективый способ.
RL>Лучше использовать очередь винды только для оповещения потоков о возникновении определённых событий и не более.
А данные откуда брать? Значит отдельно нужна очередь данных, запись в которую надо отдельно синхронизировать.... Вобщем вы предлагаете завести 2 парралельно работабщие очереди, которые придётся синхронизировать друг с другом и аждую саму по себе.
RL>Если система перегружена (например юзер запустил что) то сообщения будут скапливаться в очереди, очередь будет RL>распухать как снежный ком, вобщем очередь вещь не надёжная.
Максимальный размер очереди по умолчанию, до 10000 сообщений на поток. К тому же фраза "юзер запустил что" звучит странно.
Очередь сама по себе в 99% случает работает меньшее время, чем обработчик собятия, так что если проессор загружен на 100%, у вас всё будет тормозить. В секунду у Windows проходит до нескольких сотен сообщений. А их ещё обрабатывать надо. Загрузка проссора при этом пара процентов.
RL>Я сам видёл как чувак читал данные с COM-порта — есть\нет RL>кабель а данные идут вот тебе и очереди.
Может он просто что-то нерпвильно сделал? Я при желании могу и по хуже написать, но это моя проблема, а не проблема очереди.
RL>Для потоков интенсивно обменивающихся данными в реальном времени нужно использовать мютексы и события а данные копировать RL>не пополям структуры, а при помощи memcpy() так она работает намного быстрее.
Не выйдет. Если есть два потока, то мьютексы и события спасут, но если потоков 3? Вот ждут два потока в WaitForSingleObject оба дождались одновремнно и оба начали одновременно писать данные. И привет...
Здравствуйте, adontz, Вы писали:
A>Здравствуйте, Red Line, Вы писали:
RL>>Если потоки насыщеные (т.е скорость накачки очереди высока) то я считаю что виндовую очередь использовать нельзя.
A>ну-ну это громко сказано. Использовать можно, просто это будет не самый эффективый способ.
Да, я перегнул палку — прошу извинить
RL>>Лучше использовать очередь винды только для оповещения потоков о возникновении определённых событий и не более.
A>А данные откуда брать? Значит отдельно нужна очередь данных, запись в которую надо отдельно синхронизировать.... Вобщем вы предлагаете завести 2 парралельно работабщие очереди, которые придётся синхронизировать друг с другом и аждую саму по себе.
RL>>Если система перегружена (например юзер запустил что) то сообщения будут скапливаться в очереди, очередь будет RL>>распухать как снежный ком, вобщем очередь вещь не надёжная.
A>Максимальный размер очереди по умолчанию, до 10000 сообщений на поток. К тому же фраза "юзер запустил что" звучит странно. A>Очередь сама по себе в 99% случает работает меньшее время, чем обработчик собятия, так что если проессор загружен на 100%, у вас всё будет тормозить. В секунду у Windows проходит до нескольких сотен сообщений. А их ещё обрабатывать надо. Загрузка проссора при этом пара процентов.
Скажу просто: если у тебя на входе видеопоток который нужно обрабатывать в рантайме — то очередь уверен не пойдёт, а если данные идущие от модема — здесь я с Вами
согласен — но я бы так всё равно не делал...
RL>>Я сам видёл как чувак читал данные с COM-порта — есть\нет RL>>кабель а данные идут вот тебе и очереди.
A>Может он просто что-то нерпвильно сделал? Я при желании могу и по хуже написать, но это моя проблема, а не проблема очереди.
RL>>Для потоков интенсивно обменивающихся данными в реальном времени нужно использовать мютексы и события а данные копировать RL>>не пополям структуры, а при помощи memcpy() так она работает намного быстрее.
A>Не выйдет. Если есть два потока, то мьютексы и события спасут, но если потоков 3? Вот ждут два потока в WaitForSingleObject оба дождались одновремнно и оба начали одновременно писать данные. И привет...
Потоков может быть хоть 53.
Поток №1 закачивает данные в буфер. (Буфер есть очередь).
Все остальные потоки спят на событие. Когда поток №1 закончил запись данных в буфер, он будет остальные потоки, которые спят на событие.
Предположим, что для записи данных в очередь потоки №2,3 используют метод Put(). Если первой строкой (не стоит понимать буквально кончено) будет
вызов EnterCriticalSection(), а последней строкой LeaveCriticalSection() то получется "Кто первый встал того и тапки" Т.е оба записать никогда не смогут. Но тут речь уже о синхонизации доступа к данным,
(для этого и нужны крит. секции)а не о синхронизации потоков (для этого события и мьютексы), а это я как само собой разумеющееся. Я даже и не упоминал об этом.
Вобщем это моё виденье, хотя может знаний у меня и не хватает конечно
если у Вас есть такая возможность, то стоило бы глянуть в сторону ACE, ACE_Task<ACE_MT_SYNCH>. конечно это уже будет не чистый API, но экономия времени разработки будет значительная.
Здравствуйте, Red Line, Вы писали:
RL>Здравствуйте, achmed, Вы писали:
A>>Здравствуйте, merlinJap, Вы писали:
J>>>С уважением.... A>>не надо в структуры очереди записывать указатели на локальные переменные(например вместо char* использовать std::string), вот что могу сказать в ответ на ваше A>>сообщение, хотя это вы и сами наверное знаете знаете.
RL>А я считаю, что лучше именно указатели Если строка длинючая, то ИМХО гораздо проще передать указатель на неёё чем копировать всё по байтам. По крайней мере мне показалось это более эффективным.
Не согласен. Мы тестировали stl строки и контейнеры stl перед использованием их в одном мощном многопоточном серверном приложении — они оказались весьма эффективны. Проблем с производительностью у приложения не было никаких.
Компьютер сделает всё, что вы ему скажете, но это может сильно отличаться от того, что вы имели в виду.
Re: Очередь сообщений между потоками?
От:
Аноним
Дата:
24.05.04 06:53
Оценка:
Сдается, что у тебя проблема не с потоками,
а с тем, как создавать коллекции разнородных объектов (структур).
Я бы пока на время забыл о потоках и передачи данных между потоками,
а подумал бы именно о том, как организовать эту коллекцию.
О потоках можно потом вспомнить...
Ну вот и снова здрасте.....блин..ну зажал сам себе задачку....
Значть так...отчитываюсь....(хотя не совсем все получилось) ЕЩЕ НУЖНА ВАША ПОМОШЬ
Значить решил я сделать так, используя STL:dueue сознаю буфер в который помещаю эоементы
следующего вида
struct sStackItem{
LPVOID m_Data; — указатель на участок памяти в который были скопированны данные сообщения
UINT m_Size; — размер этих данных
};
Соответственно когда вызываю Push (в моем классе), то вы деляю память, копирую туда данные, указательн на них
пишу в структуру а ее заношу в буфер.
Аналогично в Pop беру посл элемент буффера считываю память по указателю sStackItem::m_Data, соответсвующим..размером, затем освобождаю эту память...
Все эти функции как только можно постарался развязать для многопоточного режима. НО....... все здорво работает
когда пишет один поток а читает другой....а вот если пишут 2 потока......а читает один....вот тут проблемма...и я совсем не пойму ПОЧЕМУ Насамом деле они...работают...но если кол-во переданных сообщений..не превышает определенного значения (около 5 000 000 (бред....))...
Подскажите.........почему...моих знаний явно не хватает......
Привожу код класса для очереди....
(прошу отнестись с пониманием........если обнаружаться какие либо ошибки...или недочеты в коде ПОЖАЛУЙСТА напишите....мне это важно...буду очнь рад любым высказываниям....)
НУ И КОНЕЧНО ГАВНЫЙ ВОПРОС....ПОЧЕМУ с 2мя одновременно пишушими потоками не работат!!!!!!
Здравствуйте, Leonid Troyanovsky, Вы писали:
A>>Максимальный размер очереди по умолчанию, до 10000 сообщений на поток. LT> Это почему?
Windows 2000/XP: There is a limit of 10,000 posted messages per message queue. This limit should be sufficiently large. If your application exceeds the limit, it should be redesigned to avoid consuming so many system resources. To adjust this limit, modify the following registry key:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\USERPostMessageLimit
The minimum acceptable value is 4000.