我有一个这样定义的类:这不完全,可能不会编译。
class Server
{
public:
Server();
~Server();
class Worker
{
public:
Worker(Server& server) : _server(server) { }
~Worker() { }
void Run() { }
void Stop() { }
private:
Server& _server;
}
void Run()
{
while(true) {
// do work
}
}
void Stop()
{
// How do I stop the thread?
}
private:
std::vector<Worker> _workers;
};
我的问题是,如何初始化在名为Server的外部类中传递的workers数组。
我想要的是工作线程的向量。每个工作线程都有自己的状态,但可以访问其他一些共享数据(未显示)。另外,我如何创建线程。它们应该在首次创建类对象时创建还是在thread_group外部创建。
另外,我如何干净安全地关闭线程?
编辑:
似乎我可以像这样初始化Worker:
Server::Server(int thread_count)
: _workers(thread_count), Worker(*this)), _thread_count(thread_count) { }
我目前正在Server :: Run中执行此操作来创建线程。
boost::thread_group _threads; // a Server member variable
Server::Run(){
for (int i = 0; i < _thread_count; i++)
_threads.create_thread(boost::bind(&Server::Worker::Run, _workers(i)));
// main thread.
while(1) {
// Do stuff
}
_threads.join_all();
}
有没有人发现这有什么问题? 安全关机怎么样?
编辑: 我发现它的一个问题是Worker对象似乎没有被构造! 哎呀。是的,我需要在Worker类上使用复制构造函数。
但奇怪的是,创建线程会导致多次调用Worker的复制构造函数。
答案 0 :(得分:1)
我用纯WINAPI做过,看看:
#include <stdio.h>
#include <conio.h>
#include <windows.h>
#include <vector>
using namespace std;
class Server
{
public:
class Worker
{
int m_id;
DWORD m_threadId;
HANDLE m_threadHandle;
bool m_active;
friend Server;
public:
Worker (int id)
{
m_id = id;
m_threadId = 0;
m_threadHandle = 0;
m_active = true;
}
static DWORD WINAPI Run (LPVOID lpParam)
{
Worker* p = (Worker*) lpParam; // it's needed because of the static modifier
while (p->m_active)
{
printf ("I'm a thread #%i\n", p->m_id);
Sleep (1000);
}
return 0;
}
void Stop ()
{
m_active = false;
}
};
Server ()
{
m_workers = new vector <Worker*> ();
m_count = 0;
}
~Server ()
{
delete m_workers;
}
void Run ()
{
puts ("Server is run");
}
void Stop ()
{
while (m_count > 0)
RemoveWorker ();
puts ("Server has been stopped");
}
void AddWorker ()
{
HANDLE h;
DWORD threadId;
Worker* n = new Worker (m_count ++);
m_workers->push_back (n);
h = CreateThread (NULL, 0, Worker::Run, (VOID*) n, CREATE_SUSPENDED, &threadId);
n->m_threadHandle = h;
n->m_threadId = threadId;
ResumeThread (h);
}
void RemoveWorker ()
{
HANDLE h;
DWORD threadId;
if (m_count <= 0)
return;
Worker* n = m_workers->at (m_count - 1);
m_workers->pop_back ();
n->Stop ();
TerminateThread (n->m_threadHandle, 0);
m_count --;
delete n;
}
private:
int m_count;
vector <Worker*>* m_workers;
};
int main (void)
{
Server a;
int com = 1;
a.Run ();
while (com)
{
if (kbhit ())
{
switch (getch ())
{
case 27: // escape key code
com = 0;
break;
case 'a': // add worker
a.AddWorker ();
break;
case 'r': // remove worker
a.RemoveWorker ();
break;
}
}
}
a.Stop ();
return 0;
}
这里没有同步代码,因为我没有时间去做...但我希望它会帮助你=)
答案 1 :(得分:0)
你有没有看过boost asio?看起来它可能非常适合您要做的事情。此外,您可以从许多线程调用boost asio的io_service运行(类似于您的Run方法),即您可以在许多线程中处理您的IO。对于基于asio的线程池,也感兴趣的是http://think-async.com/Asio/Recipes。
看看asio示例。也许他们提供了另一种处理你想要做的事情的方法。 ESP。看看如何完成干净的关闭。