2010-05-12 2 views
0

현재 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++을 사용 해본 적이 없으므로 다음과 같이하십시오.

첫째로, 위의 원인으로 컴파일러 오류가 발생하는 이유는 무엇입니까?

둘째, 누구나 내가 필요한 정보를 저장하는 더 나은 방법을 제안 할 수 있습니까? 연결을 시도하거나 올 때마다이 정보를 업데이트해야하며 전체 서버에 대해 전역 적이어야한다는 점을 명심하십시오.

답변

1

FastMutex는 복사 할 수 없으므로 ServerUser는 복사 할 수 없습니다. 개체를 STL 컨테이너에 삽입 할 때 개체를 복사해야합니다. 나는 당신이 수업의 디자인을 바꾸어야한다고 생각합니다.

또한 STL 컨테이너에 저장된 개체에 대한 포인터를 반환 할 때는 컨테이너에 물건을 삽입하거나 제거 할 때 개체가 재편성되어 유효하지 않을 수 있으므로 실제로주의해야합니다.

+0

@ Genesis : 스레드를 직렬로 만들 기회가 없으면 뮤텍스를 정적 ​​멤버로 만드는 것을 고려할 수 있습니다. – stefaanv

+0

그는 boost/tr1 :: shared_ptr (예 : – Nikko

+0

)과 같이 객체의 포인터를 컨테이너에 스마트하게 저장할 수 있습니다. @Nikko : 예, shared_ptr이 작동하지만 좋은 선택인지 여부는 이러한 방식과 함께 고려해야합니다. 클래스는 시스템의 나머지 부분과 함께 작동 할 것입니다 (그리고 언급 한 포인터를 반환하는 문제는 동시에 고려해야합니다). 여기에 해결책을 제안하는 나머지 코드에 대해서는 충분히 알지 못합니다. –