Re[12]: других вариантов нет
От: ssm Россия  
Дата: 10.11.04 09:43
Оценка:
Здравствуйте, .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;
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.