- 论坛徽章:
- 9
|
本帖最后由 wlmqgzm 于 2015-11-10 12:23 编辑
windoze 发表于 2015-11-10 00:28
回复 139# wlmqgzm
在你的“无锁socket”中,我不光看到了shared_ptr,甚至还看到了vector/string……你 ...
vector/string 是无锁的, 这个应该是这样, 一般在多线程**享使用vector/string时, 代码要加锁, 单线程使用不加锁, vector/string内部应该是没有锁的.
我这里使用vector/string都是单线程, 所以, 代码中无锁.
shared_ptr 这个就只是一条 std::shared_ptr<boost::asio::ip::tcp::socket> sp_socket1, 这个选择也是比较犹豫的选择,
最早期的代码是使用原生方式(直接boost::asio::ip::tcp::socket), 在accept和socket块预分配内存一起申请, 后来为了提高抗DOS性能, 修改为使用shared_ptr, 减少DOS检查成功前的处理量
这个只能综合考虑, 如果确实要去掉这个shared_ptr, 也是可以的, 这个也是我曾经纠结的部分, 刚才改回了最早期代码的原生方式.
不愧是牛人啊, 一上来就找到我的纠结点.
shared_ptr这个始终都是要用的, 就是使用量的多少, 最终, 还是为了性能和其他的综合平衡.
在管理线程相关的代码中, 还使用了一些shared_ptr, 用来包装map list等容器, 这些也是现实的选择,
socket线程中, 使用shared_ptr在异步调用接口read_handler/ write_handler中传递数据, 这些都是现实的选择,
代码中所有的shared_ptr全部替换为使用裸指针, 然后全部内存统一在管理线程中申请和释放, 也测试过, 性能只有微弱的提高, 但是, 现代化的C++中, 总感觉不应该出现裸指针这样的东西, 可靠性生疑.
最终, 代码中, 没有采用裸指针, 使用了不少的shared_ptr, 也算无锁吧, 因为:
阅读了shared_ptr代码, linux下默认使用原子量+内存屏障, 没有使用锁(mutex)
while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1,
true, __ATOMIC_ACQ_REL,
__ATOMIC_RELAXED));
-------------------------------------------------------------------------------
_M_release() // nothrow
{
// Be race-detector-friendly. For more info see bits/c++config.
_GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_use_count);
if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, -1) == 1)
{
_GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_use_count);
_M_dispose();
// There must be a memory barrier between dispose() and destroy()
// to ensure that the effects of dispose() are observed in the
// thread that runs destroy().
if (_Mutex_base<_Lp>::_S_need_barriers)
{
_GLIBCXX_READ_MEM_BARRIER;
_GLIBCXX_WRITE_MEM_BARRIER;
}
// Be race-detector-friendly. For more info see bits/c++config.
_GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count);
if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count,
-1) == 1)
{
_GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count);
_M_destroy();
}
}
} |
|