Assert 的使用

Asser 中的表达式的原则:

  • 肯定声明,不要加否定
  • 没有副作用,不会改变任何数据

例如:

1
2
3
assert(obj.isValid())

assert(state == StateOpening)

Assert 是给开发者看的,所以 Assert 只能在 debug 构建中存在,在 release 构建中应该去掉。

Assert 表示某个条件一定或者一定不会发生,它不能代替错误处理。

访问硬件寄存器中的 bit

ref: https://github.com/kensmith/cppmmio

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include <cstdint>
#include <limits>
#include <iostream>

constexpr uint32_t generate_unshifted_mask(int width)
{
    return width ? 1 | generate_unshifted_mask(width - 1) << 1: 0;
}

constexpr uint32_t generate_mask(int width, int offset)
{
    //static_assert(0 < width + offset && width + offset <= 32, "");
    return generate_unshifted_mask(width) << offset;
}

struct ro_t
{
    static uint32_t read(
                         volatile uint32_t * device,
                         int offset,
                         int mask
                         )
    { return (*device & mask) >> offset; }
    };

struct wo_t
{
    static void write(
                      volatile uint32_t * device,
                      uint32_t offset,
                      int mask,
                      int value
                      )
    { *device = ((value << offset) & mask); }
    };

struct rw_t : ro_t
{
    static void write(
                      volatile uint32_t * device,
                      uint32_t offset,
                      int mask,
                      int value
                      )
    { *device = (*device & ~mask) | ((value << offset) & mask); }
    };

// mut_t 地址
// addr 寄存器地址
// offset 偏移量
// width 宽度
template<typename mut_t, uint32_t addr, int offset, int width>
struct reg_t
{
    static_assert(width > 0, "nonpositive width");
    static_assert(offset >= 0, "negative offset");
    static_assert(width + offset <= std::numeric_limits<uint32_t>::digits, "width overflow");

    static uint32_t read()
    {
            constexpr uint32_t mask = generate_mask(offset, width);
            return mut_t::read(reinterpret_cast<volatile uint32_t*>(addr), offset, mask);
        }

    static void write(uint32_t val)
    {
            constexpr uint32_t mask = generate_mask(offset, width);
            mut_t::write(reinterpret_cast<volatile uint32_t*>(addr), offset, mask, val);
        }
    };

using enabled = reg_t<ro_t, 0xffff0000, 0, 1>;

int main(int argc, char* argv[]) {
    if (enabled::read()) {
        std::cout << "not enabled" << std::endl;
    }

    // enabled::write(1); error

    return 0;

}

生成指定范围随机数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <random>
#include <iostream>

int main(int argc, char* argv[]) {

    // 高性能随机数产生器
    std::mt19937 gen(std::random_device{}());

    int left = 1;
    int right = 5;

    // 生成一个在闭区间[a,b]上均匀分布的随机整数
    std::uniform_int_distribution<int> dis(left, right);

    for (int i = 0; i < 10; i++) {
        std::cout << dis(gen) << " ";
    }

    std::cout << std::endl;


    return 0;
}
1
5 1 3 1 3 4 3 2 3 4

call_once 保证函数只会被调用一次

std::call_once 定义在 <mutex> 中,它保证多个线程调用同一个函数的情况下,只会被调用一次。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
#include <thread>
#include <mutex>

static std::once_flag flag;

void do_once() {
    std::call_once(flag, []{
        std::cout << "Only call once"  << std::endl;
    });
}

int main(int argc, char* argv[]) {

    std::thread thread1(do_once);
    std::thread thread2(do_once);
    std::thread thread3(do_once);
    std::thread thread4(do_once);

    thread1.join();
    thread2.join();
    thread3.join();
    thread4.join();
    return 0;
}
1
Only call once