【问题标题】:C++ Mutexes and STL Lists Across Subclasses跨子类的 C++ 互斥锁和 STL 列表
【发布时间】:2011-02-18 12:19:57
【问题描述】:

我目前正在使用 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(const 服务器用户&)â: src/SocksServer.cpp:185:
从 âvoid 实例化 __gnu_cxx::new_allocator<_tp>::construct(_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::allocator]â /usr/include/c++/4.4/bits/stl_list.h:1407: 从 âvoid std::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: 从 âvoid std::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(const 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>::construct(_Tp*, const _Tp&) [with _Tp = ServerUser]â: /usr/include/c++/4.4/ext/new_allocator.h:105: 注:合成法 âServerUser::ServerUser(const 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++ 用于这种规模的项目或互斥体,所以请放轻松:)

首先,谁能告诉我为什么上面会导致编译器错误?

其次,谁能建议一种更好的方式来存储我需要的信息?请记住,每当连接来或去时,我都需要更新此信息,并且它需要对整个服务器是全局的。

【问题讨论】:

    标签: c++ multithreading stl mutex poco


    【解决方案1】:

    问题在于 FastMutex 不可复制,因此 ServerUser 不可复制。当您将对象插入 STL 容器时,它们必须被复制。我认为您将不得不更改课程的设计。

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

    【讨论】:

    • @Genesis:您可能会考虑将互斥锁设为静态成员,除非有机会让您的线程串行化。
    • 他可以将其对象的(智能)指针存储在容器中,例如 boost/tr1::shared_ptr
    • @Nikko: 是的,shared_ptr 会起作用,但它是否是一个好的选择必须结合这些类将如何与系统的其余部分一起工作(以及返回指针的问题)来考虑我提到的应该同时考虑)。我对其余代码的了解还不够,无法在这里提出解决方案。
    • 谢谢,现在说得通了。重新列表:分配元素后,列表元素的内存地址是否不是静态的?我的理解是,每当从列表中添加或删除元素时,它们两侧的元素都会修改其指针以指向新元素。但是我意识到,对于元素彼此相邻并且在进行任何更改时需要重新洗牌的向量之类的东西,情况并非如此。
    • @Genesis:您对列表的看法是正确的,但对我来说,使用指针仍然感觉像是依赖于实现细节。 STL 通常用迭代器代替指针,那么为什么不返回迭代器而不是指针呢?
    猜你喜欢
    • 2018-05-23
    • 1970-01-01
    • 2013-06-06
    • 2021-02-03
    • 2010-12-17
    • 2022-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多