현재 Poco를 사용하여 멀티 스레드 C++ 서버를 작성 중이며 어떤 사용자가 연결되었는지, 각 사용자가 얼마나 많은 연결을 갖고 있는지에 대한 정보를 유지해야하는 시점에 있습니다. 그것은 프록시 서버이며, 각각의 연결은 프록시를 통해 프록시됩니다.서브 클래스 간 C++ 뮤텍스 및 STL 목록
이 목적을 위해 ServerUser 개체의 STL 목록을 보유하는 ServerStats 클래스를 만들었습니다. ServerStats 클래스에는 목록에서 개체를 추가 및 제거 할 수있는 기능이 포함되어 있으며 목록의 사용자를 찾아 포인터를 반환하므로 목록의 지정된 ServerUser 개체 내의 멤버 함수에 액세스 할 수 있습니다.
ServerUser 클래스에는 ServerConnection 개체의 STL 목록이 포함되어 있으며이 목록 내의 요소를 추가, 제거 및 찾을 수있는 기능이 포함 된 ServerStats 클래스와 매우 비슷합니다.
이제 위의 모든 작업이 진행되고 있지만 이제 스레드 세이프 (threadafe safe)로 만들려고합니다.
ServerStats 클래스 내에 Poco :: FastMutex를 정의했으며이를 적절한 위치에서 잠 그거나 잠금 해제하여 STL 컨테이너가 검색된 것과 동시에 수정되지 않도록 할 수 있습니다. 나는 그러나 ServerUser 클래스 내에서 뮤텍스를 설정하는 문제를 데 다음과 같은 컴파일러 오류가 점점 오전 :
/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
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;
};
I 그 문제에 대한이 크기 또는 mutexes 프로젝트를 위해 C++을 사용 해본 적이 없으므로 다음과 같이하십시오.
첫째로, 위의 원인으로 컴파일러 오류가 발생하는 이유는 무엇입니까?
둘째, 누구나 내가 필요한 정보를 저장하는 더 나은 방법을 제안 할 수 있습니까? 연결을 시도하거나 올 때마다이 정보를 업데이트해야하며 전체 서버에 대해 전역 적이어야한다는 점을 명심하십시오.
@ Genesis : 스레드를 직렬로 만들 기회가 없으면 뮤텍스를 정적 멤버로 만드는 것을 고려할 수 있습니다. – stefaanv
그는 boost/tr1 :: shared_ptr (예 : – Nikko
)과 같이 객체의 포인터를 컨테이너에 스마트하게 저장할 수 있습니다. @Nikko : 예, shared_ptr이 작동하지만 좋은 선택인지 여부는 이러한 방식과 함께 고려해야합니다. 클래스는 시스템의 나머지 부분과 함께 작동 할 것입니다 (그리고 언급 한 포인터를 반환하는 문제는 동시에 고려해야합니다). 여기에 해결책을 제안하는 나머지 코드에 대해서는 충분히 알지 못합니다. –