Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: ThreadProc член класса это возможно?  (Прочитано 22183 раз)
0 Пользователей и 2 Гостей смотрят эту тему.
PSD
Главный специалист

ru
Offline Offline
Пол: Мужской

« : 03-03-2006 06:10 » 

использую

CreateThread (NULL, 0, ThreadProc, 0, 0,&dwThreadID))

Хочу чтобы ThreadProc была методом класса из которого я создаю поток, теоретически метод класса имет один скрытый парамерт указатель на обект класса так что по идее в качестве ThreadProc  можно подставить метод класса без параметров... но как это оформить и можно ли это в принципе делать не знаю.

Подскажите?

 


Записан

Да да нет нет все остальное от лукавого.
Hooter
Опытный

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 03-03-2006 06:37 » 

Насколько я помню, сделать ThreadProc методом класса можно только в том случае, если метод будет объявлен как статический.
Кстати, тебе в этом случае очень пригодится единственный параметр ThreadProc - будешь туда передавать указатель на экземпляр класса.

Иначе - никак.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #2 : 03-03-2006 06:37 » 

PSD,

class X
{


/*struct*/
{
  static int ThreadProc(...)
  {
        //...
        return 0;
  }
};

}

так не покатит? Улыбаюсь
« Последнее редактирование: 03-03-2006 11:02 от Алексей1153 » Записан

PSD
Главный специалист

ru
Offline 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
Главный специалист

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 24-03-2006 05:47 » 

Тоже вариант... но френдовую функцию не сделаешь виртуальной....
Записан

Да да нет нет все остальное от лукавого.
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #6 : 16-04-2006 21:45 » 

to PSD
Дык, ты же сам написал
static DWORD WINAPI ThreadProc( LPVOID lpParameter )
а теперь говоришь
"Тоже вариант... но френдовую функцию не сделаешь виртуальной...."
если ты ее статической сделал, то виртуальной она по определению быть не может...
Записан

С уважением Lapulya
PSD
Главный специалист

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 17-04-2006 04:12 » 

Вы правы , в принципе можнго было сделать френда и из него вызвать нужный виртуальный метод.
Записан

Да да нет нет все остальное от лукавого.
doublebug
Гость
« Ответ #8 : 18-04-2006 08:54 » 

Глянь на http://www.codeproject.com/atl/atlaux.asp
Там есть такое понятие как Thunk.
Фактически это генерируемая динамически статическая функция которая в свою очередь вызывает метод класса.
Записан
lapulya
Молодой специалист

ru
Offline 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
Главный специалист

ru
Offline Offline
Пол: Мужской

« Ответ #11 : 24-04-2006 08:46 » 

Интересное решение, получается мы можем передать в качестве главной процедуры вообще любой метод класса, только я не понял как модифицировать теплейт чтобы получилось произвольное число потоков, в моем случае один объект инкапсулирует в себе обычно 2 и больше потоков как правило один управляет асинхронным чтением данных с канала второй асинхронной записью но может быть и 4 потока когда объект выполняет функции моста а в принипе и больше если придется создаваь программый роутер.   
Записан

Да да нет нет все остальное от лукавого.
doublebug
Гость
« Ответ #12 : 24-04-2006 08:55 » 

Интересное решение, получается мы можем передать в качестве главной процедуры вообще любой метод класса, только я не понял как модифицировать теплейт чтобы получилось произвольное число потоков 
Что есть поток в данном контексте?
Темплейт всего лишь дает возможность передать мембера в качестве callback функции для какого нить API вызова.
Правда в такой реализации в системе с DEP это не будет работать.
Записан
PSD
Главный специалист

ru
Offline 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
Главный специалист

ru
Offline 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
Главный специалист

ru
Offline Offline
Пол: Мужской

« Ответ #17 : 24-04-2006 10:58 » 

Так , стоп у темлейта в качестве параметра класс а не функция... или
ты имешь виду делать для каждого потока InitThunk() с его потоковой, затем CreateThread(.... GetThunk...) и для следующего потока тоже самое но с его потоковой функцией?
А никаких Эексепшенов при завершении процесса не возникнет?
Записан

Да да нет нет все остальное от лукавого.
doublebug
Гость
« Ответ #18 : 24-04-2006 11:39 » 

точно так
не должно
вообще этоту вещь чувак делал для тех случаев когда нельзя параметр в callback передать(контекст).
Типа TIMERPROC.
Записан
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #19 : 24-04-2006 18:36 » 

ну вот, я об этом и говорил, изменение кода программы, уже загруженной в память для исполнения, в ран тайме.... Это знаетели ээээ плохо (если не сказать больше) особенно для переносимости и устойчивости, в двух словах - это просто шаманство, как сказал один товарищ "Говорил я вам... - доведут бабы и кабаки до цугундера..."
Записан

С уважением Lapulya
doublebug
Гость
« Ответ #20 : 25-04-2006 08:39 » 

Ну это не изменение кода а его ренерация.
По поводу шаманства сама Microsoft даже продает либу готорая модифицирует бинарный код проги на лету Ж).
Но это все применимо если ты на 100% представлешь что делаешь и последствия твоих ошибок.
И мое имхо это все далеко не для начинающих.
Потому если есть какой нить более документированный метод лучше использовать его.
Записан
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #21 : 25-04-2006 20:18 » 

))) регенерация ))) мне ща плохо будет, это именно изменение (если есть возражения, то прошу объяснить чем регенерация отличается от изменения). Кстати майкрософт тут совсем не показатель, они такое вытворяют на СВОЕМ !!! компиляторе, в общем случае это именно шаманство (если есть сомнения можно обратиться к букве закона, т.е. стандарта).

Я согласен что если очень надо, то можно, особенно для драйверов и тому побного, но  в приложении ммммм я думаю это легко обходиться (особенно если известен this и индекс, читай смещение функции). Думаю, что писать так в программе-тетсе для защиты диссертации или в тесте или при разбор/изучениие интересных ситуаций можно/нужно, но в коммерческой программе.... думаю не стоит. Главное, что поймать и что еще важнее найти и исправить ошибку возникшую в ран тайме ваще не реально (естесссно если падает прога не в данном месте а чуть по дальше)

Вердикт - достаточно интересно..., но не более того.
Записан

С уважением Lapulya
npak
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #22 : 26-04-2006 10:11 » new

Я вот чего не понимаю -- если используется объектно-ориентированный язык, то зачем нужно возиться с заморочками вида "как передать объект в необъектную функцию"

ИМХО, в этом случае надо сделать ОО решение - класс-обёртку вокруг соответствующего программного интерфейса (в данном случае функции работы с потоками) и дальше пользоваться только им.  Смешение ОО стиля и процедурного/структурного программирования - это один из самых "страшных грехов" программистов на Си++.

Для Си++ есть много свободных реализаций управления потоками, достаточно поискать в Гугле.  Простейший пример - http://www.codeproject.com/threads/ThreadClass.asp

Создание потока - дорогая операция в большинстве современных ОС, так как связана с переключением в режим ядра, поэтому добавление нескольких инструкций класса-обёртки роли не сыграют, зато упростят код и повысят общую надёжность программы.
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines