从另一个线程调用 socket->native_handle()
Calling socket->native_handle() from another thread
我正在编写一些 asio/tcp 服务器,并希望将本机套接字描述符映射到 TCP 会话标识符。
我正在写 id getter 像:
inline int get_session_id() { return socket_.native_handle(); }
并从第二个(数据包调度线程)线程调用,如:
cout << session_shared_ptr->get_session_id() << endl;
并且它只在第一次写入有效 ID,所以我猜我的实现中有什么地方不好。
谁能告诉我我哪里做错了?
首先,我觉得使用本机句柄作为会话 ID 是一个非常糟糕的主意。
您不仅选择了一个实现定义的后门,而且还选择了一个不可移植的后门 - 因此您的代码可能会跨平台获得不同的语义。
请记住,这些是抽象的基础句柄。抽象存在是有原因的!谁知道,如果您的网络重新连接,本机句柄可能会改变。没有任何地方记载您可以保留句柄并依靠它来识别 API 对象。
当然,当你做多线程时,你必须记住你在线程时总是做的一切:
- 同步对共享状态和资源的访问
- 协调此类对象的生命周期
- 在执行上述操作时防止饥饿和dead/soft锁定
现在,你不谈论同步措施,所以你有一个数据竞争:
Distinct objects: Safe.
Shared objects: Unsafe.
标准将数据竞争指定为Undefined Behaviour;任何事情都可能发生。你可以庆幸你的房子没有被烧毁。然而
总而言之:只需使用可靠的 ID。生成 UUID 并将其存储在会话中。如果您知道不以平等方式移动会话,请使用 C++ 对象标识(即 地址)进行标识。
如果出于某些有用的原因必须从另一个线程访问套接字,请提供同步(互斥 - 互斥,或通过发布到会话链的方式)。
我正在编写一些 asio/tcp 服务器,并希望将本机套接字描述符映射到 TCP 会话标识符。 我正在写 id getter 像:
inline int get_session_id() { return socket_.native_handle(); }
并从第二个(数据包调度线程)线程调用,如:
cout << session_shared_ptr->get_session_id() << endl;
并且它只在第一次写入有效 ID,所以我猜我的实现中有什么地方不好。
谁能告诉我我哪里做错了?
首先,我觉得使用本机句柄作为会话 ID 是一个非常糟糕的主意。
您不仅选择了一个实现定义的后门,而且还选择了一个不可移植的后门 - 因此您的代码可能会跨平台获得不同的语义。
请记住,这些是抽象的基础句柄。抽象存在是有原因的!谁知道,如果您的网络重新连接,本机句柄可能会改变。没有任何地方记载您可以保留句柄并依靠它来识别 API 对象。
当然,当你做多线程时,你必须记住你在线程时总是做的一切:
- 同步对共享状态和资源的访问
- 协调此类对象的生命周期
- 在执行上述操作时防止饥饿和dead/soft锁定
现在,你不谈论同步措施,所以你有一个数据竞争:
Distinct objects: Safe.
Shared objects: Unsafe.
标准将数据竞争指定为Undefined Behaviour;任何事情都可能发生。你可以庆幸你的房子没有被烧毁。然而
总而言之:只需使用可靠的 ID。生成 UUID 并将其存储在会话中。如果您知道不以平等方式移动会话,请使用 C++ 对象标识(即 地址)进行标识。
如果出于某些有用的原因必须从另一个线程访问套接字,请提供同步(互斥 - 互斥,或通过发布到会话链的方式)。