C++跨子类的互斥体和 STL 列表

发布于 2024-09-01 13:35:09 字数 5838 浏览 3 评论 0原文

我目前正在使用 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&) [其中 _Tp = ServerUser, _Alloc = std::分配器]â /usr/include/c++/4.4/bits/stl_list.h:1407: 从 âvoid std::list<_Tp 实例化, _Alloc>::_M_insert(std::_List_iterator<_Tp>, const _Tp&) [其中 _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++ 来处理这种规模的项目或互斥体,所以请简单一点:)

首先,任何人都可以告诉我为什么上述情况会导致编译器错误?

其次,有人可以建议一种更好的方法来存储我所需的信息吗?请记住,每当连接出现或消失时,我都需要更新此信息,并且它需要对整个服务器是全局的。

I am currently writing a multi-threaded C++ server using Poco and am now at the point where I need to be keeping information on which users are connected, how many connections each of them have, and given it is a proxy server, where each of those connections are proxying through to.

For this purpose I have created a ServerStats class which holds an STL list of ServerUser objects. The ServerStats class includes functions which can add and remove objects from the list as well as find a user in the list an return a pointer to them so I can access member functions within any given ServerUser object in the list.

The ServerUser class contains an STL list of ServerConnection objects and much like the ServerStats class it contains functions to add, remove and find elements within this list.

Now all of the above is working but I am now trying to make it threadsafe.

I have defined a Poco::FastMutex within the ServerStats class and can lock/unlock this in the appropriate places so that STL containers are not modified at the same time as being searched for example. I am however having an issue setting up mutexes within the ServerUser class and am getting the following compiler error:

/root/poco/Foundation/include/Poco/Mutex.h:
In copy constructor
âServerUser::ServerUser(const
ServerUser&)â:
src/SocksServer.cpp:185:
instantiated from âvoid
__gnu_cxx::new_allocator<_Tp>::construct(_Tp*,
const _Tp&) [with _Tp = ServerUser]â
/usr/include/c++/4.4/bits/stl_list.h:464:
instantiated from
â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:
instantiated from â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:
instantiated from âvoid std::list<_Tp,
_Alloc>::push_back(const _Tp&) [with _Tp = ServerUser, _Alloc = std::allocator]â
src/SocksServer.cpp:301:
instantiated from here
/root/poco/Foundation/include/Poco/Mutex.h:164:
error:
âPoco::FastMutex::FastMutex(const
Poco::FastMutex&)â is private
src/SocksServer.cpp:185: error: within
this context In file included from
/usr/include/c++/4.4/x86_64-linux-gnu/bits/c++allocator.h:34,
from /usr/include/c++/4.4/bits/allocator.h:48,
from /usr/include/c++/4.4/string:43,
from /root/poco/Foundation/include/Poco/Bugcheck.h:44,
from /root/poco/Foundation/include/Poco/Foundation.h:147,
from /root/poco/Net/include/Poco/Net/Net.h:45,
from /root/poco/Net/include/Poco/Net/TCPServerParams.h:43,
from src/SocksServer.cpp:1:
/usr/include/c++/4.4/ext/new_allocator.h:
In member function âvoid
__gnu_cxx::new_allocator<_Tp>::construct(_Tp*,
const _Tp&) [with _Tp = ServerUser]â:
/usr/include/c++/4.4/ext/new_allocator.h:105:
note: synthesized method
âServerUser::ServerUser(const
ServerUser&)â first required here
src/SocksServer.cpp: At global scope:
src/SocksServer.cpp:118: warning:
âstd::string getWord(std::string)â
defined but not used make: ***
[/root/poco/SocksServer/obj/Linux/x86_64/debug_shared/SocksServer.o]
Error 1

The code for the ServerStats, ServerUser and ServerConnection classes is below:

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;
};

Now I have never used C++ for a project of this size or mutexes for that matter so go easy please :)

Firstly, can anyone tell me why the above is causing a compiler error?

Secondly, can anyone suggest a better way of storing the information I require? Bear in mind that I need to update this info whenever connections come or go and it needs to be global to the whole server.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

白首有我共你 2024-09-08 13:35:09

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

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

The problem is that FastMutex isn't copyable, and consequently ServerUser isn't copyable. When you insert objects into an STL container, they have to be copied. I think you will have to change the design of your classes.

Also, you have to be really careful with returning pointers to objects which are stored in an STL container, because they can become invalid due to objects being reshuffled as you insert and remove things from the container.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文