内部类和初始化
我有一个像这样定义的类:这不是全部完成,可能不会编译。内部类和初始化
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;
};
我的问题是,我如何初始化传入名为服务器的外部类中的工人数组。
我想要的是工作线程的向量。每个工作线程都有自己的状态,但可以访问其他一些共享数据(未显示)。另外,我如何创建线程。它们应该在第一次创建类对象时创建,还是从thread_group的外部创建。
另外,我该如何干净而安全地关闭线程?
编辑:
看来,我可以这样初始化工作人员:
Server::Server(int thread_count)
: _workers(thread_count), Worker(*this)), _thread_count(thread_count) { }
而且目前我在做这在服务器::运行以创建线程。
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();
}
有没有人看到这个问题? 安全关机如何?
编辑: 我发现它的一个问题是,工人对象似乎并不构建! oops。是的,他们确实需要Worker类的复制构造函数。
但奇怪的是,创建线程会导致多次调用Worker的复制构造函数。
你看过boost asio吗?它看起来可能很适合你想要做的事情。另外,你可以从许多线程调用boost asio的io_service的运行(类似于你的Run方法),即你可以在很多线程中处理你的IO。基于asio的线程池也可能是http://think-async.com/Asio/Recipes。
看看asio的例子。也许他们提供了另一种处理你想要做的事情的方法。 ESP。看看如何完成干净的关闭。
是的,它实际上使用ASIO! – Matt 2010-11-09 11:05:41
我与纯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;
}
没有同步码在这里,因为我没有时间enougth做到这一点......但我希望它会帮助你=)
对于同步,您可以使用(例如)关键部分 – 2010-11-10 08:00:15
输入队列从哪里来?你想创造多少工人? – 2010-11-09 10:15:46
我已经删除了输入队列。我认为它会让事情混淆。如果我想创建的工作人员数量是可变的并且来自配置文件。 – Matt 2010-11-09 10:20:12
你真的需要在另一个类中定义一个类吗?它只会让我对它不那么可读。 – 2010-11-09 10:25:47