У меня есть экземпляр класса, динамически созданный (поскольку указатель передается обратно и вперед через интерфейс C), который имеет поток повышения элемента. В функции члена следующий код выполняется:Boost Thread внутри класса не может получить доступ к переменным-членам
_thrd = boost::thread(boost::bind(&cls::thrdProc, this, other vars));
Я знаю следующее: Нить была создана Поскольку процедура нить не является статической функции члена того же класса «это» передается как первый аргумент. Я пробовал это с и без boost :: bind.
Также в этом классе является переменной-членом очереди, которую я написал. Процедура потока создает скрытое окно сообщения, инициализируется библиотека связи, и по мере поступления данных библиотека отправляет сообщение Windows в процедуру сообщения (которая находится в потоке). Процедура сообщения отправляет сообщение в процедуру статического окна, которая перенаправляет ее на функцию-член того же класса с потоком. Получены сообщения и вводится процедура потока. Проблема заключается в том, что очередь не инициализируется (фактически все переменные-члены класса недопустимы). Таким образом, поскольку процедура потока и основной код приложения используют boost :: mutex для защиты данных очереди через какое-то время (зависит от количества пакетов, полученных библиотекой связи), я получаю ошибку времени выполнения на boost::lock_guard
(также попытался boost::scoped_lock
). Это потому, что процедура потока вызывает _queue.push
, которая пытается заблокировать мьютекс, который не инициализирован, так что BOOST_VERIFY
жалуется.
Я прочитал несколько вопросов и примеров, в которых упоминаются аргументы потоков, но аргументы не являются проблемой. Кажется, this
указывает на что-то еще или объект класса-оболочки не существует. Это действительно так, и я могу подтвердить, что исходный указатель действителен.
Есть ли другая проблема с копией, о которой я не знаю? Спасибо заранее!
HEADER FILE
interface language_proxy
{
virtual int connectToQ(int * id) = 0;
virtual int deconnectFromQ(int const id) = 0;
virtual int startDataCollection() = 0;
virtual int stopDataCollection() = 0;
...
};
class CMyThread : public language_proxy
{
public:
CMyThread(com lib args);
int connectToQ(int * id);
int deconnectFromQ(int const id);
int startDataCollection();
int stopDataCollection();
...
protected:
boost::mutex _mutex;
CMyQueue _queue;
boost::thread _thrd;
...
uint thrdProc(com lib args);
};
EXECUTABLE FILE(S)
int CMyThread::startDataCollection()
{
// guard against multiple starts
if(boost::thread:id() == _thrd.get_id())
{
_thrd = boost::thread(boost::bind(&CMyThread::thrdProc, this, member vars for com lib));
}
}
uint CMyThread::thrdProc(com lib args)
{
// create hidden messaging window
WNDCLASSEX wc = { 0 };
// many parameters can be ignored since window will be hidden
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpszClassName = MSG_WND_CLS;
wc.lpfnWndProc = &CMyThread::StaticWndProc;
wc.hInstance = GetModuleHandle(0);
// register the class with Windows
RegisterClassEx(&wc);
// create a window based on the above class parameters
_msg_hwnd = CreateWindowEx
(
0,
wc.lpszClassName,
L"HiddenMessageWindow",
0,
CW_USEDEFAULT,
CW_USEDEFAULT,
0,
0,
HWND_MESSAGE,
0,
0,
this
);
// initialize com lib
// process windows messages
while(true)
{
// process available messages
if(PeekMessage(&msg, _msg_hwnd, 0, 0, PM_REMOVE))
{
// break out of the loop if the quit message is found
if(WM_QUIT == msg.message)
{
printf("Quit message found\n");
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
// throws boost::thread_interrupted if the thread has been interrupted
boost::this_thread::sleep_for(boost::chrono::milliseconds(_msg_loop_dly));
}
}
UnregisterClass(MSG_WND_CLS, GetModuleHandle(0));
}
LRESULT CALLBACK CMyThread::StaticWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CMyThread * pWnd = 0;
try
{
// store class pointer for window being created
if(WM_NCCREATE == uMsg)
{
// use SetWindowLongPtr to be 64-bit compatible (a class pointer will be 64 bits and a long is only 32 bits)
pWnd = (CMyThread *)((LPCREATESTRUCT)lParam)->lpCreateParams;
SetWindowLongPtr(hWnd, GWLP_USERDATA, *reinterpret_cast< LONG_PTR * >(pWnd));
}
// access the class pointer
else
{
pWnd = (CMyThread *)GetWindowLong(hWnd, GWL_USERDATA);
}
// if a class pointer for the window exists, call its procedure
if(pWnd)
{
return(pWnd->WndProc(hWnd, uMsg, wParam, lParam));
}
}
catch(...)
{
int x = 5;
}
// call the default window procedure
return(DefWindowProc(hWnd, uMsg, wParam, lParam));
}
LRESULT CALLBACK CMyThread::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
// when a request to close the window is received, destroy the window
case WM_CLOSE:
{
DestroyWindow(hWnd);
} break;
// when a window is destroyed put a quit message in the queue to stop message processing
case WM_DESTROY:
{
PostQuitMessage(0);
} break;
// handle messages from com library
case UWM_RX_COM_LIB_MSG:
{
// use GetWindowLongPtr to be 64-bit compatible (a class pointer will be 64 bits and a long is only 32 bits)
LONG_PTR lPtr = GetWindowLongPtr(hWnd, GWLP_USERDATA);
CMyThread * pWnd = reinterpret_cast< CMyThread * >(&lPtr);
pWnd->onRx();
} break;
// handle all other cases by default behaviour
default:
{
return(DefWindowProc(hWnd, uMsg, wParam, lParam));
}
}
return(0);
}
void CMyThread::onRx()
{
// extract packet(s) from com library
// add packet(s) to vector
// THIS QUEUE IS UNINITIALIZED!
_queue.push(pkts);
}
int C_Interface_create
(
com lib arguments,
language_proxy ** p
)
{
// instantiate the C++ object through the C interface
language_proxy * tmp_p = new CMyThread(com lib args);
if(tmp_p)
{
*p = tmp_p;
}
return(0);
}
int C_Interface_start_thread(language_proxy * p)
{
p->startDataCollection();
return(0);
}
// actually in a DLL but so you have some idea of what the operation flow is
void main()
{
static language_proxy * s_proxy = 0;
C_Interface_create(1, 2, 3, &s_proxy);
c_Interface_start_thread(s_proxy);
// for debugging, endless loop to allow rx'd packets to be processed and guarantee
// s_proxy is still alive
while(1);
}
wow, пожалуйста, уменьшите длину текста или лучше отформатируйте его, но IMO очень маловероятно, чтобы кто-нибудь прочитал эту стену текста. – Paranaix