Форум программистов, компьютерный форум CyberForum.ru

Статический метод как точка входа в поток - как избавиться - C++

Восстановить пароль Регистрация
 
Bretbas
22 / 17 / 1
Регистрация: 05.08.2013
Сообщений: 466
Завершенные тесты: 1
07.01.2014, 23:21     Статический метод как точка входа в поток - как избавиться #1
Привет всем.Вопрос такой: использую потоки в своей программе,они создаются и уничтожаются в классе, и в классе так же находится метод,который является точкой входа потока.Суть в том,что если эта точка входа находится в классе,то ее нужно обьявлять как static,что мне не подходит,так как все объекты,находящиеся в этом методе нужно тоже делать статическими,а их довольно много.Собственно вот и нарисовывается сам вопрос - как избавиться от этой "статичности"?)Искал в гугле,не понял ничего)можете подробнее объяснить как это сделать?
Использую winapi для работы с потоками
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
NoMasters
Псевдослучайный
1737 / 1080 / 69
Регистрация: 13.09.2011
Сообщений: 3,093
08.01.2014, 00:02     Статический метод как точка входа в поток - как избавиться #2
Что мешает использовать в качестве точки входа специально обученную функцию, вызывающую какие угодно методы?
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
08.01.2014, 00:06     Статический метод как точка входа в поток - как избавиться #3
в новом стандарте такой проблемы нет.
но если он по какой-то причине не доступен, то:
в татическую фунцию передаете this. статическая функция обычно void* принимает.
она кастит этот void* к типу самого класса и вот в статической фунции у вас
есть указатель на инстанс класса. вызываете у него какие хотите методы, ведь
статической функции доступны все методы\мемберы через этот указатель.
Плутон
13 / 13 / 4
Регистрация: 29.06.2011
Сообщений: 85
08.01.2014, 00:10     Статический метод как точка входа в поток - как избавиться #4
Создаёте статическую функцию, которая будет являтся дружественной для нужного класса(ThreadProc).
Затем создаёте простую функцию (член) класса, которая должна выполнять необходимые действия.
В CreateThread передаёте указатель на статическую функцию, а в качестве lpParametr передаёте указатель на класс, в котором находится нужная функция член.
Затем в ThreadProc пишите:
return ((ВАШ_КЛАСС*)lpParametr->ФУНКЦИЯ_ЧЛЕН());
DiffEreD
 Аватар для DiffEreD
1420 / 757 / 95
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
08.01.2014, 00:10     Статический метод как точка входа в поток - как избавиться #5
Может воспользоваться тем что предлагает C++11:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <thread>
 
class some_class
{
   mutable std::thread t;
   int val = 100;
public:
   void foo(int n) const
   {
      for (int i = 0; i < n; ++i)
         std::cout << "Hello from foo. val = " << val << "\n";
   }
 
   void create_thread() const
   {
      t = std::thread(&some_class::foo, this, 5);
      t.join();
   }
};
 
int main()
{
   some_class sm;
   sm.create_thread();
 
   return 0;
}
Bretbas
22 / 17 / 1
Регистрация: 05.08.2013
Сообщений: 466
Завершенные тесты: 1
08.01.2014, 14:19  [ТС]     Статический метод как точка входа в поток - как избавиться #6
А как именно передать this через передаваемый указатель в статическом методе?можете привести пример?
С стандартной библиотекой <thread> знаком,но мне нужно именно winapi
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
08.01.2014, 14:33     Статический метод как точка входа в поток - как избавиться #7
свой винапишный код покажите. с ним проще будет объяснить.
Bretbas
22 / 17 / 1
Регистрация: 05.08.2013
Сообщений: 466
Завершенные тесты: 1
09.01.2014, 00:13  [ТС]     Статический метод как точка входа в поток - как избавиться #8
Я пишу вам с мобильного телефона,интернета на компьютере нет,поэтому сложно будет написать вам код,потому что он достаточно весомый...
Короче у меня есть есть два класса _figure и _area.В классе _figure имеется метод,который мне нужно выполнять в новом потоке - DWORD WINAPI MoveDown(PVOID).В классе _area есть метод void Start() в котором имеется указатель на класс _figure.И как раз в методе Stast() мне нужно заводить как раз второй поток с точкой входа MoveDown(...).Поток завожу функцией CreateThread(...) ,куда передаю собственно функцию MoveDown(...) и указатель на класс _figure.Суть в том,что мне нужно делать эту точку входа статической,и следовательно все методы и поля,которые там используются(в частности они все являются данными класса _figure) нужно делать тоже статическими,что меня категорически не устраивает...
Вот собственно рассказал на словах Вам мой код...Помогите пожалуйста
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
09.01.2014, 00:20     Статический метод как точка входа в поток - как избавиться #9
вот так я надеюсь будет понятно:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
class Figure
{
public:
  void MoveDown()
  {
    // ...
  }
 
  static void MoveDown(PVOID figure)
  {
    static_cast<Figure*>(figure)->MoveDown();
  }
};
т.е. по прежнему вызывается статический метод, но ему передается указатель на инстанс класса.
этот void* кастится к Figure* и тут же вызывается его метод. в результате метод будет вызван в
отдельном потоке для отдельного инстанса. никаких статических полей не надо.
Bretbas
22 / 17 / 1
Регистрация: 05.08.2013
Сообщений: 466
Завершенные тесты: 1
09.01.2014, 23:08  [ТС]     Статический метод как точка входа в поток - как избавиться #10
Во!всё заработало!спасибо большое...теперь всё понятно)
outoftime
║XLR8║
 Аватар для outoftime
505 / 427 / 33
Регистрация: 25.07.2009
Сообщений: 2,297
09.01.2014, 23:20     Статический метод как точка входа в поток - как избавиться #11
Bretbas, я не читал все посты. Но мне кажется паттерн одиночка (singletone) подходит как никто другой.

Добавлено через 2 минуты
http://en.wikipedia.org/wiki/Singleton_pattern
Bretbas
22 / 17 / 1
Регистрация: 05.08.2013
Сообщений: 466
Завершенные тесты: 1
10.01.2014, 23:59  [ТС]     Статический метод как точка входа в поток - как избавиться #12
Слушайте,а не поможете сделать обертку в виде класса для создания потока?Чтобы в конструктор я передавал название функции,которая будет использована как точка входа в поток,потом название класса где выполняется поток и сам объект на параметры?И чтобы статический метод этот был внутри класса,и меня не затрагивал
Bretbas
22 / 17 / 1
Регистрация: 05.08.2013
Сообщений: 466
Завершенные тесты: 1
12.01.2014, 00:57  [ТС]     Статический метод как точка входа в поток - как избавиться #13
Ммм?
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
12.01.2014, 01:04     Статический метод как точка входа в поток - как избавиться #14
если нет возможности использовать новый стандарт, то все равно лучше воспользоваться чем-то готовым.
boost, tbb, ...

если писать универсальную вещь, то код будет досаточно хитрый, с кучей шаблонов и все равно скорее всего криво получится.
Bretbas
22 / 17 / 1
Регистрация: 05.08.2013
Сообщений: 466
Завершенные тесты: 1
13.01.2014, 02:50  [ТС]     Статический метод как точка входа в поток - как избавиться #15
Да я хотел тупо обертку сделать,чтобы был класс,для создание потока, и чтобы. для каждого потока имелся свой экземпляр класса,куда через конструктор передается функция-метод,котороя потом вызывается в статическом методе этого класса.Вот типо такого что-то))
А еще...как мне передать формальный параметр в функцию,которая является точкой входа в поток?
C++
1
2
3
4
5
6
7
8
...
class primer
public:
void funcmain(int i);
static DWORD WINAPI fun(PVOID object)
{
static_cast<primer*>object -> funcmain(что сюда передать и как);
...
Вот примерчик набросал...тяжело с мобилы объяснять:-)
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
13.01.2014, 23:04     Статический метод как точка входа в поток - как избавиться #16
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class primer
{
public:
  void funcmain(int i);
};
 
struct ObjAndParam
{
  primer* obj;
  int param;
};
 
static void ThreadFun(void* data)
{
  ObjAndParam* objAndParam = static_cast<ObjAndParam*>(data);
  objAndParam->obj->funcmain(objAndParam->param);
}
 
 
Простейший вариант:
Через data нужно передать как-то объект и параметры для вызова.
Значит перед вызовом нужно создать объект ObjAndParam и посетить
в него нужные данные.
Но дальше начинаются сложности.
Если мы отдаим указатель на объект на стеке - значит нужно
как-то гарантировать, что ThreadFun вызовытся до разрушения
этого объекта. Если его создавать динамически, то нужно
как-то гарантированно его удалять. + не забываем о том,
что объект пример должнен быть живым в момент вызова
метода из другого потока. Добавляем сюда обработку
всяких исключений и ошибок для надежной работы, добавляем
возможность это делать для объектов любых типов, для вызова
любых методов с любым (ну даже с ограниченным) количеством
аргументов любых типов - получаем хитрую шаблонную магию
и всякие другие фокусы для надежной работы. Осознаем что это
все достаточно сложно и возвращаемся к выбору какого-нибудь
готового решения.
Bretbas
22 / 17 / 1
Регистрация: 05.08.2013
Сообщений: 466
Завершенные тесты: 1
14.01.2014, 01:10  [ТС]     Статический метод как точка входа в поток - как избавиться #17
Готового решения вы имеете ввиду библиотеку типа <thread>?
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
14.01.2014, 11:15     Статический метод как точка входа в поток - как избавиться #18
да.
Bretbas
22 / 17 / 1
Регистрация: 05.08.2013
Сообщений: 466
Завершенные тесты: 1
19.01.2014, 01:22  [ТС]     Статический метод как точка входа в поток - как избавиться #19
Я отказался то этой библиотеки по той причине,потому что там нет таких функций как приостановить поток и возобновить его(ResumeThread(...) к примеру) как на винапи))
Если вы опровергнете мой слова,или подскажете какое-нибудь подобие этих функций,то я буду очень благодарен и у меня будут мысли о том,чтобы вернуться к этой библиотеки))
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
19.01.2014, 12:48     Статический метод как точка входа в поток - как избавиться
Еще ссылки по теме:

C++ Точка входа в dll в Linux
Как передать нестатическое поле в статический метод класса? C++
C++ Как правильно объявить статический метод

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
19.01.2014, 12:48     Статический метод как точка входа в поток - как избавиться #20
похоже что новый стандарт вам доступен и вы сможете вот такой пример скомпилять:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include <functional>
#include <memory>
#include <string>
#include <iostream>
 
//////////////////////////////////////////////////////
// аналог апишной функции. считаем что она запускает
// переданную функцию в отдельном потоке
typedef void (ThreadFuncPtr)(void*);
void RunThread(ThreadFuncPtr threadFunc, void* param)
{
  threadFunc(param);
}
//////////////////////////////////////////////////////
 
// наш класс помошник
class RunThreadHelper
{
  // если новый стандарт недоступен, то
  // этой штуке есть альтернатива:
  // абстрактный класс с одной функцией.
  // но std::function - удобнее.
  typedef std::function<void ()> Operation;
 
public:
  static void Run(Operation operation)
  {
    // когда и как освобождать этот op - придумайте сами.
    // в простейшем случае - в ThreadFunction если все пошло хорошо.
    Operation* op = new Operation(std::move(operation));
    RunThread(&RunThreadHelper::ThreadFunction, op);
  }
 
private:
  static void ThreadFunction(void* param)
  {
    std::unique_ptr<Operation> op(static_cast<Operation*>(param));
    (*op)();
  };
};
 
 
void FreeFunction1()
{
  std::cout << "FreeFunction1" << std::endl;
}
 
void FreeFunction2(int param)
{
  std::cout << "FreeFunction2: param = " << param << std::endl;
}
 
void FreeFunction3(int param1, const std::string& param2)
{
  std::cout << "FreeFunction3: param1 = " << param1 << "; param2 = " << param2 << std::endl;
}
 
class Test
{
  std::string m_name;
 
public:
  Test(const std::string& name)
    : m_name(name)
  {
  }
 
  void Function1()
  {
    std::cout << "Test::Function1: m_name = " << m_name << std::endl;
  }
 
  void Function2(int param)
  {
    std::cout << "Test::Function2: m_name = " << m_name << "; param = " << param << std::endl;
  }
 
  void Function3(int param1, const std::string& param2)
  {
    std::cout << "Test::Function3: m_name = " << m_name << "; param1 = " << param1 << "; param2 = " << param2 << std::endl;
  }
};
 
 
int main()
{
  Test test1("test1");
  Test test2("test1");
 
  RunThreadHelper::Run(&FreeFunction1);
 
  RunThreadHelper::Run(std::bind(&FreeFunction2, 2));
  RunThreadHelper::Run([] { FreeFunction2(22); });
  RunThreadHelper::Run(std::bind(&Test::Function1, &test1));
  RunThreadHelper::Run(std::bind(&Test::Function2, &test1, 2));
  RunThreadHelper::Run(std::bind(&Test::Function3, &test1, 2, "x"));
 
  RunThreadHelper::Run(std::bind(&FreeFunction3, 3, "x"));
  RunThreadHelper::Run([] { FreeFunction3(33, "xx"); });
  RunThreadHelper::Run([&test2] { test2.Function1(); });
  RunThreadHelper::Run([&test2] { test2.Function2(2); });
  RunThreadHelper::Run([&test2] { test2.Function3(22, "xx"); });
 
  return 0;
}
Добавлено через 7 минут
C++
1
2
3
4
5
6
7
8
  static void ThreadFunction(void* param)
  {
    std::unique_ptr<Operation> op(static_cast<Operation*>(param));
    (*op)();
    // до сюда можем не дойти из-за исключения. нужно придумать как его не потерять
    // и донести до вызывающей стороны. какой-нибудь будущий результат из std использовать
    // или еще как-то.
  };
Добавлено через 10 часов 47 минут
на счет станартной библиотеки:
у std::thread есть такие методы:

std::thread::get_id - returns the id of the thread
std::thread::native_handle - returns the underlying implementation-defined thread handle

я сам не пробовал, но похоже на то, что то, что они возвращают можно использовать
в винапишных функциях после соответствующего каста. Т.е. можно зарезьюмить и засаспендить
интересующий поток.
Yandex
Объявления
19.01.2014, 12:48     Статический метод как точка входа в поток - как избавиться
Ответ Создать тему
Опции темы

Текущее время: 06:44. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru