C ++ Mutexes和STL列表跨子类

时间:2010-05-12 08:29:09

标签: c++ multithreading stl mutex poco

我目前正在使用Poco编写一个多线程C ++服务器,现在我需要保留有关哪些用户连接的信息,每个用户有多少连接,并且它是一个代理服务器,其中每个连接都代理到。

为此,我创建了一个ServerStats类,它包含一个ServerUser对象的STL列表。 ServerStats类包括可以在列表中添加和删除对象的函数,以及在列表中查找用户返回指向它们的指针,以便我可以访问列表中任何给定ServerUser对象中的成员函数。

ServerUser类包含ServerConnection对象的STL列表,很像ServerStats类,它包含添加,删除和查找此列表中元素的函数。

现在所有这些都在起作用,但我现在正试图让它成为线程安全的。

我在ServerStats类中定义了一个Poco :: FastMutex,并且可以在适当的位置锁定/解锁它,以便例如在搜索的同时不修改STL容器。但是,我在ServerUser类中设置互斥锁时出现问题,并且收到以下编译器错误:

  

/root/poco/Foundation/include/Poco/Mutex.h:   在复制构造函数中   âServerUser:: ServerUser(常量   ServerUser和放大器;)A:   SRC / SocksServer.cpp:185:
  从void中实例化   __gnu_cxx :: new_allocator< _TP> ::构建体(_TP *,   const _Tp&)[with _Tp = ServerUser]â   /usr/include/c++/4.4/bits/stl_list.h:464:   实例化   âstd:: _ List_node< _Tp> * std :: list< _Tp,   _Alloc> :: _ M_create_node(const _Tp&)[with _Tp = ServerUser,_Alloc =   的std ::分配器]答   /usr/include/c++/4.4/bits/stl_list.h:1407:   从voidstd :: list< _Tp实例化,   _Alloc> :: _ M_insert(std :: _ List_iterator< _Tp>,const _Tp&)[with _Tp = ServerUser,   _Alloc = std :: allocator]â/ usr /include/c++/4.4/bits/stl_list.h:920:   从voidstd :: list< _Tp实例化,   _Alloc> :: push_back(const _Tp&)[with _Tp = ServerUser,_Alloc = std :: allocator]â   SRC / SocksServer.cpp:301:
  从这里实例化   /root/poco/Foundation/include/Poco/Mutex.h:164:   错误:   âPoco:: FastMutex :: FastMutex(常量   Poco :: FastMutex&)是私人的   src / SocksServer.cpp:185:错误:内部   此上下文包含在文件中   /usr/include/c++/4.4/x86_64-linux-gnu/bits/c++allocator.h:34,                    来自/usr/include/c++/4.4/bits/allocator.h:48,                    来自/usr/include/c++/4.4/string:43,                    来自/root/poco/Foundation/include/Poco/Bugcheck.h:44,                    来自/root/poco/Foundation/include/Poco/Foundation.h:147,                    来自/root/poco/Net/include/Poco/Net/Net.h:45,                    来自/root/poco/Net/include/Poco/Net/TCPServerParams.h:43,                    来自src / SocksServer.cpp:1:   /usr/include/c++/4.4/ext/new_allocator.h:   在成员函数中   __gnu_cxx :: new_allocator< _TP> ::构建体(_TP *,   const _Tp&)[with _Tp = ServerUser]â:   /usr/include/c++/4.4/ext/new_allocator.h:105:   注意:合成方法   âServerUser:: ServerUser(常量   ServerUser&) - 首先需要这里   src / SocksServer.cpp:在全局范围内:   src / SocksServer.cpp:118:警告:   âstd:: string getWord(std :: string)â   定义但未使用make:***   [/root/poco/SocksServer/obj/Linux/x86_64/debug_shared/SocksServer.o]   错误1

ServerStats,ServerUser和ServerConnection类的代码如下:

class ServerConnection
{
public:
    bool continue_connection;
    int bytes_in;
    int bytes_out;
    string source_address;
    string destination_address;

    ServerConnection()
    {
        continue_connection = true;
    }

    ~ServerConnection()
    {
    }
};

class ServerUser
{
public:
    string username;
    int connection_count;
    string client_ip;

    ServerUser()
    {
    }

    ~ServerUser()
    {
    }

    ServerConnection* addConnection(string source_address, string destination_address)
    {
        //FastMutex::ScopedLock lock(_connection_mutex);

        ServerConnection connection;
        connection.source_address = source_address;
        connection.destination_address = destination_address;
        client_ip = getWord(source_address, ":");

        _connections.push_back(connection);
        connection_count++;

        return &_connections.back();
    }

    void removeConnection(string source_address)
    {
        //FastMutex::ScopedLock lock(_connection_mutex);

        for(list<ServerConnection>::iterator it = _connections.begin(); it != _connections.end(); it++)
        {
            if(it->source_address == source_address)
            {
                it = _connections.erase(it);
                connection_count--;
            }
        }
    }

    void disconnect()
    {    
        //FastMutex::ScopedLock lock(_connection_mutex);

        for(list<ServerConnection>::iterator it = _connections.begin(); it != _connections.end(); it++)
        {
            it->continue_connection = false;
        }
    }

    list<ServerConnection>* getConnections()
    {
        return &_connections;
    }

private:
    list<ServerConnection> _connections;

    //UNCOMMENTING THIS LINE BREAKS IT:
    //mutable FastMutex _connection_mutex;
};

class ServerStats
{
public:
    int current_users;

ServerStats()
{
    current_users = 0;
}

~ServerStats()
{
}

ServerUser* addUser(string username)
{
    FastMutex::ScopedLock lock(_user_mutex);

    for(list<ServerUser>::iterator it = _users.begin(); it != _users.end(); it++)
    {
        if(it->username == username)
        {
            return &(*it);
        }
    }

    ServerUser newUser;
    newUser.username = username;
    _users.push_back(newUser);
    current_users++;

    return &_users.back();
}

void removeUser(string username)
{
    FastMutex::ScopedLock lock(_user_mutex);

    for(list<ServerUser>::iterator it = _users.begin(); it != _users.end(); it++)
    {
        if(it->username == username)
        {
            _users.erase(it);
            current_users--;
            break;
        }
    }
}

ServerUser* getUser(string username)
{
    FastMutex::ScopedLock lock(_user_mutex);

    for(list<ServerUser>::iterator it = _users.begin(); it != _users.end(); it++)
    {
        if(it->username == username)
        {
            return &(*it);
        }
    }
    return NULL;
}

private:
    list<ServerUser> _users;
    mutable FastMutex _user_mutex;
};

现在我从来没有将C ++用于这种大小的项目或互斥体,所以请轻松一下:)

首先,任何人都可以告诉我为什么上面的代码会导致编译错误吗?

其次,有人能建议更好的方式存储我需要的信息吗?请记住,每当连接进入或结束时我都需要更新此信息,并且它需要对整个服务器是全局的。

1 个答案:

答案 0 :(得分:1)

问题是FastMutex不可复制,因此ServerUser不可复制。将对象插入STL容器时,必须复制它们。我想你必须改变你的课程设计。

此外,您必须非常小心地返回指向存储在STL容器中的对象的指针,因为当您从容器中插入和移除内容时,由于对象被重新洗牌,它们可能会变得无效。

相关问题