Здравствуйте, .erax, Вы писали:
E>Здравствуйте, ssm, Вы писали:
E>>>... остались операции по работе с очередью.
ssm>>оставь только операции с очередью и убери mtserverClass->Send(...), что бы убедится
E>да, дело в операциях с очередью.
НЕТ, дело НЕ в операциях с очередью. я накалякал ниже простой примерчик, суть которого:
есть сервер, умеющий выполнять асинхронно комманду(Command::execute)
есть 100 клиентов(работают в отдельных потоках), каждый из которых просит сервер асинхронно выполнить 20 комманд. При выполнении примера, загрузка процессора 0-1%, если интерестно поиграй с количеством клиентов и комманд. Все сделано на одной критической секции, для std::queue
#include <algorithm>
#include <iostream>
#include <queue>
#include <atlbase.h>
class Command
{
public:
Command()
{
}
void execute()
{
static int i = 0;
std::cerr << ++i << std::endl;
}
};
class Server
{
public:
Server()
: joined(false)
{
threadHandle.Attach(AtlCreateThread(&Server::run, this));
}
void queueCommand(Command *cmd)
{
cs.Lock();
commands.push(cmd);
cs.Unlock();
}
static DWORD WINAPI run(Server *srv)
{
srv->runLoop();
return 0;
}
void join()
{
joined = true;
::WaitForSingleObject(threadHandle, INFINITE);
}
private:
bool joined;
CHandle threadHandle;
std::queue<Command*> commands;
CComAutoCriticalSection cs;
private:
void runLoop()
{
while (true)
{
if(!commands.empty())
{
Command *cmd = 0;
//extract command
cs.Lock();
if(!commands.empty())
{
cmd = commands.front();
commands.pop();
}
cs.Unlock();
if(cmd)
{
//execute command
cmd->execute();
//delete command
delete cmd;
}
}
else if(joined)
{
break;
}
Sleep(1);
}
}
};
class Client
{
public:
void sendCommand(Server *server)
{
threadHandle.Attach(AtlCreateThread(&Client::run, server));
}
~Client()
{
::WaitForSingleObject(threadHandle, 10);
}
private:
CHandle threadHandle;
static DWORD WINAPI run(Server *server)
{
for(int i = 0; i < 20; ++i)
{
server->queueCommand(new Command());
}
//даем время серверу
Sleep(1);
return 0;
}
};
int main()
{
//создали сервер
Server srv;
//дали время раздуплится потоку сервера
Sleep(100);
//деструкторы клиентов ждут окончания
//своих потоков
{
//кол.во клиентских потоков
const size_t clientCount = 100;
Client clients[clientCount];
//запустить клиентские потоки
std::for_each(
clients, clients + clientCount,
std::bind2nd(std::mem_fun1_ref(&Client::sendCommand), &srv));
}
//ждем пока сервер не обработает все сообщения
srv.join();
return 0;
}