PSD
Главный специалист
Offline
Пол:
|
|
« : 03-03-2006 06:10 » |
|
использую
CreateThread (NULL, 0, ThreadProc, 0, 0,&dwThreadID))
Хочу чтобы ThreadProc была методом класса из которого я создаю поток, теоретически метод класса имет один скрытый парамерт указатель на обект класса так что по идее в качестве ThreadProc можно подставить метод класса без параметров... но как это оформить и можно ли это в принципе делать не знаю.
Подскажите?
|
|
|
Записан
|
Да да нет нет все остальное от лукавого.
|
|
|
Hooter
|
|
« Ответ #1 : 03-03-2006 06:37 » |
|
Насколько я помню, сделать ThreadProc методом класса можно только в том случае, если метод будет объявлен как статический. Кстати, тебе в этом случае очень пригодится единственный параметр ThreadProc - будешь туда передавать указатель на экземпляр класса.
Иначе - никак.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #2 : 03-03-2006 06:37 » |
|
PSD, class X { /*struct*/ { static int ThreadProc(...) { //... return 0; } }; } так не покатит?
|
|
« Последнее редактирование: 03-03-2006 11:02 от Алексей1153 »
|
Записан
|
|
|
|
PSD
Главный специалист
Offline
Пол:
|
|
« Ответ #3 : 03-03-2006 10:58 » |
|
Я в итоге сделал так ...... class C_Serial_Link{
static DWORD WINAPI ThreadProc( LPVOID lpParameter ) {return reinterpret_cast<C_Serial_Link *>(lpParameter)->PortReadThread(lpParameter );} public: DWORD PortReadThread (LPVOID lpvoid); }
|
|
|
Записан
|
Да да нет нет все остальное от лукавого.
|
|
|
hd44780
Гость
|
|
« Ответ #4 : 23-03-2006 15:42 » |
|
Я всегда делаю функцию потока в классе как friend. friend DWORD threadFunc (LPVOId pParam);
при запуске из класса даю аргумент this. По этому указателю функция потока может получить доступ ко всем (!) членам и методам.
|
|
|
Записан
|
|
|
|
PSD
Главный специалист
Offline
Пол:
|
|
« Ответ #5 : 24-03-2006 05:47 » |
|
Тоже вариант... но френдовую функцию не сделаешь виртуальной....
|
|
|
Записан
|
Да да нет нет все остальное от лукавого.
|
|
|
lapulya
Молодой специалист
Offline
|
|
« Ответ #6 : 16-04-2006 21:45 » |
|
to PSD Дык, ты же сам написал static DWORD WINAPI ThreadProc( LPVOID lpParameter ) а теперь говоришь "Тоже вариант... но френдовую функцию не сделаешь виртуальной...." если ты ее статической сделал, то виртуальной она по определению быть не может...
|
|
|
Записан
|
С уважением Lapulya
|
|
|
PSD
Главный специалист
Offline
Пол:
|
|
« Ответ #7 : 17-04-2006 04:12 » |
|
Вы правы , в принципе можнго было сделать френда и из него вызвать нужный виртуальный метод.
|
|
|
Записан
|
Да да нет нет все остальное от лукавого.
|
|
|
|
lapulya
Молодой специалист
Offline
|
|
« Ответ #9 : 22-04-2006 23:19 » |
|
to doublebug а можно подробнее где это написано откуда и докуда читать (такие толмуты реально нет времени читать), а вообще не очень понятно как это - динамически (во время исполнения программы) определить ПОСТОЯННЫЙ АДРЕС функции!!! Очень на ерунду смахивает...не, в теории, конечно можно, если память в которую загружена программа (область в которую записан код) править в динамике, НО сказать, что это плохо - это значит ничего не сказать...
|
|
|
Записан
|
С уважением Lapulya
|
|
|
doublebug
Гость
|
|
« Ответ #10 : 24-04-2006 07:16 » |
|
в начале есть содержание там есть такая вещь Win32 Callback Thunking (C++ Closures): CAuxThunk<>
* Win32 CBTHook thunk
вот кусок сода из библиотеки
template <class T> class CAuxThunk { BYTE m_mov; // mov ecx, %pThis DWORD m_this; // BYTE m_jmp; // jmp func DWORD m_relproc; // relative jmp public: typedef void (T::*TMFP)();// это тип указателя на функцию член класса void InitThunk(TMFP method, const T* pThis)//передается указатель на функцию-член и указатель на сам класс { union { DWORD func; TMFP method; } addr; //здесь генерируется код этой функции addr.method = (TMFP)method; m_mov = 0xB9; m_this = (DWORD)pThis; m_jmp = 0xE9; m_relproc = addr.func - (DWORD)(this+1); FlushInstructionCache(GetCurrentProcess(), this, sizeof(*this)); } FARPROC GetThunk() const { _ASSERTE(m_mov == 0xB9); return (FARPROC)this; } };
сам этот темплейт является как-бы статической функцией класса. На чистом С++ такое не сделаешью Потому ипользуется динамическая генерация кода.
|
|
|
Записан
|
|
|
|
PSD
Главный специалист
Offline
Пол:
|
|
« Ответ #11 : 24-04-2006 08:46 » |
|
Интересное решение, получается мы можем передать в качестве главной процедуры вообще любой метод класса, только я не понял как модифицировать теплейт чтобы получилось произвольное число потоков, в моем случае один объект инкапсулирует в себе обычно 2 и больше потоков как правило один управляет асинхронным чтением данных с канала второй асинхронной записью но может быть и 4 потока когда объект выполняет функции моста а в принипе и больше если придется создаваь программый роутер.
|
|
|
Записан
|
Да да нет нет все остальное от лукавого.
|
|
|
doublebug
Гость
|
|
« Ответ #12 : 24-04-2006 08:55 » |
|
Интересное решение, получается мы можем передать в качестве главной процедуры вообще любой метод класса, только я не понял как модифицировать теплейт чтобы получилось произвольное число потоков
Что есть поток в данном контексте? Темплейт всего лишь дает возможность передать мембера в качестве callback функции для какого нить API вызова. Правда в такой реализации в системе с DEP это не будет работать.
|
|
|
Записан
|
|
|
|
PSD
Главный специалист
Offline
Пол:
|
|
« Ответ #13 : 24-04-2006 09:08 » |
|
Поток в смычле Thread который создается CreateThread(...) А что есть DEP?
|
|
|
Записан
|
Да да нет нет все остальное от лукавого.
|
|
|
doublebug
Гость
|
|
« Ответ #14 : 24-04-2006 09:12 » |
|
DEP это Data Execution Protection. Потому будет access violation. Надо еще добавить VirtualProtect вызов чтоб скорректировать флаги для страницы. Ну и есесно лучше память через new выделять для этого дела. У тебя разные функции для потоков используются или одна ?
|
|
|
Записан
|
|
|
|
PSD
Главный специалист
Offline
Пол:
|
|
« Ответ #15 : 24-04-2006 10:19 » |
|
Обычно разные, WriteChannel и ReadChannel Может быть еще SuperVisionQuerySort , ReciveClient SendClient пока пяти потоков для одного объекта хватало для всех задач.
Если нужно охватить еще один канал создается еще один экзепляр Объекта и унего свои потоки над всем этим безобразием весит MasterChannelFactory которая управляет времением жизни объектов и соттвественно должна ловить (пока еще не релизованно) эксепшены всех объектов системы и соттвественно при необходимости акуратно загружать и выгружать каналы.
|
|
|
Записан
|
Да да нет нет все остальное от лукавого.
|
|
|
doublebug
Гость
|
|
« Ответ #16 : 24-04-2006 10:48 » |
|
ну тогда его не зачем модифицировать для каждой функции свой Thunk Должен быть. тока мембер потому как поточная функция параметр принимает тоже должен быть с параметром (в твоем случает это &dwThreadID) а вообще для поточной функции надо использовать CAuxStdThunk ну и мембер должен быть тоже stdcall объявлен.
|
|
|
Записан
|
|
|
|
PSD
Главный специалист
Offline
Пол:
|
|
« Ответ #17 : 24-04-2006 10:58 » |
|
Так , стоп у темлейта в качестве параметра класс а не функция... или ты имешь виду делать для каждого потока InitThunk() с его потоковой, затем CreateThread(.... GetThunk...) и для следующего потока тоже самое но с его потоковой функцией? А никаких Эексепшенов при завершении процесса не возникнет?
|
|
|
Записан
|
Да да нет нет все остальное от лукавого.
|
|
|
doublebug
Гость
|
|
« Ответ #18 : 24-04-2006 11:39 » |
|
точно так не должно вообще этоту вещь чувак делал для тех случаев когда нельзя параметр в callback передать(контекст). Типа TIMERPROC.
|
|
|
Записан
|
|
|
|
lapulya
Молодой специалист
Offline
|
|
« Ответ #19 : 24-04-2006 18:36 » |
|
ну вот, я об этом и говорил, изменение кода программы, уже загруженной в память для исполнения, в ран тайме.... Это знаетели ээээ плохо (если не сказать больше) особенно для переносимости и устойчивости, в двух словах - это просто шаманство, как сказал один товарищ "Говорил я вам... - доведут бабы и кабаки до цугундера..."
|
|
|
Записан
|
С уважением Lapulya
|
|
|
doublebug
Гость
|
|
« Ответ #20 : 25-04-2006 08:39 » |
|
Ну это не изменение кода а его ренерация. По поводу шаманства сама Microsoft даже продает либу готорая модифицирует бинарный код проги на лету Ж). Но это все применимо если ты на 100% представлешь что делаешь и последствия твоих ошибок. И мое имхо это все далеко не для начинающих. Потому если есть какой нить более документированный метод лучше использовать его.
|
|
|
Записан
|
|
|
|
lapulya
Молодой специалист
Offline
|
|
« Ответ #21 : 25-04-2006 20:18 » |
|
))) регенерация ))) мне ща плохо будет, это именно изменение (если есть возражения, то прошу объяснить чем регенерация отличается от изменения). Кстати майкрософт тут совсем не показатель, они такое вытворяют на СВОЕМ !!! компиляторе, в общем случае это именно шаманство (если есть сомнения можно обратиться к букве закона, т.е. стандарта).
Я согласен что если очень надо, то можно, особенно для драйверов и тому побного, но в приложении ммммм я думаю это легко обходиться (особенно если известен this и индекс, читай смещение функции). Думаю, что писать так в программе-тетсе для защиты диссертации или в тесте или при разбор/изучениие интересных ситуаций можно/нужно, но в коммерческой программе.... думаю не стоит. Главное, что поймать и что еще важнее найти и исправить ошибку возникшую в ран тайме ваще не реально (естесссно если падает прога не в данном месте а чуть по дальше)
Вердикт - достаточно интересно..., но не более того.
|
|
|
Записан
|
С уважением Lapulya
|
|
|
npak
|
|
« Ответ #22 : 26-04-2006 10:11 » |
|
Я вот чего не понимаю -- если используется объектно-ориентированный язык, то зачем нужно возиться с заморочками вида "как передать объект в необъектную функцию" ИМХО, в этом случае надо сделать ОО решение - класс-обёртку вокруг соответствующего программного интерфейса (в данном случае функции работы с потоками) и дальше пользоваться только им. Смешение ОО стиля и процедурного/структурного программирования - это один из самых "страшных грехов" программистов на Си++. Для Си++ есть много свободных реализаций управления потоками, достаточно поискать в Гугле. Простейший пример - http://www.codeproject.com/threads/ThreadClass.aspСоздание потока - дорогая операция в большинстве современных ОС, так как связана с переключением в режим ядра, поэтому добавление нескольких инструкций класса-обёртки роли не сыграют, зато упростят код и повысят общую надёжность программы.
|
|
|
Записан
|
|
|
|
|