muduo_base库源码分析(二)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
按照上图的时序,最终得到的x为11,但这显然是错误的,正确的x应该为12。这就体现了原子操作的必要性。

在这里插入图片描述
解释一下上面几个原语:

__sync_fetch_and_add(type *ptr, type value);

函数的返回值是 *ptr(旧值),同时 *ptr=*ptr+value

__sync_val_compare_and_swap(type *ptr, type oldval, type newval);

如果 *ptr不等于oldval,那么直接函数返回 *ptr,结束;
如果 *ptr等于oldval,那么函数返回 *ptr(旧值),同时 *ptr=newval

__sync_lock_test_and_set(type *ptr, type value);

函数的返回值是 *ptr(旧值),同时 *ptr=value
在这里插入图片描述

在这里插入图片描述

Types.h源码

#ifndef MUDUO_BASE_TYPES_H
#define MUDUO_BASE_TYPES_H

#include <stdint.h>
#include <string.h>  // memset
#include <string>

#ifndef NDEBUG
#include <assert.h>
#endif

namespace muduo
{

using std::string;

inline void memZero(void* p, size_t n)
{
  memset(p, 0, n);
}

template<typename To, typename From>
inline To implicit_cast(From const &f)
{
  return f;
}

template<typename To, typename From>     // use like this: down_cast<T*>(foo);
inline To down_cast(From* f)                 
{
#if !defined(NDEBUG) && !defined(GOOGLE_PROTOBUF_NO_RTTI)
  assert(f == NULL || dynamic_cast<To>(f) != NULL);  // RTTI: debug mode only!
#endif
  return static_cast<To>(f);
}

}  // namespace muduo

#endif  // MUDUO_BASE_TYPES_H

针对Types.h,我写了个测试小例子,顺便复习下RTTI:
我觉得这个例子挺好的^^

#include <iostream>
#include "muduo/base/Types.h"
using namespace std;
class B {
public:
        virtual void foo(){}
};
class D :public B {

};
int main() {

        B b_obj;
        D d_obj;

        B*pb = &b_obj;
        D*pd = &d_obj;
        //相比于普通的隐式转换pb=pd;把隐式转换封装成下面这种函数的形式,程序员阅读起来更明显
        pb =muduo:: implicit_cast<B*, D*>(pd);


        B*pb1 = &b_obj;//基类指针指向基类对象
        B*pb2 = &d_obj;//基类指针指向派生类对象
        D*pd1 = dynamic_cast<D*>(pb1);
        if (pd1 == NULL)
        {
                cout <<"下行转换失败" << endl;
        }

        pd1 =muduo:: down_cast<D*>(pb3);//ok

        return 0;
}

linux下结果:
在这里插入图片描述

gcc原子操作

Atomic.h

#ifndef MUDUO_BASE_ATOMIC_H
#define MUDUO_BASE_ATOMIC_H

#include "muduo/base/noncopyable.h"

#include <stdint.h>

namespace muduo
{

namespace detail
{
template<typename T>
class AtomicIntegerT : noncopyable
{
 public:
  AtomicIntegerT()
    : value_(0)
  {
  }


  T get()
  {
    return __sync_val_compare_and_swap(&value_, 0, 0);
  }

  T getAndAdd(T x)
  {
    return __sync_fetch_and_add(&value_, x);
  }

  T addAndGet(T x)
  {
    return getAndAdd(x) + x;
  }

  T incrementAndGet()
  {
    return addAndGet(1);
  }

  T decrementAndGet()
  {
    return addAndGet(-1);
  }

  void add(T x)
  {
    getAndAdd(x);
  }

  void increment()
  {
    incrementAndGet();
  }

  void decrement()
  {
    decrementAndGet();
  }

  T getAndSet(T newValue)
  {
    return __sync_lock_test_and_set(&value_, newValue);
  }

 private:
  volatile T value_;
};
}  

typedef detail::AtomicIntegerT<int32_t> AtomicInt32;//方便创建对象
typedef detail::AtomicIntegerT<int64_t> AtomicInt64;

}  // namespace muduo

#endif  // MUDUO_BASE_ATOMIC_H

测试代码:
Atomic_unittest.cc

#include "muduo/base/Atomic.h"
#include <assert.h>

int main()
{
  {
  muduo::AtomicInt64 a0;
  assert(a0.get() == 0);
  assert(a0.getAndAdd(1) == 0);//函数名字面意思很好理解,先get再add,后面类似
  assert(a0.get() == 1);
  assert(a0.addAndGet(2) == 3);
  assert(a0.get() == 3);
  assert(a0.incrementAndGet() == 4);//先+1再get
  assert(a0.get() == 4);
  a0.increment();
  assert(a0.get() == 5);
  assert(a0.addAndGet(-3) == 2);
  assert(a0.getAndSet(100) == 2);//先get旧值再set新值
  assert(a0.get() == 100);
  }

  {
  muduo::AtomicInt32 a1;
  assert(a1.get() == 0);
  assert(a1.getAndAdd(1) == 0);
  assert(a1.get() == 1);
  assert(a1.addAndGet(2) == 3);
  assert(a1.get() == 3);
  assert(a1.incrementAndGet() == 4);
  assert(a1.get() == 4);
  a1.increment();
  assert(a1.get() == 5);
  assert(a1.addAndGet(-3) == 2);
  assert(a1.getAndSet(100) == 2);
  assert(a1.get() == 100);
  }
}

在这里插入图片描述
没有任何输出说明测试结果没问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值