RAII, Berkeley Sockets, and STL Containers

可紊 提交于 2020-01-07 03:12:11

问题


Let me start by stating I am using a GNU C++ compiler that does NOT support move constructors. It only supports the 98 standard.

Given that, I want to write a C++ class that wraps Berkeley style sockets in a simple way that follows RAII. Here is a very simple class:

class SimpleSocket
{
  int m_sockfd;
public:
  SimpleSocket()
  {
    m_sockfd = socket(AF_INET, ...);
  }
  SimpleSocket(const SimpleSocket& other)
  {
    m_sockfd = other.m_sockfd;
  }
  ~SimpleSocket()
  {
    closeSocket();
  }
  void closeSocket()
  {
    if(m_sockfd != -1)
    { 
      close(m_sockfd);
      m_sockfd = -1;
    }
  }
};

Let's say I want to create a whole bunch of these in a STL C++ vector like so.

vector<SimpleSocket> vec_of_sockets;
for(int i = 0 ; i < 10 ; ++i)
{
  SimpleSocket new_sock;
  vec_of_sockets.push_back(new_sock);
}

What I found was that vector uses the copy constructor to move the objects around and then destructing the old sockets. This has the unfortunate side-effect of calling closeSocket() which closes my file descriptor.

I want to follow RAII and close the file descriptor when the object's destructor is called but it makes it where I cannot use it inside of the STL C++ containers. I know that I can update my compiler and implement a move constructor which would fix the problem but I work for a company that does not believe in using anything that is modern. (I'm really frustrated by it but there is nothing I can do about it.)


回答1:


Both Linux and Windows implement reference counting in the kernel/winsock2 level. you could have used a reference counted pointer in your user mode program, but that would waste more memory than you'd think. you can elevate the reference counting you OS already does behind the scenes. here is an example implementation for Linux:

 SimpleSocket(const SimpleSocket& other)
  {
    m_sockfd = dup(other.m_sockfd);
  }

The operating system will increment the reference count of the specified socket and will return a new descriptor in which you can use. do note that when you "copy" a socket this way, both of the sockets will refer to the same underlying socket even if the descriptors are different.




回答2:


If you could use Smart Pointers Boost library, store your class inside a shared_ptr as in:

std::vector<boost::shared_ptr<SimpleSocket>>


来源:https://stackoverflow.com/questions/42281711/raii-berkeley-sockets-and-stl-containers

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!