C++11 学习笔记(11) std::move 右值引用 初识

std::move

参考链接:
c++ 右值引用 原文
详解C++右值引用
std::move
std::remove_reference
value_categary

例子:
int i = 101;
auto j = std::move(i);

Visual Studio 2013 的源码

其含义是 获取其参数的右值(rvalue)引用, 并转变为另一个 xvalue.

Continue reading

C++11 学习笔记(10) std::atomic i; ++i 前缀自增运算的原子性分析

目前项目中使用到了多线程, 我选择 C++11 std::thread 库实现,
模仿开源的流媒体服务器 crtmpserver 里的 protocol类,
每生成一个实例类, 都会有全局的唯一id.
在整个函数声明周期里, 定义:
static u_int32_t idGlobalGenerator; // 初始化0
即当一个类生成时, 该实例类的私有成员 u_int32_t id_;
在构造函数里初始化 id_ = idGlobalGenerator++;
由于我的开发场景是多线程, 因此 idGlobalGenerator
被声明为:

执行 ++idGlobalGenerator; 操作, 根据文档和语义它是原子性的. 而在这里产生的疑惑是:

u_int32_t id = ++idGlobalGenerator;

该执行是否是原子性, 保证多线程环境下, 赋值的 id都是唯一的值.
于是我在 stackoverflow上直接提了问题(当时没有亲自验证): 链接

Continue reading

C++11 学习笔记(9) 线程与信号 改进2 atomic

本文基于 C++11 学习笔记(7) 线程与信号 添加上了 atomic 支持做的改进:

改进的参考资源:
C++11 atomic 与 mutex 性能比较
stackoverflow 讨论C++11 atomic 与 mutex 速度
介绍 atomic 并发的博客
C++11 atomic memory model
C++11 修复了双重检查锁定问题

引用 wilburding作者的 C++11 atomic memory model文章(http://wilburding.github.io/blog/2013/04/07/c-plus-plus-11-atomic-and-memory-model/) :

C++11 atomic 与 mutex 性能比较 的博客 也提到 使用 std::mutex
直接调用lock unlock 的性能开销比 lock_guard 或者 atomic大的多.

因此针对系列笔记 (7)的代码作了优化:

Continue reading

C++11 学习笔记(8) 使用bind改进 rtmpd iohandler 与 protocol 的绑定关系的思路

rtmpd ( 即 crtmpserver )的 是C++版本的流媒体服务器,
其实现方式与 Java 版本的 red5类似. 源码中有大量的指针互相
注册, 以便每个类都能找到对应的功能类, 做通知功能或者传输数据.
而指针的声明周期又需要作者自己清楚地了解(没有用到 shared_ptr).
也许在 C++11推出后, 可以方便地使用 std::bind 与 std::function
来重新定义类之间的关系, 通过互相的注册函数(包括通知函数).

在 rtmpd 的 docs 文档中有一个 architecture.txt 描述了 rtmpd 的代码结构:

Continue reading

C++11 学习笔记(7) 线程与信号

C++11 stl里推出了线程操作相关的库(根据平台特性使用对应的线程库, eg: pthread in posix):
std::thread
std::condition_variable 条件变量(信号量)
std::mutex 互斥量

现在结合以上提到库以及 std::signal 完成一个小例子:
  1. 定义一个全局工作类, 带有线程成员, 以及线程执行的函数, 在线程函数中定时(chrono库)输出时间.
  2. main thread 中调用 std::signal 注册接收 SIGINT SIGTERM SIGABRT 信号(目的是接收中断信号, 跳出 main thread while true 的loop 循环)
  3. 工作线程开始运行
  4. main thread 在线程创建后进入 while true loop 同样定时输出时间
  5. 因为在命令行终端执行该程序, 需要其停止时, Ctrl-C( or Ctrl-Z in Windows) 中断,
    程序的接收到 SIGTERM 信号 signal 处理的单独线程中将全局的 mainRunning 置为 false,
    并且通知工作线程停止 main thread loop 循环在 mainRunning 为 false 后跳出循环
  6. 程序结束

Continue reading

C++11 学习笔记(6) tuple 与 tie

std::tuple std::tie

在Python语法里会有元组的数据结构, 它与list有所区别.
维基百科的解释:

A tuple is an ordered list of elements. In set theory,
an n-tuple is a sequence of elements, where is a non-negative integer.
There is only one 0-tuple, an empty sequence.
An n-tuple is defined inductively using the construction of an ordered pair

C++11标准正式推出该数据结构, 此时想到的使用场景是函数返回值以 tuple的形式打包返回 n个元素的数据.
在 11标准之前, 如果想获得多个结果值有两种实现方式:
1. 以 struct 或者 class类封装(这个实现在代码维护上又多了一个使用类)
2. 传多个引用的方式, 引用的变量会在函数中修改

而现在, 可以使用 tuple描述的例子:
Continue reading

C++11 学习笔记(5) delegate 模式

delegeate 模式最早接触到是在大四实习ios开发时候.当时使用之后觉得
objc代码写起来很舒服(当时并没有对注册回调函数有清晰的概念)

现在用C++11的 functional 模拟实现 delegate 模式 :)

代码转自cprogramming

[题外话] 工作两年, 对回调函数的理解一次比一次有新的体会.

  • 首先阅读 Redis 的源码, 在C中大量的函数指针其实是注册的回调函数
  • 后来接触了 Lua 脚本(写交互状态的逻辑代码), 发现使用传统的
    面向对象和过程的实现方式 在代码开发上难度和时间会消耗很大又
    因为 Lua 本身支持函数式编程的方式(当时就只懂使用简单的保存
    状态的闭包), 通过项目实践和学习, 异步回调的理解加深, 同时将
    代码逻辑开发的难度降低.
  • 随后 Node.js 流行, 在使用其开发一个小型功能程序中惊奇地发现
    回调的使用与在 Lua项目中的理解是一致的, 更加对自己的工作的
    成果有了自信 :)

C++11 学习笔记(4) 11标准以前模仿 lambda 实现

C++11 推出了 lambda支持

而在之前要想模仿闭包的实现, 可以使用比较技巧的方式:
其原理是利用定义一个 functor类, 重写 operator() 操作符号
实现方式转自cprogramming