libco usage

libco 协程,被分类到非对称协程。分类的方法是: 对称协程(典型的如 golang 的 goroutine),一个协程 yield 后,执行机会不会直接返还到调用者,而是调度器来决定唤起哪个协程。 非对称协程(例如 libco ),一个协程 yield 后,会返还到调用者,继续执行调用者的函数。 非对称在于程序控制流转移到被调协程时使用的是 call/resume 操作,而当被调协程让出 CPU 时使用的却是 return/yield 操作。此外,协程间的地位也不对等,caller 与 callee 关系是确定的,不可更改的,非对称协程只能返回最初调用它的协程。 ...

2022-09-06 · 3 min · Chang Liu

Paxos Algorithm Note

Paxos 协议与工程实现 写在前面,我没有完整实现过 Paxos 协议,不敢保证下面描述的内容完全正确。本文主要是学习的笔记,如果有错误,十分欢迎指出,大家一起讨论学习。 ...

2022-06-26 · 4 min · Chang Liu

cgroup usage

cgroup 全称是 control group,是 linux 下的一个内核模块,用来控制进程的系统资源使用。例如可以限制进程 cpu 使用量、内存使用量等。比如知名开源软件 docker 就是基于 cgroup 来限制容器资源使用,使用 namespace 隔离进程空间。 ...

2022-06-26 · 1 min · Chang Liu

Why Does Conv Need a Mutex

我们以 C++11 的 API 接口定义来描述 大家在编写多线程类的程序时,会用到信号量 condition_variable,有没有疑惑过为什么 cv 这类接口,在调用 wait/notify 时候还需要用一个 mutex。 为什么 cv.wait() 需要用 mutex 保护? 常见的 cv 代码实现类似下方,包含三个部分:检查条件是否满足;如果不满足等待到满足;等待到满足后执行逻辑。 ...

2022-06-23 · 1 min · Chang Liu

2022 05 读书分享

书名:1984 政治小说,推荐指数 4 颗星 小说虚构了一个极权社会,介绍了为真理部工作的外党成员温斯顿的故事。在极权社会下,到处都有电屏的监视。人们每天还要进行仇恨会的活动。对于不认同老大哥统治的思想有“问题”的人,会被思想警察完全从社会上抹去。 ...

2022-06-04 · 1 min · Chang Liu

2267. 检查是否有合法括号字符串路径

记忆化搜索,刚好卡过去 执行用时:1964 ms, 在所有 C++ 提交中击败了 5.08% 的用户 int mem[100][100][100][100]; class Solution { public: // 0 unknow // 1 true // 2 false bool dfs(const vector<vector<char>>& grid, int x1, int y1, int x2, int y2) { if (x1 >= grid.size() || x2 >= grid.size() || y1>=grid[0].size() || y2 < 0 || x2 < 0 || x1 > x2 || y1 > y2) return false; if ((x2 - x1 + y2 - y1)%2==0) return false; if (mem[x1][y1][x2][y2] != 0) { return mem[x1][y1][x2][y2] == 1; } if ( x2 - x1 + y2 - y1 == 1 && grid[x1][y1] == '(' && grid[x2][y2] == ')') { mem[x1][y1][x2][y2] = 1; return true; } if (grid[x1][y1] == '(' && grid[x2][y2] == ')'){ bool tmp = dfs(grid, x1+1, y1, x2-1, y2) || dfs(grid, x1+1, y1, x2, y2-1) || dfs(grid, x1, y1+1, x2-1, y2) || dfs(grid, x1, y1+1, x2, y2-1); if (tmp) { mem[x1][y1][x2][y2] = 1; return true; } for (int i=x1; i<=x2; ++i) for (int j=y1; j<=y2; ++j) { if (i == x1 && j==y1) continue; if (i == x2 && j==y2) continue; if ((dfs(grid, x1, y1, i, j) && dfs(grid, i, j+1, x2, y2))) { mem[x1][y1][x2][y2] = 1; return true; } if (dfs(grid, x1, y1, i, j) && dfs(grid, i+1, j, x2, y2)) { mem[x1][y1][x2][y2] = 1; return true; } } mem[x1][y1][x2][y2] = 2; return false; } else { mem[x1][y1][x2][y2] = 2; return false; } } bool hasValidPath(vector<vector<char>>& grid) { int row = grid.size(); int col = grid[0].size(); if ((row + col)%2==0) return false; if ( grid[0][0] == ')' || grid[row - 1][col - 1] == '(') return false; memset(mem, 0, sizeof mem); return dfs(grid, 0, 0, row-1, col -1); } }; 题解里面有一个写法很好,可以学习一下 ...

2022-05-11 · 2 min · Chang Liu

2266. 统计打字方案数

爬楼梯的加强版本,分别提前生成三个字母和四个字母的 fib 数组,然后分组统计后相乘。代码如下: class Solution { public: int countTexts(string pressedKeys) { int f1[100005]; int f2[100005]; memset(f1, 0, sizeof f1); memset(f2, 0, sizeof f2); f1[0] = 1; f1[1] = 2; f1[2] = 4; f2[0] = 1; f2[1] = 2; f2[2] = 4; f2[3] = 8; for (int i=3; i<100005; ++i) f1[i] = (0LL + f1[i-1] + f1[i-2] + f1[i-3])%int(1e9+7); for (int i=4; i<100005; ++i) f2[i] = (0LL + f2[i-1] + f2[i-2] + f2[i-3] + f2[i-4])%int(1e9+7); int ans = 1; int cur_ch = pressedKeys[0]; int cur_cnt = 1; for (int i=1; i<pressedKeys.size(); ++i) { if (pressedKeys[i] != cur_ch) { if (cur_ch == '7' || cur_ch == '9') ans = 1LL *ans * f2[cur_cnt - 1] % int(1e9+7); else ans = 1LL *ans * f1[cur_cnt - 1] % int(1e9+7); cur_ch = pressedKeys[i]; cur_cnt = 1; } else { ++ cur_cnt; } } if (cur_ch == '7' || cur_ch == '9') ans = 1LL * ans * f2[cur_cnt - 1] % int(1e9+7); else ans = 1LL * ans * f1[cur_cnt - 1] % int(1e9+7); return ans; } };

2022-05-10 · 1 min · Chang Liu

2022 04 读书分享

尘劫: 知青畅想曲 一本名字和封面看起来都非常像地摊文学的书,实际上却是“中共党史出版社”出版的关于知青的报告文学,内容包含了大量真实的知青故事,读来让人不禁唏嘘。 ...

2022-05-09 · 1 min · Chang Liu

golang | error 的内部实现

Golang error 是一个包含了 Error() string 函数的接口,任何实现了 Error() string 的结构体都可以认为是 error 类型。 // The error built-in interface type is the conventional interface for // representing an error condition, with the nil value representing no error. type error interface { Error() string } 对于简单场景,返回一个带字符串描述的 error 可以通过 return errors.New("this is a err") 来实现。其内部实现的机制为:定义了一个 errorString 的结构体,调用 Error() 的时候返回初始化时传入的字符串。 ...

2022-05-07 · 1 min

golang | []byte 和 string 的区别与适用场景

[]byte 和 string 有什么区别?类型转换需要拷贝数据吗?如何选择正确的类型? []byte和string的类型字义非常类似,[]byte 比 string 多一个 cap 成员。string 在大多数的语言中都表示不可变字符串,[]byte 则是可以修改的数组分片。所以在做 []byte 和 string 转换的时候,如果只是简单的将指针复制,就相当于同一块内存同时有了可变和不可变引用,修改了 []byte 会影响到 string 的不可变性(rust 选手应该比较熟悉)。所以做类型转换时,会额外的有内存申请与数据拷贝动作。 ...

2022-03-03 · 1 min