Windows 上使用 Git Tips 两则

Windows Terminal 中 git log 显示 UTF-8 编码的中文

这个准确的说其实是 powershell 自己的问题。

打开当前用户对应的 powershell 的 profile 文件,如果没有就创建一个,目录一般位于 C:\Users\<user>\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1

添加:

1
$env:LANG=zh_CN.UTF8

然后重启 powershell 即可。

Filename too long 导致 checkout 失败

原因是 git 默认使用旧版的 Windows API,对于路径的支持最大为 MAX_PATH(多么熟悉的宏)。

解决方法是直接开启 git 对 windows 的长文件名支持,执行

1
git config --global core.longpaths true

复习:DCLP 和 Memory Reordering

本文是对 Jeff Preshing 的 Double Checked Locking Is Fixed in C++ 11 笔记。

0x00 传统实现

因为 synchronization 只需要在实例第一次创建时保证;此后( instance != nullptr 时)都不需要锁来保证 synchronization。

在第一次判断实例为空和上锁之间存在一个 potential race,因此上锁后需要再一次判断实例是否为空。

这也是 double checked 的来由。

所以一个传统但并不100%正确的 DCLP 实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Singleton {
public:
static Singleton* GetInstance()
{
if (instance == nullptr) {
std::lock_guard<std::mutex> lock(mtx);
if (instance == nullptr) {
instance = new Singleton(); // <-- key point
}
}

return instance;
}

private:
// omit explicit static field initialization.
static std::mutex mtx;
static Singleton* instance;
};

这基本是早起 C++ DCLP 的实现架子。

0x01 问题:内存乱序以及为什么锁帮不了忙

语句

1
instance = new Singleton();

在 C++ 中实际上等效于

1
2
3
tmp = operator new(sizeof(Singleton));  // step 1: allocate memory via operator new
new(tmp) Singleton; // step 2: placement-new for construction
instance = tmp; // step 3: assign addr to instance

注意:其中除了分配内存是固定第一步之外,构造对象和赋值内存地址的生成代码顺序是由编译器自己决定。这里的顺序只是一种可能性。

ASIO Buffer 使用简记

近段有相当一部分时间在熟悉和练习 ASIO

练习过程中发现 ASIO 中如何使用&管理 buffer 是新手大概率会遇到的问题。

结合最近几个 practice demo,稍微简单总结了一下使用经验:

0x00

const_buffermutable_buffer 是两个 fundamental buffer classes。二者的区别在语义上表达的很明显了。

实现上二者提供的接口非常一致,除了一个面向 const void*,另一个面向 void*。这点可以从 ctor 和 data() 中看出。

另外,为了和 C++ 现有的 const cast semantics 保持一致,一个 mutable_buffer 对象可以 implicitly converted to const_buffer

避免在 Linux 上使用 signals

首先承认这个标题乍看之下很像 troll,但真的不是 troll;“避免使用”总的来说更接近 whenever possible 的意思。

另外,这篇 post 面向的主要是偏底层的、直接使用 system calls 或其 runtime wrapper(glibc)的开发者,最典型的比如 C/C++ 开发者。

其他语言的开发者通常因为要么 runtime “屏蔽”了这部分内容(如 Java);要么 runtime 自身对这部分做了较大的抽象/改造(如 Golang),因此很难对此 post 提到的各种观点/做法产生共鸣。

FYI:自从工作后中文写作能力一直在退化,因此这篇文章如果存在语句不通顺或者用词不当的地方,烦请见谅。

0x00 背景回顾:什么是 signal?

signal 源自 Unix,后来成为 POSIX 标准的一部分,现在则被几乎所有的 *nix 系统支持。

signal 本质上是一种通讯机制,用于系统在某个事件(event)发生时通知某个进程(或线程)。

Monthly Read Posts in Aug 2019

Concurrency

A Lock-Free… Linear Search?

实现一个 lock-free array list。

可以作为更复杂的 lockess hashtable 的一个基底实现


The World’s Simplest Lock-Free Hash Table

上一篇的应用。

因为核心是 lockless linear search,所以这里的 hashtable 自然是用 open-addressing 来解决冲突了。

另外两个核心点分别是:

  1. 利用 murmurhash3 finalizer 做 hash function
  2. 利用 idx &= len - 1 其中 len 为二次幂来做 wrap around。

Atomic vs. Non-Atomic Operations

这次考虑的是 non-atomic load/store operations


The Happens-Before Relation

happens-before: If operation A happens-before operation B, then the memory effects of A effectively become visible to the thread performing B before B performs.

  1. Happens-before doesn’t imply happening before: no violation if memory effects visibility preserved
  2. Happening before doesn’t imply happens-before: the happens-before relationship only exists where the language standard says it exists.

The Synchronizes-With Relation

guard-variable & payload metaphore

payload: set of data being propagated between threads
guard variable: protects access to the payload.

a write-release can synchronizes-with a read-acquire.


Acquire and Release Fences

An acquire fence prevents the memory reordering of any read which precedes it in program order with any read or write which follows it in program order.

A release fence prevents the memory reordering of any read or write which precedes it in program order with any write which follows it in program order.

acquire and release fences is that they can establish a synchronizes-with relationship


Acquire and Release Fences Don’t Work the Way You’d Expect

How acquire/release fences differ from acquire/release operations.

Database

index merge 引起的死锁分析

学到了原来还有 index merge 这种操作。

所以说索引不加好,破事一堆。

Misc

Creating a Linux service with systemd

看起来比使用 supervisor 靠谱

解决 CMake 依赖工程中同名 cmake 函数调用混乱

拿 learn-asio 这个项目练手时发现一个问题:learn-asio 依赖了 KBase,这两个项目都是我用 anvil 进行托管的,所以两个项目的 cmake 目录里各自有一份 compiler_*.cmake

因为 compiler_*.cmake 提供的函数 apply_common_compiler_property_to_target() 默认使用了非常严格的属性,导致构建 asio 练手工程出现很多 warning 和静态分析的错误,所以为了省事我把 learn-asio 的这个函数做了宽松化处理。

但是重新构建的时候发现没有效果。

检查了一圈之后发现这个函数的调用变成了 KBase 目录下的版本,猜想可能原因是我首先引入了当前工程目录下的这个 .cmake 模块文件;然后又通过加载依赖的方式引入了 KBase 的 .cmake 模块文件,导致同名函数直接被覆盖成了最后出现的依赖提供的版本。

研究了一下没想到怎么解决,于是看了一下 folly 的处理方式,惊讶地发现 folly 是直接把项目名称 hardcode 进了函数里…

最后仿照着给 anvil 做了一个 patch