ucontext - phxrpc代码阅读(4)

写在前面

国庆假期过半,phxrpc的代码阅读大概要小小告一段落啦。因为这两天还要读工作相关的代码,以及最后几天还有一次短途旅行。

所以非阻塞TCP流可能要留到下一篇了,这一篇只涉及非阻塞TCP流使用到的ucontext协程库,及其使用的一些框架代码。

161013更新:这点破东西写到今天才写完,GG。

什么是ucontext

"Subroutines are special cases of ... coroutines." –Donald Knuth.

首先我们来看一下,什么是线程。线程是进程内一条执行流的状态,包含了硬件状态(硬件计数器,寄存器,条件码等)和堆栈中的数据。

线程通常只有一个入口和一个出口。当线程返回时,线程的生命周期也结束了。所以,通常线程的执行由内核调度。

协程的定义与线程类似,也是硬件状态+堆栈的状态组合。但是与线程不同的是,协程可以有多个出口。可以通过yield来暂停自己,调用其它协程。再次启动时,会从上次挂起的地方继续运行。

phxrpc中的ucontext

phxrpc提供了system和boost两种ucontext的实现,所以提供了一个uthread_context_base的基类。其实在这里我是有一点怀疑虚函数的性能的,不过好在协程的切换以及网络IO操作还是比较耗性能的,所以虚函数多出来的几次内存寻址也并非不能接受 …

more ...

打造你的专属键盘 — ErgoDone

写在前面

低能预警:这是最没有技术含量的一篇博客,无关人员可以撤离。

部分图片来自网络,侵删

这个十一假期,亲手DIY了一把键盘。当然,我只搞定了焊接部分,把不同的组件拼在了一起。

在焊接的过程中,也学习到了一些新知识。写在这里,记录下来。

ErgoDone介绍

ErgoDone是著名开源硬件ErgoDox的中国特色版本,精简了一些硬件以控制成本。总体价格在500RMB左右,是工薪阶级装逼界的一颗新星。

Ergodox的一个版本:

ErgoDone明显就屌丝了许多:

键盘主控

ErgoDone使用了Arduino pro micro做为主控,基中使用了mega32u4做为芯片,提供了模拟USB输入设备的相关函数(包括键盘、鼠标)。网上有许多现成的范例,用这款芯片(以及另一版使用mega32u4的Arduino开发版,Arduino Leonardo)制作体感鼠标(搭配陀螺仪)、游戏摇杆(搭配相关硬件)以及各种专用输入设备。

Arduino pro micro淘宝价不到20块钱,相对来说算是非常超值了。

焊接

由于本人算是菜的抠脚的业余选手,在这个键盘上的主要工作就是焊接。然而,就在焊接这样一件相对简单的工作上,我也是踩了不少坑 …

more ...

阻塞TCP流 - phxrpc代码阅读(3)

写在前面

phxrpc的流(streamstreambuf)与网络访问其实是耦合在一起的,所以本文可以结合着第一篇笔记一起来看。虽然我非常想吐槽这种强耦合性的设计,但是我决定还是好好理解phxrpc的设计之后。。。攒一波大的:)

BlockTcpStreamBuf

class BlockTcpStreamBuf继承自BaseTcpStreamBuf。其中重写了precvpsend两个函数,并且持有了一个文件描述符(file descriptor):socket_

precvpsend直接调用了<sys/socket.h>中的recv(2)send(2),并没有其它操作。

网络相关的操作,则由class BlockTcpStream来负责。BlockTcpStreamBuf只负责IO部分。

if (BaseTcpUtils::SetNonBlock(sockfd, false …
more ...

定时器以及其它 - phxrpc阅读笔记(2)

写在前面

phxrpc使用了协程(ucontext)和IO复用技术(epoll)来实现网络通信。定时器在其中起到了非常重要的作用。下面我们就来分析一下phxrpc的timer.[h|cpp]中的代码。

system_clock vs steady_clock

system_clocksteadly_clock都是来自<chrono>库,都是用来获取当前时间的。

system_clock用来从系统时钟获取时钟时间(wall clock time),而steadly_clock获取的是时钟tick,而且保证随着时间的推移,时钟tick数不会变小。

然而实际上,在某些系统下,这两个时钟的实现是一致的。详细信息可以参考这里

注:在clang++ 4.2.1, g++ 5.4 下实验,这两个时钟是不同的。所以个人认为在这里最好不要做任何无意义的假设。

几毫秒的安睡

void …
more ...

自定义你的stream buffer - phxrpc阅读笔记(1)

写在前面

phxrpc是微信团队开源的一个轻量级RPC框架。

我对RPC这些东西了解不多,看到phxrpc的代码相对简单,而且还在初步开发阶段(在本文写作时,版本号是0.8)。所以想读一读,提高一下姿势水平。

就是这样。

自定义stream buffer

network/socket_stream_base.[h|cpp]中的class BaseTcpStreamBuf继承了std::streambuf,自定义了一个流缓冲区,用于接收/发送TCP数据包。

这个用法比较新颖(或者是我见识少),网上的资料也不多。这里翻译一篇介绍文章,学习一下新姿势。

A beginner's guide to writing a custom stream buffer

流(streams)是STL中提供的一个重要的抽象概念。著名的“Hello world”程序,便是使用了std …

more ...

Code Golf - Heapify

void heapify(vector<int>& vec) {
    int n = vec.size();
    for (int a = 0, b = 1; b - 1 < n; a = b, b <<= 1) {
        nth_element(vec.begin() + a, vec.begin() + b, vec.end());
    }
}

You can implement a "heapify" by only four lines of code. And the time complexity is O(n).

Fancy …

more ...


Workflowy full notes

Recently, I'm becoming a crazy fan of workflowy because its ability to build a personal wiki concisely.

However, there's only one thing bothers me that workflowy hide all the notes as the screenshot below, and it annoys me a lot.

Alt text

Luckily we can always find a way to get around …

more ...

用C++实现一个通用的sort函数

问题

用C++实现一个尽可能通用的sort函数

分析

一个通用的sort函数应该包含以下要点:

  • 确实可以排序(LOL)
  • 可以应对C-style array和C++-style container的排序需求
  • 可以应用于任意random access container
  • 可以使用用户自定义的排序函数 / 仿函数 / lambda函数

实现

为了与std中的通用函数做区别,这里的命名规则,包括类型与函数,都在前面加了"my"以示区别。可能与标准的命名法有出入,所以仅做示例用。

思路

拷贝代码是愚蠢的行为。

或者说,

对于同一钟实现,尽量使用同一份代码。

感谢C++ Templates,对于不同类型与需求的函数,我们可以将生成多份代码的劳动放心的交给编译器。并且,Templates的代码生成是在编译期完成的,即不会造成额外的代码膨胀(如果你姿势正确的话),也一般不会造成额外的运行时开销。

函数原型

我们模仿std::sort来进行开发。

template< class It, class Compare >
void sort …
more ...

Beauty-of-Programming 2015 Qualification Round Tutorial

A. 2月29日 (Feb. 29th)

Description

Given a starting date and an ending date. Count how many Feb. 29th are between the given dates.

Solution

The easiest way, of course, the brute force, which is quite simple with Python using the datetime lib.

However, it's not an effective way for the …

more ...