| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Общие вопросы > Потоки, работающие кроссплатформенно.. |
| Автор: Proger10 9.7.2009, 23:51 |
| Подскажите пожалуйста чтиво какое-нибудь (желательно с примерами), где можно почерпнуть информацию об организации работы с потоками. Код должен работать под Linux и Windows. Если будет и MacOS - будет вообще предел блаженства. Задача простейшая. Есть два "вечных" цикла, которые должны работать одновременно. Изредка перебрасывая какую-либо информацию через общие переменные. Пока что у меня получается только два цикла по очереди, либо две запущенных проги одновременно Компилятор: GCC. |
| Автор: Proger10 10.7.2009, 00:15 | ||
| Походу прямая мне дорога к Boost'у. Не подскажите ли, как с ним скомпилить прогу? Компилить пытался так:
(у меня GLut приложение) Пример взял отсюда: http://ru.wikipedia.org/wiki/Boost_(библиотека) (самый последний про треды) И вот чего-то не компилится оно... |
| Автор: Proger10 10.7.2009, 00:38 |
| О, действительно, так компилируется успешно! Спасибо! |
| Автор: Proger10 10.7.2009, 01:32 |
| У меня тут некоторая проблема возникла.. Понимаю, что это уже оффтопик по отношению к этой теме, но всё же - может кто смекнёт в чём проблема.. Вот мой код: http://paste.org.ru/?iqkord Команда сборки: g++ main.cpp -lglut -lboost_thread-mt `pkg-config opencv --cflags --libs` Требует: OpenCV, OpenGL, GLut, Boost Идея такая. Запускаю два окна в разных потоках. Одно окно - вечный цикл получающий изображение с вебкамеры, другое окно - это glutMainLoop, которая чего-то там лупит Фишка в том, что после cvWaitKey( 0 ) - это ожидание клика, - стартует drawScene(), на которой происходит "segmentation fault" (что в переводе на язык Windows: программа выполнила недопустимую ошибку и будет закрыта Почему у меня отрубилась возможность доступа к opengl? Без потоков - оба кода рабочие. Только выполняться они должны параллельно, взаимодействуя вот так друг с другом.. "Вот так" это - получаем кадр, чего-нибудь нарисуем через OpenGL, получаем ещё кадр - ещё рисуем.. Но пока что не получается даже и этого :( Есть предположение, что можно попытаться выделить всё, что связано с OpenGL в отдельный класс. Потом создать экземпляр этого класса и вызывать уже не drawScene, а "myClass.drawScene();". Только вот как бустом запустить в отдельном потоке экземпляр класса? Или такое нельзя сделать? |
| Автор: vinick 10.7.2009, 02:45 | ||
segmentation fault - это не просто недопустимая ошибка. это ошибка вызванная обращением к запретной области памяти. Явных проблем в коде я не вижу, но drawScene вызывается из обоих потоков и не защищена мьютексом. Скорее всего проблема в этом. Если ты работаешь в Linux попробуй запустить программу под valgrind, он ловит проблемы с памятью. |
| Автор: andrew_121 10.7.2009, 03:49 |
| Proger10, Да, и strace не забудь. И лог покажи. |
| Автор: Proger10 10.7.2009, 13:18 | ||
Хочу попробовать использовать вот такой пример мьютекса: http://www.ddj.com/showArticle.jhtml?documentID=cuj0205kempf&pgno=4 Но куда вставлять эту строчку "boost::mutex::scoped_lock lock(io_mutex);"? В начало drawScene функции и куда-то ещё? Изменил код на такой: http://paste.org.ru/?f1et0d Пока что, всё тоже самое осталось :( Сейчас буду тестить различными дебаггерами. Добавлено @ 13:23 valgrind после запуска моей проги выдаёт вот это: http://pastebin.ca/1490567 strace после запуска моего кода выдаёт только: "<unfinished ...> \n +++ killed by SIGSEGV +++" |
| Автор: andrew_121 10.7.2009, 13:49 | ||||
| Proger10 В твоем коде:
Ты уверен что эту параметры не нужны? Ты их в ноль проинициализируй, передаешь их функции хз* что) И для чего:
Перед возвратом из мэин? |
| Автор: Proger10 10.7.2009, 13:59 | ||
| andrew_121, тьфу.. по поводу ещё одной initOpenCVWindow - ошибся. Ну до той строки выполнение всё равно и не дойдёт никогда Я изменил на такое:
но от этого лучше не стало. Да они и так пустые эти argv. Я ничего не передаю в параметрах. Тем более что в начале линия отрисовывается через OpenGL. А вот после нажатия любой кнопки (для дальнейшей отрисовки на opengl) - сегментэйшн фолт.. Так как в начале отрисовывается и в OpenGL окно, и в OpenCV - можно подумать, что всё прекрасно инициализировано. А вот дальше с доступом какие-то конкретные проблемы.. |
| Автор: Proger10 10.7.2009, 14:20 |
| Кстати, с закомментированной drawScene - кадры получаем отлично. Т.е. с OpenCV всё впорядке. Что-то с OpenGL переменными... Может оно вообще drawScene не видит? |
| Автор: MTWizard 10.7.2009, 14:32 | ||
И убери заглушки. boost::bind подключается в <boost/bind.hpp> или <boost/function.hpp> |
| Автор: Proger10 10.7.2009, 14:39 | ||||
А.. спасибо. Понял. Только ситуацию, это естественно, так и не поправило.. Первый раз в OpenGL отрисовывается, а второй раз уже нет (второй - из потока). Не с инициализацией тут проблемы. С последующим доступом.. |
| Автор: vinick 10.7.2009, 14:49 | ||||||
Можно при помощи boost::bind
Valgrind говорит что у тебя было обращение к не инициализированной памяти, при вызове openGL функции откуда-то из initOpenCVWindow. Добавь при компиляции -g -O0, тогда в выхлопе valgrind будут номера строк и сможешь увидеть в каком конккретно вызове процесс упал. |
| Автор: Proger10 10.7.2009, 15:24 |
| Что-то не особо заметны номера строк.. В отдельный класс попытаюсь сейчас выделить OpenGL функции.. |
| Автор: Proger10 10.7.2009, 15:41 | ||
vinick, не пойму с классом.. http://paste.org.ru/?96j7qg - оно мне выдаёт на компайле:
Добавлено через 3 минуты и 40 секунд Упс, там про ошибку на 119 строке, ессно так: boost::thread myThread1( boost::bind( &OpenGLClass::initGlutWindow, c ) ); Ну да всё равно. К чему мы передаём в функцию initGlutWindow параметр экземпляра класса? Это точно верная форма вызова?? Очень подозрительная форма вызова: "OpenGLClass::initGlutWindow" |
| Автор: AlexT84 10.7.2009, 15:50 | ||||
Можно и без бинда
|
| Автор: vinick 10.7.2009, 15:54 | ||||||
Заметны
Добавлено через 4 минуты и 22 секунды
Это верная форма вызова. Ругается у тебя по другой причине, я так понял что ты ее уже исправил. |
| Автор: Proger10 10.7.2009, 16:28 | ||
| AlexT84, попытался сделать: http://paste.org.ru/?3e2azl и вот:
нифига не работает :( |
| Автор: Proger10 10.7.2009, 16:28 |
| --- |
| Автор: vinick 10.7.2009, 16:32 | ||||
замени на
|
| Автор: AlexT84 10.7.2009, 16:40 |
| Быть может, это потому, что у тебя operator () два раза определён. На 74 и 98 строке. Да, кстати, если хочеш работать с потоками, вынеси OpenGLClass c; из main, либо сделай его динамическим. |
| Автор: Proger10 10.7.2009, 16:53 | ||
http://paste.org.ru/?frnwfq
никак не угадаю где ошибка.. |
| Автор: DRUID3 10.7.2009, 16:58 | ||
Тупо для инфы - еще можно и через Qt4... |
| Автор: AlexT84 10.7.2009, 17:02 |
| 22 строка -- объявление объекта до описания класса 78 строка -- OpenGLClass { конструктор объявляется OpenGLClass() { остальные скорее всего производные. |
| Автор: MTWizard 10.7.2009, 17:15 |
| У тебя чистой воды гонка: ты запускаешь одновременно инициализацию openCV и openGL в разніх потоках. Если инициализация openCV отработает раньше, то она вызовет функции openGL в тот момент, когда openGL ещё недоинициализирована. Так что окончания инициализации надо дождаться и только потом запускать рисование |
| Автор: Proger10 10.7.2009, 17:18 | ||
| Что-то не получается.. а что за ошибка на 128? http://paste.org.ru/?f2udwb
|
| Автор: AlexT84 10.7.2009, 17:34 |
| На 128й строке у тебя скорее всего закрался посторонний символ, когда ты копипастил код с форума. Попробуй удалить её и перепечатать руками. На 84, 85, 86 передаёш методы класса как статические функции. на 137 должно быть производная от 128й. В общем доведи свой код, до состояния, когда он скомпилится без потоков. Потом и можно будет разбиратся. |
| Автор: andrew_121 10.7.2009, 17:40 |
Используй libpthread. Она на многие ОС портирована. OpenGLClass создай динамически. |
| Автор: Proger10 10.7.2009, 17:47 | ||
Нее.. погоди, вот с этим я не согласен. Я говорил, что у меня на OpenGL уже отрисовывается(!) первый раз.. А после клика на кнопку там вызывается второй раз drawScene - и вот тогда вылетает. Почему же мы делаем вывод, что оно не инициализируется, если оно даже отрисовывает первый раз линию успешно? А вот второй раз после cvWaitKey улетает.. |
| Автор: Lazin 10.7.2009, 17:50 |
зачем? зачем? |
| Автор: Proger10 10.7.2009, 17:56 | ||||||||
| А я кстати не понял зачем мне Qt4 предлагают Пытаюсь вот бустом запустить.. Хотя пока что и без буста класс не работает Добавлено через 1 минуту и 39 секунд Я вот знаете что не пойму.. У меня вот так объявлено:
почему оно мне выдаёт такую ошибку?
Добавлено через 5 минут и 31 секунду Я пытаюсь пока запустить класс без бустов и тут даже не выходит.. у меня сейчас код в таком состоянии: http://paste.org.ru/?43huh7
не подскажите ли, чего сейчас тут не так? Добавлено через 7 минут и 2 секунды Причём тут вообще строчки 84-86?? они вот: ----------------------------------- glLoadIdentity(); glBegin( GL_LINES ); ----------------------------------- и что в них не так? Добавлено через 12 минут и 58 секунд Там кстати была строчка в drawScene: boost::mutex::scoped_lock lock( io_mutex ); я её закомментил. Терь также ругается на другие строчки
пом оно определиться не может с ошибкой... |
| Автор: vinick 10.7.2009, 18:44 | ||||||||
Proger10, в твоем коде.
drawScene не статическая функция, нельзя ее туда передавать.
Ну тут совсем неправильно, если drawScene объявить статической, то вызывать ее надо
если не объявлять, то
Вывод: объяви drawScene как статическую. |
| Автор: Proger10 10.7.2009, 18:55 |
| Понятно. Спасибо! Терь скомпилировалось Объявил статисческими и handleResize, и handleKeypress.. Терь попробую с потоками.. Добавлено через 52 секунды Кстати, у меня наоборот - сейчас функция drawScene статическая и вызвать можно только так: openGLClass.drawScene(); через двоеточие - ругается. |
| Автор: andrew_121 10.7.2009, 19:03 |
| Lazin, Просто ждал от вас этого вопроса Кроме "вопросов", по теме что-то полезное сообщите? |
| Автор: vinick 10.7.2009, 19:11 | ||
Если двоеточия, то надо использовать имя класса а не имя объекта. Я настойчиво рекомендую почитать книжку по языку. Потому как то, что ты сотворил с классами - мягко говоря бред. |
| Автор: Proger10 10.7.2009, 19:13 |
| Омг ёмаё!!! Следующая проблема.. Как мне объявить: MyOpenGLClass openGLClass; так, чтобы она была видна из openCV? При инициализации в openGLClass (в конструктуре) есть glutMainLoop - это глутовский вечный цикл... дальше код не идёт на выполнение Добавлено через 4 минуты и 21 секунду vinick, понимаю, что бред. Мне хочется просто заставить её работать. Хоть как.. потом я уже красоту наведу. Я же решения ещё не нашёл даже.. |
| Автор: vinick 10.7.2009, 19:23 |
Вернись к варианту без классов, пока у тебя не общих данных, они тут нафиг не нужны. А то ты еще больше запутаешься. Найди место в коде где вылетает SIGSEGV, а потом уже отладчиком или отладочной печатью выясни почему это происходит. |
| Автор: Proger10 10.7.2009, 19:24 | ||
| Вот дерьмо.. снова segmentation fault. Привёл код в чувство: http://paste.org.ru/?orggqz Но после первого нажатия клавиши, сука, вылетает... Уж зла нет. Добавлено через 1 минуту и 41 секунду
Так в том-то и дело, что не понятно. Почему-то уходит доступ к OpenGL. Почему - фиг его знает.. Причём первый раз drawScene срабатывает, а на второй раз drawScene - вылетает. В классы я захотел выделить в надежде, что выделятся все переменные в одно место и там не будет таких ошибок... а фиг тут.. Добавлено через 3 минуты и 18 секунд Тут ведь видите.. код простейший. Тут ошибок быть не может.. Ну.. образно Мне кажется проблема в технологии распараллеливания.. Именна она делает невозможным доступ к opengl... мне так кажется. |
| Автор: Proger10 10.7.2009, 19:43 |
| То есть по сути я хочу сделать вечный цикл в котором отрисовывать в OpenGL.. больше ничего. Добавлено через 6 минут и 51 секунду только проблема в том, что для того, чтобы глут инициализировать нужно запустить glutMainLoop, который по сути вечный цикл и управление до моего кода не дойдёт, если поточить не буду эти два цикла (мой и glutMainLoop). |
| Автор: Lazin 10.7.2009, 20:01 | ||
зачем? подозреваю, что в целях обфускации кода, но не уверен... может просветите, откуда такая необходимость? зачем? boost.thread на порядок проще чем pthread, ТС все еще не может скомпилировать свой код, а ты ему предлагаешь использовать pthread? Добавлено через 1 минуту и 32 секунды а glut threadsafe? |
| Автор: Proger10 10.7.2009, 20:03 |
| Не правда! Я уже скомпилил его! Один хрен - не идёт |
| Автор: Lazin 10.7.2009, 20:11 |
| Proger10, начни последовательной программы, добейся того, что-бы твой код был прост и понятен, и самое главное - работал, а потом думай, что и как там можно распараллелить |
| Автор: Proger10 10.7.2009, 20:14 |
| Ну так.. отдельные части работают отлично! Т.е. opencv окно работает превосходно. И glut работает также превосходно. Когда у меня возникает цикл (в opencv) (предположим что это просто пустой цикл) почему-то drawScene отваливается. Lazin, чем плох этот код? http://paste.org.ru/?iqkord Прост.. но не работает ведь! |
| Автор: Proger10 10.7.2009, 21:12 |
| Кстати, а нет ли тут людей соображающих в GLut? Походу в ней проблема.. нельзя ли убрать glutMainLoop? Всмысле, чтобы при этом осталась работоспособсность проекта |
| Автор: zim22 10.7.2009, 21:26 |
ну конечно в ней. если ваш код не работает - то виновата библиотека/компилятор |
| Автор: Proger10 10.7.2009, 21:35 | ||
хахаха не, я серьёзно! Добавлено через 6 минут и 29 секунд Вот такой рабочий код: http://n2.nabble.com/show-webcam-in-OpenGL-td3091448.html он же: http://paste.org.ru/?8cv3zk Но ёлки палки.. 800 строк только для получения кадра и рисования двух палочек на экране?? |
| Автор: zim22 10.7.2009, 22:25 | ||
вы не пробовали в соотв.теме спросить? http://forum.vingrad.ru/forum/c-c++multimedia-OpenGL-DirectX.html |
| Автор: Proger10 10.7.2009, 22:27 |
| Дык зачем спрашивать если уже есть решение Кстати, вот текстуирование: http://paste.org.ru/?k51xks Будете смеяться, но проблема с неизвестно-куда-пиханием цикла по получению кадров осталась Добавлено через 2 минуты и 52 секунды Аааа... понял! Вот ответ: glutIdleFunc(display); во время idle (простаивания) будет вызываться постоянно функция display - ну здесь и можно ретривить по кадру с камеры. Походу... проблема решена |