当前位置:   article > 正文

muduo库base源码分析二 (原子性操作AtomicIntegerT类封装)_#if !defined(ndebug) && !defined(google_protobuf_n

#if !defined(ndebug) && !defined(google_protobuf_no_rtti)

为什么需要原子性操作?

我们考虑这样一种场景,两个线程对同一个变量同时x++操作。

x++ 在计算机的步骤:从内存中读取x的值到寄存器中,对寄存器加1,再把新值写回x所处的内存地址。

假设有如下时序图

两个线程运行结束后,x等于11,正确应该是12,那要得出正确的结果,有两个方法:

第一种是锁:在X++ 之前加一把锁,加完解锁。这样就可以保证在同一时刻只有一个线程进入临界区域,对X进行读的操作,写的操作,当一个线程进入这个临界区域的时候,其他线程就不能访问这个临界区的资源,只能等到占用的线程unlook 的时候才能进入。多个线程访问资源的时候势必会发生锁竞争。锁竞争是高性能服务器四大杀手之一,我们应该尽可能的减少锁的使用。原子性操作可以实现这一目标。

第二种原子操作:原子性操作可以把X++的3步骤看成一个整体。现代的CPU都提供了原子性操作的相关指令。

这些是GCC 提供的原子性操作,当然前提是CPU支持原子性操作的指令。

  1. // 原子自增操作
  2. type __sync_fetch_and_add (type *ptr, type value)
  3. // 原子比较和交换(设置)操作
  4. type __sync_val_compare_and_swap (type *ptr, type oldval type newval)
  5. bool __sync_bool_compare_and_swap (type *ptr, type oldval type newval)
  6. // 原子赋值操作
  7. type __sync_lock_test_and_set (type *ptr, type value)
  8. 使用这些原子性操作,编译的时候需要加-march=cpu-type

 -march=native 让GCC自动检测CPU是什么类型的体系结构

noncopyable 不可拷贝的实现就是将拷贝构造和赋值运算符做成私有的。

  1. #ifndef MUDUO_BASE_ATOMIC_H
  2. #define MUDUO_BASE_ATOMIC_H
  3. #include <boost/noncopyable.hpp>
  4. #include <stdint.h>
  5. namespace muduo
  6. {
  7. namespace detail
  8. {
  9. template<typename T>
  10. class AtomicIntegerT : boost::noncopyable
  11. {
  12. public:
  13. AtomicIntegerT()
  14. : value_(0)
  15. {
  16. }
  17. // uncomment if you need copying and assignment
  18. //
  19. // AtomicIntegerT(const AtomicIntegerT& that)
  20. // : value_(that.get())
  21. // {}
  22. //
  23. // AtomicIntegerT& operator=(const AtomicIntegerT& that)
  24. // {
  25. // getAndSet(that.get());
  26. // return *this;
  27. // }
  28. // 原子获取值
  29. T get()
  30. {
  31. return __sync_val_compare_and_swap(&value_, 0, 0);
  32. }
  33. T getAndAdd(T x)
  34. {
  35. return __sync_fetch_and_add(&value_, x);
  36. }
  37. T addAndGet(T x)
  38. {
  39. return getAndAdd(x) + x;
  40. }
  41. T incrementAndGet()
  42. {
  43. return addAndGet(1);
  44. }
  45. T decrementAndGet()
  46. {
  47. return addAndGet(-1);
  48. }
  49. void add(T x)
  50. {
  51. getAndAdd(x);
  52. }
  53. void increment()
  54. {
  55. incrementAndGet();
  56. }
  57. void decrement()
  58. {
  59. decrementAndGet();
  60. }
  61. T getAndSet(T newValue)
  62. {
  63. return __sync_lock_test_and_set(&value_, newValue);
  64. }
  65. private:
  66. volatile T value_;
  67. };
  68. }
  69. typedef detail::AtomicIntegerT<int32_t> AtomicInt32;
  70. typedef detail::AtomicIntegerT<int64_t> AtomicInt64;
  71. }
  72. #endif // MUDUO_BASE_ATOMIC_H

这些接口是模仿java 原子性操作类来写的.

原子性操作实现无锁队列:

无锁队列的实现 | 酷 壳 - CoolShell
 

volatile的作用: 作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值。简单地说就是防止编译器对代码进行优化

当要求使用volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,而不是使用保存在寄存器中的备份。即使它前面的指令刚刚从该处读取过数据。而且读取的数据立刻被保存

muduo库中用到的编译器选项,加上编译选项可以使编写的代码质量更高。

-g  生成调试信息

-D 定义一个宏

-Wall 大部分的警告给出提示

-Wextra 给出一些额外的警告

-Werror 当出现警告时转为错误,停止编译

-Wconversion 一些可能改变值的隐式转换,给出警告

-Wno-unused-parameter 函数中出现未使用的参数,不给出警告

-Wold-style-cast C风格的转换,给出警告

-Woverloaded-virtual 如果函数的声明隐藏住了基类的虚函数,就给出警告

-Wpointer-arith 对函数指针和void*无类型指针做算数操作时,给出警告

-Wshadow 当局部变量遮盖住了另一个局部变量,或者全局变量时,给出警告

-Wwrite-strings 规定字符串常量的类型是const char[length],因此把这样的常量赋值给non-const char * 指针将产出警告,这些警告可以帮助在编译期间企图写入字符串常量的代码。

-march=native 指定cpu体系结构为本地平台。GCC是一个交叉编译器,它能够生成其他平台运行的代码,比如生成arm 平台的代码 。

Types.h

typedef __gnu_cxx::__sso_string string; 短字符优化

阅读代码的时候可以看到发生了隐式转换

  1. template<typename To, typename From>
  2. inline To implicit_cast(From const &f) {
  3. return f;
  4. }

使用 static_cast 向下转型, 不依赖RTTI 机制向下转型。 

  1. template<typename To, typename From> // use like this: down_cast<T*>(foo);
  2. inline To down_cast(From* f) { // so we only accept pointers
  3. // Ensures that To is a sub-type of From *. This test is here only
  4. // for compile-time type checking, and has no overhead in an
  5. // optimized build at run-time, as it will be optimized away
  6. // completely.
  7. if (false) {
  8. implicit_cast<From*, To>(0);
  9. }
  10. #if !defined(NDEBUG) && !defined(GOOGLE_PROTOBUF_NO_RTTI)
  11. assert(f == NULL || dynamic_cast<To>(f) != NULL); // RTTI: debug mode only!
  12. #endif
  13. return static_cast<To>(f);
  14. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/48484
推荐阅读
相关标签
  

闽ICP备14008679号