├── .gitignore ├── README.md ├── example_code ├── apue │ └── file_lock.c ├── cas │ ├── lockfree_ringbuff │ │ ├── ringbuff.h │ │ └── unittest │ │ │ ├── Makefile │ │ │ ├── unittest │ │ │ └── unittest.cpp │ └── lockfree_stack │ │ ├── lockfree_stack.cpp │ │ ├── lockfree_stack.h │ │ └── test │ │ └── unittest │ │ ├── Makefile │ │ ├── unittest │ │ └── unittest.cpp ├── condition.cc ├── coroutine_demo │ ├── coroutine │ │ ├── Makefile │ │ ├── coroutine.cpp │ │ ├── coroutine.h │ │ └── main.cpp │ ├── demo0.cpp │ ├── demo1.cpp │ ├── demo2.cpp │ └── demo3.cpp ├── cpp-concurrency-master │ ├── .gitignore │ ├── README.md │ ├── make_all.sh │ └── src │ │ ├── 01_hello_thread.cpp │ │ ├── 02_lambda_thread.cpp │ │ ├── 02_thread.cpp │ │ ├── 03_thread_argument.cpp │ │ ├── 04_thread_self_manage.cpp │ │ ├── 05_call_once.cpp │ │ ├── 06_naive_multithread.cpp │ │ ├── 07_mutex_lock.cpp │ │ ├── 08_improved_mutex_lock.cpp │ │ ├── 09_deadlock_bank_transfer.cpp │ │ ├── 10_improved_bank_transfer.cpp │ │ ├── 11_bank_transfer_wait_notify.cpp │ │ ├── 12_async_task.cpp │ │ ├── 13_packaged_task.cpp │ │ ├── 14_promise_future.cpp │ │ ├── 15_parallel_algorithm.cpp │ │ └── CMakeLists.txt ├── cpp │ ├── ConsistentHash.cpp │ └── macro.cpp ├── design_parttern │ └── observer.cc ├── epoll │ ├── client.c │ ├── readme.md │ └── server.c ├── function │ ├── test.c │ ├── test_asm.c │ └── test_jmp.c ├── grpc_demo │ ├── demo │ │ ├── client.go │ │ ├── customer │ │ │ ├── customer.pb.go │ │ │ └── customer.proto │ │ ├── main.go │ │ └── readme.md │ └── stream_rpc │ │ ├── client.go │ │ ├── hellostream │ │ ├── hellostream.pb.go │ │ └── hellostream.proto │ │ ├── readme.md │ │ └── server.go ├── linux_perf_example │ ├── high_iowait_process │ │ ├── app.c │ │ └── readme.md │ ├── perf_demo.c │ └── readme.md ├── lua │ ├── build.sh │ └── test.cpp ├── main.cc ├── memleak_check │ ├── mem_hook │ │ ├── hook_demo │ │ │ ├── example │ │ │ │ ├── checkpasswd │ │ │ │ ├── checkpasswd.cpp │ │ │ │ ├── hack.cpp │ │ │ │ └── hack.so │ │ │ └── example2 │ │ │ │ ├── myfopen.c │ │ │ │ ├── myfopen.so │ │ │ │ ├── prog │ │ │ │ └── prog.c │ │ ├── macro.h │ │ ├── main.cpp │ │ ├── memory_op.cpp │ │ ├── memory_op.h │ │ ├── test1.cpp │ │ ├── test1.h │ │ ├── test2.cpp │ │ └── test2.h │ └── mem_leak_tool │ │ ├── macro.h │ │ ├── memery_op.cpp │ │ ├── memery_op.h │ │ └── prog.cpp ├── mult_file_no_static_obj_init │ ├── Makefile │ ├── file1.cpp │ ├── file1.h │ ├── file2.cpp │ ├── file2.h │ ├── fix_bug_demo │ │ ├── Makefile │ │ ├── file1.cpp │ │ ├── file1.h │ │ ├── file2.cpp │ │ ├── file2.h │ │ └── main.cpp │ ├── main.cpp │ └── readme.md ├── network │ └── test_tcp_connect_and_close │ │ ├── client.cc │ │ ├── readme.md │ │ └── server.cc ├── obj_pool │ ├── README.md │ └── pool.c ├── pb_demo │ ├── heartbeat.db │ ├── heartbeat.pb.cc │ ├── heartbeat.pb.h │ ├── heartbeat.proto │ ├── protoc-gen │ │ ├── helloworld │ │ │ ├── build.sh │ │ │ ├── demo.proto │ │ │ ├── go.mod │ │ │ ├── go.sum │ │ │ ├── main.go │ │ │ └── out │ │ │ │ └── hello.txt │ │ └── protoc-gen-pod │ │ │ ├── Makefile │ │ │ ├── build.sh │ │ │ ├── go.mod │ │ │ ├── go.sum │ │ │ ├── main.go │ │ │ ├── out │ │ │ ├── build.sh │ │ │ ├── custom │ │ │ │ ├── custom_opt.cpp │ │ │ │ ├── custom_opt.h │ │ │ │ └── custom_opt.pb.go │ │ │ ├── demo.cpp │ │ │ ├── demo.h │ │ │ ├── demo.pb.go │ │ │ ├── google.golang.org │ │ │ │ └── protobuf │ │ │ │ │ └── types │ │ │ │ │ └── descriptorpb │ │ │ │ │ ├── descriptor.cpp │ │ │ │ │ └── descriptor.h │ │ │ ├── heartbeat.cpp │ │ │ ├── heartbeat.h │ │ │ ├── heartbeat.pb.go │ │ │ ├── machine.cpp │ │ │ ├── machine.h │ │ │ ├── machine.pb.go │ │ │ ├── proto │ │ │ │ ├── custom_opt.pb.cc │ │ │ │ ├── custom_opt.pb.h │ │ │ │ ├── demo.pb.cc │ │ │ │ ├── demo.pb.h │ │ │ │ ├── heartbeat.pb.cc │ │ │ │ ├── heartbeat.pb.h │ │ │ │ ├── machine.pb.cc │ │ │ │ └── machine.pb.h │ │ │ ├── test_main │ │ │ └── test_main.cpp │ │ │ └── proto │ │ │ ├── custom_opt.proto │ │ │ ├── demo.proto │ │ │ ├── heartbeat.proto │ │ │ └── machine.proto │ ├── reader │ ├── reader.cc │ ├── readme.md │ ├── reflect │ │ ├── demo1 │ │ │ ├── Makefile │ │ │ ├── build.sh │ │ │ ├── main │ │ │ ├── main.cpp │ │ │ ├── out │ │ │ │ ├── person.pb.cc │ │ │ │ └── person.pb.h │ │ │ └── person.proto │ │ └── demo2 │ │ │ ├── Makefile │ │ │ ├── main │ │ │ ├── main.cpp │ │ │ ├── out │ │ │ ├── person.pb.cc │ │ │ └── person.pb.h │ │ │ └── person.proto │ ├── writter │ └── writter.cc ├── pdf │ ├── C++11的内存数据1.pdf │ └── C++11的内存数据2.pdf ├── perd_record │ ├── perf_collector.h │ ├── perf_stat.h │ ├── perf_stat_def.h │ ├── perf_stat_str_def.h │ ├── perf_stat_type_def.h │ ├── readme.md │ └── test_main.c ├── readme.md ├── redis_conf │ └── redis_7000.conf ├── reflect │ ├── dep.h │ ├── helper.h │ └── main.cc ├── shell │ └── cpu.sh └── test │ ├── coverage │ ├── bin │ │ └── main │ └── src │ │ ├── .main.c.gcov.swp │ │ ├── Makefile │ │ ├── main.c │ │ ├── main.c.gcov │ │ ├── main.gcda │ │ ├── main.gcno │ │ ├── module_a.c │ │ ├── module_a.c.gcov │ │ ├── module_a.gcda │ │ ├── module_a.gcno │ │ ├── module_a.h │ │ ├── module_b.c │ │ ├── module_b.gcda │ │ ├── module_b.gcno │ │ └── module_b.h │ └── gmock │ ├── FooInterface.h │ ├── FooMain.cc │ └── FooMock.h ├── note ├── C++字节对齐.md ├── C++编译耗时优化.md ├── CMAKE教程.md ├── PhysX.md ├── TCP和网络编程.md ├── asan.md ├── bash&shell编程.md ├── c++.md ├── c++11多线程.md ├── c++STL.md ├── c++其他.md ├── c++内存管理.md ├── c++多个文件链接初始化顺序问题.md ├── c++学习.md ├── c++智能指针.md ├── c++模板与泛型编程.md ├── c++的前置声明.md ├── c++的多态和虚函数.md ├── c++的类型转换cast.md ├── c++类中使用static和const.md ├── c++面向对象.md ├── design_pattern │ ├── example_code │ │ ├── adapter.c │ │ ├── adapter.h │ │ ├── command.c │ │ ├── command.h │ │ ├── deco.c │ │ ├── deco.h │ │ ├── factory.c │ │ ├── factory.h │ │ ├── fecade.c │ │ ├── fecade.h │ │ ├── fecade2.c │ │ ├── fecade2.h │ │ ├── flyweight.c │ │ ├── flyweight.h │ │ ├── observer.c │ │ ├── observer.h │ │ ├── proxy.c │ │ ├── proxy.h │ │ ├── singleton.c │ │ ├── singleton.h │ │ ├── strategy.c │ │ ├── strategy.h │ │ ├── template.c │ │ ├── template.h │ │ └── test_main.c │ └── note │ │ ├── 0模板模式.md │ │ ├── 10装饰器模式.md │ │ ├── 11命令模式.md │ │ ├── 12门面fecade模式.md │ │ ├── 1策略模式.md │ │ ├── 2观察者模式.md │ │ ├── 3工厂模式.md │ │ ├── 4单例模式.md │ │ ├── 5享元模式.md │ │ ├── 6代理模式.md │ │ ├── 7适配器模式.md │ │ ├── 8状态机模式.md │ │ └── 9责任链模式.md ├── docker.md ├── git教程.md ├── grpc_helloworld.md ├── jemalloc.md ├── limiter.md ├── linux命令.md ├── linux命令_gcc.md ├── linux命令_linux性能分析和优化.md ├── linux命令_linux性能分析和优化2.md ├── linux命令_linux性能分析和优化3.md ├── linux命令_make教程.md ├── linux命令_tcpdump.md ├── linux命令_常用.md ├── linux命令整理.md ├── linux配置.md ├── protobuff_with_golang_tutorial.md ├── reactor模型.md ├── redis_cluster.md ├── shell.md ├── unix环境高级编程.md ├── vscode写c++插件以及配置.md ├── 《重构》的笔记.md ├── 一致性哈希.md ├── 书单_技术类_别人整理的书单.md ├── 书单_技术类_自己整理的.md ├── 书单和博客.md ├── 函数调用过程.md ├── 分布式id生成.md ├── 分布式锁.md ├── 工具栈.md ├── 开源项目.md ├── 收集见到过的一些工具和轮子.md ├── 数据库-索引.md ├── 数据库.md ├── 数据库_mvcc.md ├── 消息队列.md ├── 系统设计.md ├── 系统设计类的问题.md ├── 线程同步.md ├── 缓存系统.md ├── 编码需要注意的问题.md ├── 编译,链接与装载.md ├── 设计模式.md └── 设计模式的基本原则.md └── pic ├── Linux性能分析2.jpg ├── Linux性能分析3.jpg ├── Linux性能分析4.jpg ├── apue笔记.jpg ├── brk1.png ├── docker_1.png ├── docker_pic.PNG ├── git_1.JPG ├── git_2.JPG ├── git_3.JPG ├── git_4.png ├── git_5.png ├── git_6.JPG ├── innodb.png ├── innodb2.png ├── linux性能分析1.PNG ├── make_pic1.png ├── malloc.png ├── malloc2.png ├── malloc3.png ├── mvcc.png ├── myisam.png ├── mysql.png ├── perf.png ├── px_pic1.png ├── px_pic2.png ├── px_pic3.png ├── rate_limit_1.png ├── rate_limit_2.png ├── tcp1.PNG ├── tcp2.PNG ├── tcp3.PNG ├── uml_aggregation.png ├── uml_assocation.png ├── uml_composition.png ├── uml_dependency.png ├── uml_inhert.png ├── 一致性哈希.png ├── 内存_1.png ├── 函数调用1.png ├── 函数调用2.png ├── 函数调用3.png ├── 函数调用4.png ├── 函数调用简单的汇编介绍.pdf ├── 多态和虚函数_1.jpg ├── 多态和虚函数_2.jpg ├── 工具栈_1.png ├── 工具栈_2.png ├── 工具栈_3.png ├── 工具栈_4.png ├── 工具栈_5.png ├── 工具栈_6.png ├── 工具栈_7.png ├── 数据库_1.jpg ├── 数据库_2ACID.png ├── 数据库_3隔离等级.png ├── 数据库索引_1.jpg └── 系统设计1.png /.gitignore: -------------------------------------------------------------------------------- 1 | *.out 2 | .vscode 3 | .DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 程序员的自我修养 2 | 3 | 这个repo的大致的想法是,把自己看到的,学到的东西 或者时觉得不错的一些零散碎片的东西,整理上来。 4 | 5 | ----- 6 | 7 | ## 目录 8 | 9 | * [C/C++](#C/C++) 10 | * [Linux](#Linux和系统编程) 11 | * [数据库](#数据库) 12 | * [编码实践和设计模式](#编码实践和设计模式) 13 | * [数据结构和算法](#数据结构和算法) 14 | * [工具和锤子](#工具和锤子) 15 | 16 | --- 17 | 18 | ## C/C++ 19 | 20 | > [c++基础](./note/c++学习.md) 21 | 22 | > [STL容器](./note/c++STL.md) 23 | 24 | > [编译,链接,装载](./note/编译,链接与装载.md) 25 | 26 | > [函数调用过程](./note/函数调用过程.md) 27 | 28 | > [内存管理](./note/c++内存管理.md) 29 | 30 | > [其他](./note/c++.md) 31 | 32 | > [C++踩坑指南](https://www.jianshu.com/p/b67222570785) 33 | 34 | ## Linux和系统编程 35 | 36 | > [Linux 基本命令](./note/linux命令.md) 37 | 38 | > [linux 关于性能分析的命令](./note/linux命令_linux性能分析和优化.md) 39 | 40 | > [linux 其他](./note/linux命令整理.md) 41 | 42 | ### 乱七八糟的东西 43 | 44 | > [协程](https://www.jianshu.com/p/c4de909fee75) 45 | 46 | > [protobuff](https://www.jianshu.com/p/131f0bf218ef) 47 | 48 | > [分布式id生成](./note/分布式id生成.md) 49 | 50 | > [分布式锁](./note/分布式锁.md) 51 | 52 | > [消息队列](./note/%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97.md) 53 | 54 | > [缓存系统](https://www.jianshu.com/p/057da7850c93) 55 | 56 | > [限流器实现](./note/limiter.md) 57 | 58 | > [一致性哈希](./note/%E4%B8%80%E8%87%B4%E6%80%A7%E5%93%88%E5%B8%8C.md) 59 | 60 | > [大型C++工程编译时间优化](./note/C++编译耗时优化.md) 61 | 62 | ## 工具和锤子 63 | 64 | > [jemalloc](./note/jemalloc.md) 65 | 66 | > [Address Sanitizer](./note/asan.md) 67 | 68 | > [PhysX基本概念](./note/PhysX.md) 69 | 70 | > [收集些小工具,代码片段或轮子](./note/%E6%94%B6%E9%9B%86%E8%A7%81%E5%88%B0%E8%BF%87%E7%9A%84%E4%B8%80%E4%BA%9B%E5%B7%A5%E5%85%B7%E5%92%8C%E8%BD%AE%E5%AD%90.md) 71 | 72 | > [git教程](./note/git教程.md) 73 | 74 | > [make构建教程](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/linux%E5%91%BD%E4%BB%A4_make%E6%95%99%E7%A8%8B.md) 75 | 76 | > [vscode插件](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/vscode%E5%86%99c%2B%2B%E6%8F%92%E4%BB%B6%E4%BB%A5%E5%8F%8A%E9%85%8D%E7%BD%AE.md) 77 | 78 | ## 数据结构和算法 79 | 80 | >[常见的算法题](https://github.com/zhaozhengcoder/Algorithm) 81 | 82 | >[关于系统设计类的问题](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md) 83 | 84 | ## 数据库 85 | 86 | >[数据库系统基本概念](./note/数据库.md) 87 | 88 | >[数据库索引](./note/数据库-索引.md) 89 | 90 | ## 编码实践和设计模式 91 | 92 | > [设计模式](./note/设计模式.md) 93 | 94 | > [Google-style 编码规范](https://zh-google-styleguide.readthedocs.io/en/latest/contents/) 95 | 96 | ## 书单和博客 97 | 98 | * [书单和博客](./note/书单和博客.md) 99 | 100 | ## 后记 101 | 102 | **Typesetting** 103 | 104 | - 内容按照 [中文文案排版指北](https://mazhuang.org/wiki/chinese-copywriting-guidelines/) 进行排版。 105 | 106 | - markdown [教程](http://xianbai.me/learn-md/index.html) 107 | 108 | - branch test test 109 | 110 | -------------------------------------------------------------------------------- /example_code/apue/file_lock.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | /* 11 | 此种方法只能锁整个文件,访问被锁的文件后回直接返回 12 | */ 13 | int main(int argc, char *argv[]) 14 | { 15 | int fdB; 16 | FILE *pA; 17 | 18 | fdB = open("B.lock", O_CREAT | O_EXCL, 0644); 19 | if (fdB < 0 && errno == EEXIST) 20 | { 21 | // 其实是判断文件B.lock是否已经存在 22 | printf("File A.dat is already locked.\n"); 23 | return -1; 24 | } 25 | else if (fdB < 0) 26 | { 27 | perror("error"); 28 | return -1; 29 | } 30 | 31 | //下面进行对文件A.dat的访问 32 | pA = fopen("./A.dat", "w"); 33 | //... 34 | if(pA != NULL) 35 | { 36 | fprintf(pA, "This is testing for fprintf...\n"); 37 | printf("write file \n"); 38 | fclose(pA); 39 | } 40 | else 41 | { 42 | printf("if(pA == NULL) \n"); 43 | } 44 | 45 | sleep(5); 46 | close(fdB); 47 | unlink("B.lock"); // 去掉对加锁文件的引用,删除 "B.lock" 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /example_code/cas/lockfree_ringbuff/unittest/Makefile: -------------------------------------------------------------------------------- 1 | APP_EXE=unittest 2 | 3 | all: $(APP_EXE) 4 | 5 | CFLAGS += -Wsign-conversion -Wpedantic -Wall -DNDEBUG -O3 6 | CFLAGS += -g 7 | 8 | ifeq ($(_LOCK), 1) 9 | CFLAGS += -D USE_LOCK 10 | endif 11 | 12 | #默认无锁版本 13 | $(APP_EXE):unittest.cpp ../ringbuff.h Makefile 14 | g++ -std=c++11 $(CFLAGS) unittest.cpp ../ringbuff.h -o $(APP_EXE) -lpthread 15 | 16 | #构建有锁版本 17 | lock_version: 18 | make $(APP_EXE) _LOCK=1 19 | 20 | clean: 21 | rm $(APP_EXE) -------------------------------------------------------------------------------- /example_code/cas/lockfree_ringbuff/unittest/unittest: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/example_code/cas/lockfree_ringbuff/unittest/unittest -------------------------------------------------------------------------------- /example_code/cas/lockfree_stack/lockfree_stack.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/example_code/cas/lockfree_stack/lockfree_stack.cpp -------------------------------------------------------------------------------- /example_code/cas/lockfree_stack/lockfree_stack.h: -------------------------------------------------------------------------------- 1 | #ifndef __LOCKFREE_STACK_H__ 2 | #define __LOCKFREE_STACK_H__ 3 | 4 | class Node 5 | { 6 | public: 7 | int val; 8 | int extra_info; 9 | 10 | Node *next; 11 | Node(int val): val(val), next(NULL) {} 12 | }; 13 | 14 | class Stack 15 | { 16 | public: 17 | void push(int val, int debug_thread_info); 18 | Node* pop(); 19 | void print(); 20 | int get_size(); 21 | 22 | private: 23 | std::atomic _top; 24 | }; 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /example_code/cas/lockfree_stack/test/unittest/Makefile: -------------------------------------------------------------------------------- 1 | APP_EXE=unittest 2 | 3 | all: $(APP_EXE) 4 | 5 | CFLAGS += -Wsign-conversion -Wpedantic -Wall -DNDEBUG -O3 6 | CFLAGS += -g 7 | 8 | $(APP_EXE):unittest.cpp ../../lockfree_stack.h ../../lockfree_stack.cpp Makefile 9 | g++ -std=c++11 $(CFLAGS) unittest.cpp ../../lockfree_stack.cpp -o $(APP_EXE) -lpthread 10 | 11 | clean: 12 | rm $(APP_EXE) -------------------------------------------------------------------------------- /example_code/cas/lockfree_stack/test/unittest/unittest: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/example_code/cas/lockfree_stack/test/unittest/unittest -------------------------------------------------------------------------------- /example_code/condition.cc: -------------------------------------------------------------------------------- 1 | 2 | // condition条件变量 3 | // 线程使用condition同步 4 | // 使用基本的condition api 写一个例子 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | pthread_mutex_t count_lock; 11 | pthread_cond_t count_nonzero; 12 | unsigned count = 0; 13 | 14 | void * decrement_count(void * arg) 15 | { 16 | pthread_mutex_lock(&count_lock); 17 | printf("[< decrement_count] get count_lock \n"); 18 | while(count == 0) 19 | { 20 | printf("[< decrement_count] count == 0 \n"); 21 | printf("[< decrement_count] before cond_wait \n"); 22 | pthread_cond_wait(&count_nonzero, &count_lock); 23 | printf("[< decrement_count] after cond_wait \n"); 24 | } 25 | 26 | count = count + 1; 27 | pthread_mutex_unlock(&count_lock); 28 | } 29 | 30 | void * increment_count(void *arg) 31 | { 32 | pthread_mutex_lock(&count_lock); 33 | printf("[>increment_count] get count_lock \n"); 34 | if(count == 0) 35 | { 36 | printf("[>increment_count] before cond_signal \n"); 37 | pthread_cond_signal(&count_nonzero); 38 | printf("[>increment_count] after cond_signal \n"); 39 | } 40 | count = count + 1; 41 | pthread_mutex_unlock(&count_lock); 42 | } 43 | 44 | int main(void) 45 | { 46 | printf("in main\n"); 47 | pthread_t tid1, tid2; 48 | 49 | pthread_mutex_init(&count_lock, NULL); 50 | pthread_cond_init(&count_nonzero, NULL); 51 | 52 | pthread_create(&tid1, NULL, decrement_count, NULL); 53 | sleep(1); 54 | pthread_create(&tid2, NULL, increment_count, NULL); 55 | 56 | sleep(5); 57 | pthread_exit(0); 58 | 59 | return 0; 60 | } 61 | 62 | // g++ -g condition.cc -lpthread 63 | 64 | // in main 65 | // [< decrement_count] get count_lock 66 | // [< decrement_count] count == 0 67 | // [< decrement_count] before cond_wait 68 | // [>increment_count] get count_lock 69 | // [>increment_count] before cond_signal 70 | // [>increment_count] after cond_signal 71 | // [< decrement_count] after cond_wait -------------------------------------------------------------------------------- /example_code/coroutine_demo/coroutine/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | g++ main.cpp coroutine.cpp -g -o main 3 | g++ unit_test.cpp coroutine.cpp -g -o unittest 4 | 5 | clean: 6 | rm -f main 7 | rm -f unit_test 8 | rm *.o -------------------------------------------------------------------------------- /example_code/coroutine_demo/coroutine/coroutine.h: -------------------------------------------------------------------------------- 1 | #ifndef __COROUTINE_H__ 2 | #define __COROUTINE_H__ 3 | 4 | #include 5 | #include 6 | 7 | enum ROUNTINE_STATE {FREE,RUNNABLE,RUNNING,SUSPEND}; 8 | 9 | typedef void (*TaskFunc)(void *arg); 10 | const int CO_ROUTINE_MAX = 1024 * 100; // 最多可以运行10w个协程 11 | const int CO_STACK_SIZE = 1024 * 128; // 每个协程的大小是128k 12 | 13 | const int INVALID_IDX = -1; 14 | 15 | class CO_ROUTINE_CTX 16 | { 17 | public: 18 | ucontext_t ctx; // 协程的上下文 (协程被切出的时候,上下文保存在这里) 19 | TaskFunc func; // 协程的任务函数 20 | void *arg; // 协程任务函数的函数 21 | enum ROUNTINE_STATE state; // 协程的状态 22 | char stack[CO_STACK_SIZE]; // 协程的栈空间 23 | }; 24 | 25 | class CO_MGR 26 | { 27 | private: 28 | CO_MGR(); 29 | static CO_MGR * instance; 30 | 31 | public: 32 | static CO_MGR * get_instance(); 33 | ucontext_t main; 34 | int cur_max_num; 35 | int running_co; 36 | CO_ROUTINE_CTX co_ctxs[CO_ROUTINE_MAX]; 37 | }; 38 | 39 | int co_create(CO_MGR * mgr, TaskFunc func, void *arg); 40 | int co_yield(); 41 | int co_resume(int co_id); 42 | bool co_is_all_finished(CO_MGR * mgr); 43 | bool co_is_dead(CO_MGR * mgr, int co_id); 44 | int get_running_co_id(CO_MGR * mgr); 45 | CO_MGR * co_mgr_get(); 46 | #endif -------------------------------------------------------------------------------- /example_code/coroutine_demo/coroutine/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "coroutine.h" 3 | 4 | struct DB_REQ_ARG 5 | { 6 | int req; 7 | int result; 8 | }; 9 | 10 | int send_query_db_req(void * req) 11 | { 12 | printf("do %s \n", __FUNCTION__); 13 | return 0; 14 | } 15 | 16 | void foo1(void *arg) 17 | { 18 | DB_REQ_ARG * req = (DB_REQ_ARG *)arg; 19 | send_query_db_req(req); 20 | 21 | CO_MGR * mgr = co_mgr_get(); 22 | co_yield(); 23 | printf("func resume, co id %d\n", mgr->running_co); 24 | } 25 | 26 | void foo2(void *arg) 27 | { 28 | DB_REQ_ARG * req = (DB_REQ_ARG *)arg; 29 | send_query_db_req(req); 30 | 31 | CO_MGR * mgr = co_mgr_get(); 32 | co_yield(); 33 | printf("func resume once, co id %d\n", mgr->running_co); 34 | 35 | co_yield(); 36 | printf("func resume twice, co id %d\n", mgr->running_co); 37 | } 38 | 39 | void schedule_test() 40 | { 41 | DB_REQ_ARG arg; 42 | CO_MGR * mgr = co_mgr_get(); 43 | 44 | int id1 = co_create(mgr, foo1, &arg); 45 | if (id1 < 0) {return;} 46 | 47 | int id2 = co_create(mgr, foo2, &arg); 48 | if (id2 < 0) {return;} 49 | 50 | arg.result = 100; 51 | while(!co_is_dead(mgr, id1) || !co_is_dead(mgr, id2)) 52 | { 53 | co_resume(id1); 54 | co_resume(id2); 55 | } 56 | printf("===== %s end ====\n", __FUNCTION__); 57 | } 58 | 59 | 60 | int main() 61 | { 62 | schedule_test(); 63 | 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /example_code/coroutine_demo/demo0.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void ping(); 4 | void pong(); 5 | 6 | void ping() 7 | { 8 | printf("ping\n"); 9 | pong(); 10 | } 11 | 12 | void pong() 13 | { 14 | printf("pong\n"); 15 | ping(); 16 | } 17 | 18 | int main(int argc, char *argv[]) 19 | { 20 | ping(); 21 | return 0; 22 | } 23 | 24 | // 运行结果: 25 | // [1] 431 segmentation fault (core dumped) ./a.out -------------------------------------------------------------------------------- /example_code/coroutine_demo/demo1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | const int MAX_COUNT = 5; 6 | 7 | static ucontext_t uc[3]; 8 | static int count = 0; 9 | 10 | void ping(); 11 | void pong(); 12 | 13 | void ping() 14 | { 15 | while (count < MAX_COUNT) 16 | { 17 | printf("ping %d\n", ++count); 18 | // yield to pong 19 | sleep(1); 20 | swapcontext(&uc[1], &uc[2]); // 保存当前context于uc[1],切换至uc[2]的context运行 21 | printf("ping -> end \n"); 22 | } 23 | } 24 | 25 | void pong() 26 | { 27 | while (count < MAX_COUNT) 28 | { 29 | printf("pong %d\n", ++count); 30 | // yield to ping 31 | sleep(1); 32 | swapcontext(&uc[2], &uc[1]); // 保存当前context于uc[2],切换至uc[1]的context运行 33 | printf("pong -> end \n"); 34 | } 35 | } 36 | 37 | char st1[8192]; 38 | char st2[8192]; 39 | 40 | int main(int argc, char *argv[]) 41 | { 42 | 43 | // initialize context 44 | printf("times %d \n", MAX_COUNT); 45 | getcontext(&uc[1]); 46 | getcontext(&uc[2]); 47 | 48 | printf("begin \n"); 49 | 50 | uc[1].uc_link = &uc[0]; // 这个玩意表示uc[1]运行完成后,会跳至uc[0]指向的context继续运行 51 | uc[1].uc_stack.ss_sp = st1; // 设置新的堆栈 52 | uc[1].uc_stack.ss_size = sizeof st1; 53 | makecontext(&uc[1], ping, 0); 54 | 55 | uc[2].uc_link = &uc[0]; // 这个玩意表示uc[2]运行完成后,会跳至uc[0]指向的context继续运行 56 | uc[2].uc_stack.ss_sp = st2; // 设置新的堆栈 57 | uc[2].uc_stack.ss_size = sizeof st2; 58 | makecontext(&uc[2], pong, 0); 59 | 60 | // start ping-pong 61 | swapcontext(&uc[0], &uc[1]); 62 | 63 | // 将当前context信息保存至uc[0],跳转至uc[1]保存的context去执行 64 | // 这里我稍微要多说几句,因为我迷惑过,我曾经困惑的一点在于uc[0],为什么uc[0]不需要设置堆栈的信息? 65 | // 因为swapcontext已经帮我们做好了一切,swapcontext函数会将当前点的信息保存在uc[0]中 66 | // 当然我们没有设置的话,默认的堆栈一定是主堆栈啦 67 | printf("end \n"); 68 | 69 | return 0; 70 | } -------------------------------------------------------------------------------- /example_code/coroutine_demo/demo2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | const int MAX_COUNT = 5; 6 | 7 | static ucontext_t uc[4]; // 添加一个元素 8 | static int count = 0; 9 | 10 | void ping(); 11 | void pong(); 12 | 13 | void ping() 14 | { 15 | while (count < MAX_COUNT) 16 | { 17 | printf("ping %d\n", ++count); 18 | // yield to pong 19 | sleep(1); 20 | swapcontext(&uc[1], &uc[2]); // 保存当前context于uc[1],切换至uc[2]的context运行 21 | printf("ping -> end \n"); 22 | } 23 | } 24 | 25 | void pong() 26 | { 27 | while (count < MAX_COUNT) 28 | { 29 | printf("pong %d\n", ++count); 30 | // yield to ping 31 | sleep(1); 32 | swapcontext(&uc[2], &uc[1]); // 保存当前context于uc[2],切换至uc[1]的context运行 33 | printf("pong -> end \n"); 34 | } 35 | } 36 | 37 | char st1[8192]; 38 | char st2[8192]; 39 | 40 | int main(int argc, char *argv[]) 41 | { 42 | 43 | // initialize context 44 | printf("times %d \n", MAX_COUNT); 45 | getcontext(&uc[1]); 46 | getcontext(&uc[2]); 47 | getcontext(&uc[3]); 48 | 49 | printf("begin \n"); 50 | 51 | uc[1].uc_link = &uc[3]; // 上下文完毕之后,改成切换到uc[3] 52 | uc[1].uc_stack.ss_sp = st1; // 设置新的堆栈 53 | uc[1].uc_stack.ss_size = sizeof st1; 54 | makecontext(&uc[1], ping, 0); 55 | 56 | uc[2].uc_link = &uc[3]; // 上下文完毕之后,改成切换到uc[3] 57 | uc[2].uc_stack.ss_sp = st2; // 设置新的堆栈 58 | uc[2].uc_stack.ss_size = sizeof st2; 59 | makecontext(&uc[2], pong, 0); 60 | 61 | // start ping-pong 62 | swapcontext(&uc[0], &uc[1]); 63 | 64 | printf("end \n"); 65 | 66 | return 0; 67 | } -------------------------------------------------------------------------------- /example_code/coroutine_demo/demo3.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | const int MAX_COUNT = 5; 6 | 7 | static ucontext_t uc[4]; 8 | static int count = 0; 9 | static int first_entry = 0; 10 | 11 | void ping(); 12 | void pong(); 13 | 14 | void ping() 15 | { 16 | while (count < MAX_COUNT) 17 | { 18 | printf("ping %d\n", ++count); 19 | // yield to pong 20 | sleep(1); 21 | swapcontext(&uc[1], &uc[2]); // 保存当前context于uc[1],切换至uc[2]的context运行 22 | printf("ping -> end \n"); 23 | } 24 | } 25 | 26 | void pong() 27 | { 28 | while (count < MAX_COUNT) 29 | { 30 | printf("pong %d\n", ++count); 31 | // yield to ping 32 | sleep(1); 33 | swapcontext(&uc[2], &uc[1]); // 保存当前context于uc[2],切换至uc[1]的context运行 34 | printf("pong -> end \n"); 35 | } 36 | } 37 | 38 | char st1[8192]; 39 | char st2[8192]; 40 | 41 | int main(int argc, char *argv[]) 42 | { 43 | 44 | // initialize context 45 | printf("times %d \n", MAX_COUNT); 46 | getcontext(&uc[1]); 47 | getcontext(&uc[2]); 48 | getcontext(&uc[3]); 49 | 50 | printf("begin , is_first_entry %d \n", first_entry); 51 | 52 | if (first_entry == 0) 53 | { 54 | first_entry++; 55 | 56 | uc[1].uc_link = &uc[3]; // 57 | uc[1].uc_stack.ss_sp = st1; // 58 | uc[1].uc_stack.ss_size = sizeof st1; 59 | makecontext(&uc[1], ping, 0); 60 | 61 | uc[2].uc_link = &uc[3]; // 62 | uc[2].uc_stack.ss_sp = st2; // 63 | uc[2].uc_stack.ss_size = sizeof st2; 64 | makecontext(&uc[2], pong, 0); 65 | 66 | // start ping-pong 67 | swapcontext(&uc[0], &uc[1]); 68 | } 69 | printf("end \n"); 70 | 71 | return 0; 72 | } -------------------------------------------------------------------------------- /example_code/cpp-concurrency-master/.gitignore: -------------------------------------------------------------------------------- 1 | # General 2 | .DS_Store 3 | .AppleDouble 4 | .LSOverride 5 | 6 | # Icon must end with two \r 7 | Icon 8 | 9 | # Thumbnails 10 | ._* 11 | 12 | # Files that might appear in the root of a volume 13 | .DocumentRevisions-V100 14 | .fseventsd 15 | .Spotlight-V100 16 | .TemporaryItems 17 | .Trashes 18 | .VolumeIcon.icns 19 | .com.apple.timemachine.donotpresent 20 | 21 | # Directories potentially created on remote AFP share 22 | .AppleDB 23 | .AppleDesktop 24 | Network Trash Folder 25 | Temporary Items 26 | .apdisk 27 | 28 | # bin 29 | bin 30 | -------------------------------------------------------------------------------- /example_code/cpp-concurrency-master/README.md: -------------------------------------------------------------------------------- 1 | Source code for [C++ 并发编程](https://paul.pub/cpp-concurrency/) -------------------------------------------------------------------------------- /example_code/cpp-concurrency-master/make_all.sh: -------------------------------------------------------------------------------- 1 | rm -rf bin 2 | 3 | mkdir build 4 | cd build 5 | 6 | cmake ../src/ 7 | make 8 | 9 | cd ../ 10 | mv build/bin ./ 11 | rm -rf build/ 12 | -------------------------------------------------------------------------------- /example_code/cpp-concurrency-master/src/01_hello_thread.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | void hello() { 7 | cout << "Hello World from new thread." << endl; 8 | } 9 | 10 | int main() { 11 | thread t(hello); 12 | t.join(); 13 | 14 | return 0; 15 | } -------------------------------------------------------------------------------- /example_code/cpp-concurrency-master/src/02_lambda_thread.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() { 7 | thread t([] { 8 | cout << "Hello World from lambda thread." << endl; 9 | }); 10 | 11 | t.join(); 12 | 13 | return 0; 14 | } -------------------------------------------------------------------------------- /example_code/cpp-concurrency-master/src/02_thread.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | static const int MAX = 10e8; 10 | 11 | static mutex gMutex; 12 | 13 | static double sum = 0; 14 | 15 | void worker(int min, int max) { 16 | for (int i = min; i <= max; i++) { 17 | sum += sqrt(i); 18 | } 19 | } 20 | 21 | void serial_task(int min, int max) { 22 | auto start_time = chrono::steady_clock::now(); 23 | sum = 0; 24 | worker(0, MAX); 25 | auto end_time = chrono::steady_clock::now(); 26 | auto ms = chrono::duration_cast(end_time - start_time).count(); 27 | cout << "Serail task finish, " << ms << " ms consumed, Result: " << sum << endl; 28 | } 29 | 30 | void concurrent_worker(int min, int max) { 31 | { 32 | lock_guard guard(gMutex); 33 | cout << "Thread " << this_thread::get_id() << " work for [" << min << ", " << max << "]" << endl; 34 | } 35 | double cur_sum = 0; 36 | for (int i = min; i <= max; i++) { 37 | cur_sum += sqrt(i); 38 | } 39 | { 40 | lock_guard guard(gMutex); 41 | sum += cur_sum; 42 | } 43 | } 44 | 45 | void concurrent_task(int min, int max) { 46 | auto start_time = chrono::steady_clock::now(); 47 | 48 | unsigned concurrent_count = thread::hardware_concurrency(); 49 | cout << "hardware_concurrency: " << concurrent_count << endl; 50 | vector threads; 51 | min = 0; 52 | sum = 0; 53 | for (int t = 0; t < concurrent_count; t++) { 54 | int range = max / concurrent_count * (t + 1); 55 | threads.push_back(thread(concurrent_worker, min, range)); 56 | min = range + 1; 57 | } 58 | for (int i = 0; i < threads.size(); i++) { 59 | threads[i].join(); 60 | } 61 | 62 | auto end_time = chrono::steady_clock::now(); 63 | auto ms = chrono::duration_cast(end_time - start_time).count(); 64 | cout << "Concurrent task finish, " << ms << " ms consumed, Result: " << sum << endl; 65 | } 66 | 67 | int main() { 68 | serial_task(0, MAX); 69 | concurrent_task(0, MAX); 70 | return 0; 71 | } -------------------------------------------------------------------------------- /example_code/cpp-concurrency-master/src/03_thread_argument.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | void hello(string name) { 8 | cout << "Welcome to " << name << endl; 9 | } 10 | 11 | int main() { 12 | thread t(hello, "https://paul.pub"); 13 | t.join(); 14 | 15 | return 0; 16 | } -------------------------------------------------------------------------------- /example_code/cpp-concurrency-master/src/04_thread_self_manage.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | void print_time() { 11 | auto now = chrono::system_clock::now(); 12 | auto in_time_t = chrono::system_clock::to_time_t(now); 13 | 14 | std::stringstream ss; 15 | ss << put_time(localtime(&in_time_t), "%Y-%m-%d %X"); 16 | cout << "now is: " << ss.str() << endl; 17 | } 18 | 19 | void sleep_thread() { 20 | this_thread::sleep_for(chrono::seconds(3)); 21 | cout << "[thread-" << this_thread::get_id() << "] is waking up" << endl; 22 | } 23 | 24 | void loop_thread() { 25 | for (int i = 0; i < 10; i++) { 26 | cout << "[thread-" << this_thread::get_id() << "] print: " << i << endl; 27 | } 28 | } 29 | 30 | int main() { 31 | print_time(); 32 | 33 | thread t1(sleep_thread); 34 | thread t2(loop_thread); 35 | 36 | t1.join(); 37 | t2.detach(); 38 | 39 | print_time(); 40 | return 0; 41 | } -------------------------------------------------------------------------------- /example_code/cpp-concurrency-master/src/05_call_once.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | void init() { 8 | cout << "Initialing..." << endl; 9 | // Do something... 10 | } 11 | 12 | void worker(once_flag* flag) { 13 | call_once(*flag, init); 14 | } 15 | 16 | int main() { 17 | once_flag flag; 18 | 19 | thread t1(worker, &flag); 20 | thread t2(worker, &flag); 21 | thread t3(worker, &flag); 22 | 23 | t1.join(); 24 | t2.join(); 25 | t3.join(); 26 | 27 | return 0; 28 | } -------------------------------------------------------------------------------- /example_code/cpp-concurrency-master/src/06_naive_multithread.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | static const int MAX = 10e8; 10 | static double sum = 0; 11 | 12 | void worker(int min, int max) { 13 | for (int i = min; i <= max; i++) { 14 | sum += sqrt(i); 15 | } 16 | } 17 | 18 | void serial_task(int min, int max) { 19 | auto start_time = chrono::steady_clock::now(); 20 | sum = 0; 21 | worker(0, MAX); 22 | auto end_time = chrono::steady_clock::now(); 23 | auto ms = chrono::duration_cast(end_time - start_time).count(); 24 | cout << "Serail task finish, " << ms << " ms consumed, Result: " << sum << endl; 25 | } 26 | 27 | void concurrent_task(int min, int max) { 28 | auto start_time = chrono::steady_clock::now(); 29 | 30 | unsigned concurrent_count = thread::hardware_concurrency(); 31 | cout << "hardware_concurrency: " << concurrent_count << endl; 32 | vector threads; 33 | min = 0; 34 | sum = 0; 35 | for (int t = 0; t < concurrent_count; t++) { 36 | int range = max / concurrent_count * (t + 1); 37 | threads.push_back(thread(worker, min, range)); 38 | min = range + 1; 39 | } 40 | for (int i = 0; i < threads.size(); i++) { 41 | threads[i].join(); 42 | } 43 | 44 | auto end_time = chrono::steady_clock::now(); 45 | auto ms = chrono::duration_cast(end_time - start_time).count(); 46 | cout << "Concurrent task finish, " << ms << " ms consumed, Result: " << sum << endl; 47 | } 48 | 49 | int main() { 50 | serial_task(0, MAX); 51 | concurrent_task(0, MAX); 52 | return 0; 53 | } -------------------------------------------------------------------------------- /example_code/cpp-concurrency-master/src/07_mutex_lock.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | static const int MAX = 10e8; 11 | static double sum = 0; 12 | 13 | static mutex exclusive; 14 | 15 | void concurrent_worker(int min, int max) { 16 | for (int i = min; i <= max; i++) { 17 | exclusive.lock(); 18 | sum += sqrt(i); 19 | exclusive.unlock(); 20 | } 21 | } 22 | 23 | void concurrent_task(int min, int max) { 24 | auto start_time = chrono::steady_clock::now(); 25 | 26 | unsigned concurrent_count = thread::hardware_concurrency(); 27 | cout << "hardware_concurrency: " << concurrent_count << endl; 28 | vector threads; 29 | min = 0; 30 | sum = 0; 31 | for (int t = 0; t < concurrent_count; t++) { 32 | int range = max / concurrent_count * (t + 1); 33 | threads.push_back(thread(concurrent_worker, min, range)); 34 | min = range + 1; 35 | } 36 | for (int i = 0; i < threads.size(); i++) { 37 | threads[i].join(); 38 | } 39 | 40 | auto end_time = chrono::steady_clock::now(); 41 | auto ms = chrono::duration_cast(end_time - start_time).count(); 42 | cout << "Concurrent task finish, " << ms << " ms consumed, Result: " << sum << endl; 43 | } 44 | 45 | int main() { 46 | concurrent_task(0, MAX); 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /example_code/cpp-concurrency-master/src/08_improved_mutex_lock.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | static const int MAX = 10e8; 11 | static double sum = 0; 12 | 13 | static mutex exclusive; 14 | 15 | void concurrent_worker(int min, int max) { 16 | double tmp_sum = 0; 17 | for (int i = min; i <= max; i++) { 18 | tmp_sum += sqrt(i); 19 | } 20 | exclusive.lock(); 21 | sum += tmp_sum; 22 | exclusive.unlock(); 23 | } 24 | 25 | void concurrent_task(int min, int max) { 26 | auto start_time = chrono::steady_clock::now(); 27 | 28 | unsigned concurrent_count = thread::hardware_concurrency(); 29 | cout << "hardware_concurrency: " << concurrent_count << endl; 30 | vector threads; 31 | min = 0; 32 | sum = 0; 33 | for (int t = 0; t < concurrent_count; t++) { 34 | int range = max / concurrent_count * (t + 1); 35 | threads.push_back(thread(concurrent_worker, min, range)); 36 | min = range + 1; 37 | } 38 | for (int i = 0; i < threads.size(); i++) { 39 | threads[i].join(); 40 | } 41 | 42 | auto end_time = chrono::steady_clock::now(); 43 | auto ms = chrono::duration_cast(end_time - start_time).count(); 44 | cout << "Concurrent task finish, " << ms << " ms consumed, Result: " << sum << endl; 45 | } 46 | 47 | int main() { 48 | concurrent_task(0, MAX); 49 | return 0; 50 | } -------------------------------------------------------------------------------- /example_code/cpp-concurrency-master/src/09_deadlock_bank_transfer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | class Account { 9 | public: 10 | Account(string name, double money): mName(name), mMoney(money) {}; 11 | 12 | public: 13 | void changeMoney(double amount) { 14 | mMoney += amount; 15 | } 16 | string getName() { 17 | return mName; 18 | } 19 | double getMoney() { 20 | return mMoney; 21 | } 22 | mutex* getLock() { 23 | return &mMoneyLock; 24 | } 25 | 26 | private: 27 | string mName; 28 | double mMoney; 29 | mutex mMoneyLock; 30 | }; 31 | 32 | class Bank { 33 | public: 34 | void addAccount(Account* account) { 35 | mAccounts.insert(account); 36 | } 37 | 38 | bool transferMoney(Account* accountA, Account* accountB, double amount) { 39 | lock_guard guardA(*accountA->getLock()); 40 | lock_guard guardB(*accountB->getLock()); 41 | 42 | if (amount > accountA->getMoney()) { 43 | return false; 44 | } 45 | 46 | accountA->changeMoney(-amount); 47 | accountB->changeMoney(amount); 48 | return true; 49 | } 50 | 51 | double totalMoney() const { 52 | double sum = 0; 53 | for (auto a : mAccounts) { 54 | sum += a->getMoney(); 55 | } 56 | return sum; 57 | } 58 | 59 | private: 60 | set mAccounts; 61 | }; 62 | 63 | void randomTransfer(Bank* bank, Account* accountA, Account* accountB) { 64 | while(true) { 65 | double randomMoney = ((double)rand() / RAND_MAX) * 100; 66 | if (bank->transferMoney(accountA, accountB, randomMoney)) { 67 | cout << "Transfer " << randomMoney << " from " << accountA->getName() 68 | << " to " << accountB->getName() 69 | << ", Bank totalMoney: " << bank->totalMoney() << endl; 70 | } else { 71 | cout << "Transfer failed, " 72 | << accountA->getName() << " has only $" << accountA->getMoney() << ", but " 73 | << randomMoney << " required" << endl; 74 | } 75 | } 76 | } 77 | 78 | int main() { 79 | Account a("Paul", 100); 80 | Account b("Moira", 100); 81 | 82 | Bank aBank; 83 | aBank.addAccount(&a); 84 | aBank.addAccount(&b); 85 | 86 | thread t1(randomTransfer, &aBank, &a, &b); 87 | thread t2(randomTransfer, &aBank, &b, &a); 88 | 89 | t1.join(); 90 | t2.join(); 91 | 92 | return 0; 93 | } -------------------------------------------------------------------------------- /example_code/cpp-concurrency-master/src/10_improved_bank_transfer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | class Account { 9 | public: 10 | Account(string name, double money): mName(name), mMoney(money) {}; 11 | 12 | public: 13 | void changeMoney(double amount) { 14 | mMoney += amount; 15 | } 16 | string getName() { 17 | return mName; 18 | } 19 | double getMoney() { 20 | return mMoney; 21 | } 22 | mutex* getLock() { 23 | return &mMoneyLock; 24 | } 25 | 26 | private: 27 | string mName; 28 | double mMoney; 29 | mutex mMoneyLock; 30 | }; 31 | 32 | class Bank { 33 | public: 34 | void addAccount(Account* account) { 35 | mAccounts.insert(account); 36 | } 37 | 38 | bool transferMoney(Account* accountA, Account* accountB, double amount) { 39 | // lock(*accountA->getLock(), *accountB->getLock()); 40 | // lock_guard lockA(*accountA->getLock(), adopt_lock); 41 | // lock_guard lockB(*accountB->getLock(), adopt_lock); 42 | 43 | scoped_lock lockAll(*accountA->getLock(), *accountB->getLock()); 44 | 45 | if (amount > accountA->getMoney()) { 46 | return false; 47 | } 48 | 49 | accountA->changeMoney(-amount); 50 | accountB->changeMoney(amount); 51 | return true; 52 | } 53 | 54 | double totalMoney() const { 55 | double sum = 0; 56 | for (auto a : mAccounts) { 57 | sum += a->getMoney(); 58 | } 59 | return sum; 60 | } 61 | 62 | private: 63 | set mAccounts; 64 | }; 65 | 66 | mutex sCoutLock; 67 | void randomTransfer(Bank* bank, Account* accountA, Account* accountB) { 68 | while(true) { 69 | double randomMoney = ((double)rand() / RAND_MAX) * 100; 70 | if (bank->transferMoney(accountA, accountB, randomMoney)) { 71 | sCoutLock.lock(); 72 | cout << "Transfer " << randomMoney << " from " << accountA->getName() 73 | << " to " << accountB->getName() 74 | << ", Bank totalMoney: " << bank->totalMoney() << endl; 75 | sCoutLock.unlock(); 76 | } else { 77 | sCoutLock.lock(); 78 | cout << "Transfer failed, " 79 | << accountA->getName() << " has only " << accountA->getMoney() << ", but " 80 | << randomMoney << " required" << endl; 81 | sCoutLock.unlock(); 82 | } 83 | } 84 | } 85 | 86 | int main() { 87 | Account a("Paul", 100); 88 | Account b("Moira", 100); 89 | 90 | Bank aBank; 91 | aBank.addAccount(&a); 92 | aBank.addAccount(&b); 93 | 94 | thread t1(randomTransfer, &aBank, &a, &b); 95 | thread t2(randomTransfer, &aBank, &b, &a); 96 | 97 | t1.join(); 98 | t2.join(); 99 | 100 | return 0; 101 | } -------------------------------------------------------------------------------- /example_code/cpp-concurrency-master/src/11_bank_transfer_wait_notify.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | class Account { 10 | public: 11 | Account(string name, double money): mName(name), mMoney(money) {}; 12 | 13 | public: 14 | void changeMoney(double amount) { 15 | unique_lock lock(mMoneyLock); 16 | mConditionVar.wait(lock, [this, amount] { 17 | return mMoney + amount > 0; 18 | }); 19 | mMoney += amount; 20 | mConditionVar.notify_all(); 21 | } 22 | 23 | string getName() { 24 | return mName; 25 | } 26 | 27 | double getMoney() { 28 | return mMoney; 29 | } 30 | 31 | private: 32 | string mName; 33 | double mMoney; 34 | mutex mMoneyLock; 35 | condition_variable mConditionVar; 36 | }; 37 | 38 | class Bank { 39 | public: 40 | void addAccount(Account* account) { 41 | mAccounts.insert(account); 42 | } 43 | 44 | void transferMoney(Account* accountA, Account* accountB, double amount) { 45 | accountA->changeMoney(-amount); 46 | accountB->changeMoney(amount); 47 | } 48 | 49 | double totalMoney() const { 50 | double sum = 0; 51 | for (auto a : mAccounts) { 52 | sum += a->getMoney(); 53 | } 54 | return sum; 55 | } 56 | 57 | private: 58 | set mAccounts; 59 | }; 60 | 61 | mutex sCoutLock; 62 | void randomTransfer(Bank* bank, Account* accountA, Account* accountB) { 63 | while(true) { 64 | double randomMoney = ((double)rand() / RAND_MAX) * 100; 65 | { 66 | lock_guard guard(sCoutLock); 67 | cout << "Try to Transfer " << randomMoney 68 | << " from " << accountA->getName() << "(" << accountA->getMoney() 69 | << ") to " << accountB->getName() << "(" << accountB->getMoney() 70 | << "), Bank totalMoney: " << bank->totalMoney() << endl; 71 | } 72 | bank->transferMoney(accountA, accountB, randomMoney); 73 | } 74 | } 75 | 76 | int main() { 77 | Account a("Paul", 100); 78 | Account b("Moira", 100); 79 | 80 | Bank aBank; 81 | aBank.addAccount(&a); 82 | aBank.addAccount(&b); 83 | 84 | thread t1(randomTransfer, &aBank, &a, &b); 85 | thread t2(randomTransfer, &aBank, &b, &a); 86 | 87 | t1.join(); 88 | t2.join(); 89 | 90 | return 0; 91 | } -------------------------------------------------------------------------------- /example_code/cpp-concurrency-master/src/12_async_task.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | static const int MAX = 10e8; 10 | static double sum = 0; 11 | 12 | void worker(int min, int max) { 13 | for (int i = min; i <= max; i++) { 14 | sum += sqrt(i); 15 | } 16 | } 17 | 18 | class Worker { 19 | public: 20 | Worker(int min, int max): mMin(min), mMax(max) {} 21 | double work() { 22 | mResult = 0; 23 | for (int i = mMin; i <= mMax; i++) { 24 | mResult += sqrt(i); 25 | } 26 | return mResult; 27 | } 28 | double getResult() { 29 | return mResult; 30 | } 31 | 32 | private: 33 | int mMin; 34 | int mMax; 35 | double mResult; 36 | }; 37 | 38 | int main() { 39 | sum = 0; 40 | auto f1 = async(worker, 0, MAX); 41 | cout << "Async task triggered" << endl; 42 | f1.wait(); 43 | cout << "Async task finish, result: " << sum << endl << endl; 44 | 45 | double result = 0; 46 | cout << "Async task with lambda triggered, thread: " << this_thread::get_id() << endl; 47 | auto f2 = async(launch::async, [&result]() { 48 | cout << "Lambda task in thread: " << this_thread::get_id() << endl; 49 | for (int i = 0; i <= MAX; i++) { 50 | result += sqrt(i); 51 | } 52 | }); 53 | f2.wait(); 54 | cout << "Async task with lambda finish, result: " << result << endl << endl; 55 | 56 | Worker w(0, MAX); 57 | cout << "Task in class triggered" << endl; 58 | auto f3 = async(&Worker::work, &w); 59 | f3.wait(); 60 | cout << "Task in class finish, result: " << w.getResult() << endl << endl; 61 | 62 | return 0; 63 | } -------------------------------------------------------------------------------- /example_code/cpp-concurrency-master/src/13_packaged_task.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | static const int MAX = 10e8; 10 | 11 | double concurrent_worker(int min, int max) { 12 | double sum = 0; 13 | for (int i = min; i <= max; i++) { 14 | sum += sqrt(i); 15 | } 16 | return sum; 17 | } 18 | 19 | double concurrent_task(int min, int max) { 20 | vector> results; 21 | 22 | unsigned concurrent_count = thread::hardware_concurrency(); 23 | min = 0; 24 | for (int i = 0; i < concurrent_count; i++) { 25 | packaged_task task(concurrent_worker); 26 | results.push_back(task.get_future()); 27 | 28 | int range = max / concurrent_count * (i + 1); 29 | thread t(std::move(task), min, range); 30 | t.detach(); 31 | 32 | min = range + 1; 33 | } 34 | 35 | cout << "threads create finish" << endl; 36 | double sum = 0; 37 | for (auto& r : results) { 38 | sum += r.get(); 39 | } 40 | return sum; 41 | } 42 | 43 | int main() { 44 | auto start_time = chrono::steady_clock::now(); 45 | 46 | double r = concurrent_task(0, MAX); 47 | 48 | auto end_time = chrono::steady_clock::now(); 49 | auto ms = chrono::duration_cast(end_time - start_time).count(); 50 | cout << "Concurrent task finish, " << ms << " ms consumed, Result: " << r << endl; 51 | return 0; 52 | } -------------------------------------------------------------------------------- /example_code/cpp-concurrency-master/src/14_promise_future.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | static const int MAX = 10e8; 10 | 11 | double concurrent_worker(int min, int max) { 12 | double sum = 0; 13 | for (int i = min; i <= max; i++) { 14 | sum += sqrt(i); 15 | } 16 | return sum; 17 | } 18 | 19 | void concurrent_task(int min, int max, promise* result) { 20 | vector> results; 21 | 22 | unsigned concurrent_count = thread::hardware_concurrency(); 23 | min = 0; 24 | for (int i = 0; i < concurrent_count; i++) { 25 | packaged_task task(concurrent_worker); 26 | results.push_back(task.get_future()); 27 | 28 | int range = max / concurrent_count * (i + 1); 29 | thread t(std::move(task), min, range); 30 | t.detach(); 31 | 32 | min = range + 1; 33 | } 34 | 35 | cout << "threads create finish" << endl; 36 | double sum = 0; 37 | for (auto& r : results) { 38 | sum += r.get(); 39 | } 40 | result->set_value(sum); 41 | cout << "concurrent_task finish" << endl; 42 | } 43 | 44 | int main() { 45 | auto start_time = chrono::steady_clock::now(); 46 | 47 | promise sum; 48 | concurrent_task(0, MAX, &sum); 49 | 50 | auto end_time = chrono::steady_clock::now(); 51 | auto ms = chrono::duration_cast(end_time - start_time).count(); 52 | cout << "Concurrent task finish, " << ms << " ms consumed." << endl; 53 | cout << "Result: " << sum.get_future().get() << endl; 54 | return 0; 55 | } -------------------------------------------------------------------------------- /example_code/cpp-concurrency-master/src/15_parallel_algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | void generateRandomData(vector& collection, int size) { 11 | random_device rd; 12 | mt19937 mt(rd()); 13 | uniform_real_distribution dist(1.0, 100.0); 14 | for (int i = 0; i < size; i++) { 15 | collection.push_back(dist(mt)); 16 | } 17 | } 18 | 19 | int main() { 20 | vector collection; 21 | generateRandomData(collection, 10e6); 22 | 23 | vector copy1(collection); 24 | vector copy2(collection); 25 | vector copy3(collection); 26 | 27 | auto time1 = chrono::steady_clock::now(); 28 | sort(execution::seq, copy1.begin(), copy1.end()); 29 | auto time2 = chrono::steady_clock::now(); 30 | auto duration = chrono::duration_cast(time2 - time1).count(); 31 | cout << "Sequenced sort consuming " << duration << "ms." << endl; 32 | 33 | auto time3 = chrono::steady_clock::now(); 34 | sort(execution::par, copy2.begin(),copy2.end()); 35 | auto time4 = chrono::steady_clock::now(); 36 | duration = chrono::duration_cast(time4 - time3).count(); 37 | cout << "Parallel sort consuming " << duration << "ms." << endl; 38 | 39 | auto time5 = chrono::steady_clock::now(); 40 | sort(execution::par_unseq, copy2.begin(),copy2.end()); 41 | auto time6 = chrono::steady_clock::now(); 42 | duration = chrono::duration_cast(time6 - time5).count(); 43 | cout << "Parallel unsequenced sort consuming " << duration << "ms." << endl; 44 | } -------------------------------------------------------------------------------- /example_code/cpp-concurrency-master/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.8) 2 | project(cpp-concurrency) 3 | 4 | set(CMAKE_CXX_COMPILER "g++-9") 5 | set(CMAKE_CXX_STANDARD 17) 6 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 7 | 8 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ./bin) 9 | 10 | add_executable(hello_thread 01_hello_thread.cpp) 11 | add_executable(lambda_thread 02_lambda_thread.cpp) 12 | add_executable(thread_argument 03_thread_argument.cpp) 13 | add_executable(thread_self_manage 04_thread_self_manage.cpp) 14 | add_executable(call_once 05_call_once.cpp) 15 | add_executable(naive_multithread 06_naive_multithread.cpp) 16 | add_executable(mutex_lock 07_mutex_lock.cpp) 17 | add_executable(improved_mutex_lock 08_improved_mutex_lock.cpp) 18 | add_executable(deadlock_bank_transfer 09_deadlock_bank_transfer.cpp) 19 | add_executable(improved_bank_transfer 10_improved_bank_transfer.cpp) 20 | add_executable(bank_transfer_wait_notify 11_bank_transfer_wait_notify.cpp) 21 | add_executable(async_task 12_async_task.cpp) 22 | add_executable(packaged_task 13_packaged_task.cpp) 23 | add_executable(promise_future 14_promise_future.cpp) 24 | 25 | # For OS X 26 | if(APPLE) 27 | if (DEFINED ENV{tbb_path}) 28 | message("tbb_path=" $ENV{tbb_path}) 29 | include_directories($ENV{tbb_path}/include/) 30 | link_directories($ENV{tbb_path}/lib/) 31 | add_executable(parallel_algorithm 15_parallel_algorithm.cpp) 32 | target_link_libraries(parallel_algorithm tbb) 33 | else() 34 | message("[Warning] 'tbb_path' not defined, 'export tbb_path=xxx' to build parallel algorithm.") 35 | endif() 36 | endif() 37 | 38 | # For Linux 39 | IF("${CMAKE_SYSTEM}" MATCHES "Linux") 40 | add_executable(parallel_algorithm 15_parallel_algorithm.cpp) 41 | target_link_libraries(parallel_algorithm tbb) 42 | target_link_libraries(hello_thread pthread) 43 | target_link_libraries(lambda_thread pthread) 44 | target_link_libraries(thread_argument pthread) 45 | target_link_libraries(thread_self_manage pthread) 46 | target_link_libraries(call_once pthread) 47 | target_link_libraries(naive_multithread pthread) 48 | target_link_libraries(mutex_lock pthread) 49 | target_link_libraries(improved_mutex_lock pthread) 50 | target_link_libraries(deadlock_bank_transfer pthread) 51 | target_link_libraries(improved_bank_transfer pthread) 52 | target_link_libraries(bank_transfer_wait_notify pthread) 53 | target_link_libraries(async_task pthread) 54 | target_link_libraries(packaged_task pthread) 55 | target_link_libraries(promise_future pthread) 56 | endif() 57 | 58 | -------------------------------------------------------------------------------- /example_code/cpp/ConsistentHash.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/example_code/cpp/ConsistentHash.cpp -------------------------------------------------------------------------------- /example_code/cpp/macro.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | #define mymax(a,b) (a>b?a:b) 8 | #define MALLOC(n, type) \ 9 | ((type *) malloc((n)* sizeof(type))) 10 | 11 | #define myswap(a,b) \ 12 | int tmp = 10;\ 13 | a = a + b;\ 14 | b = a - b;\ 15 | a = a - b;\ 16 | a = tmp; 17 | 18 | #define macro_test(a)\ 19 | cout< 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | class OBSERVERABLE; 8 | 9 | class OBSERVER 10 | { 11 | private: 12 | OBSERVERABLE *_subject; 13 | 14 | public: 15 | void observe(OBSERVERABLE *subject); 16 | ~OBSERVER(); 17 | virtual void update() = 0; 18 | }; 19 | 20 | class OBSERVERABLE 21 | { 22 | private: 23 | vector _observers; 24 | 25 | public: 26 | void notify(); 27 | void myregister(OBSERVER *observer); 28 | void unregister(OBSERVER *observer); 29 | }; 30 | 31 | void OBSERVER::observe(OBSERVERABLE *subject) 32 | { 33 | _subject = subject; 34 | _subject->myregister(this); 35 | } 36 | 37 | OBSERVER::~OBSERVER() 38 | { 39 | _subject->unregister(this); 40 | } 41 | 42 | void OBSERVERABLE::notify() 43 | { 44 | for (int i = 0; i < _observers.size(); i++) 45 | { 46 | _observers[i]->update(); 47 | } 48 | } 49 | 50 | void OBSERVERABLE::myregister(OBSERVER *observer) 51 | { 52 | _observers.push_back(observer); 53 | } 54 | 55 | void OBSERVERABLE::unregister(OBSERVER *observer) 56 | { 57 | auto iter = find(_observers.begin(), _observers.end(), observer); 58 | if (iter != _observers.end()) 59 | { 60 | swap(*iter, _observers.back()); 61 | _observers.pop_back(); 62 | } 63 | } 64 | 65 | class TEST_OBSERVER : public OBSERVER 66 | { 67 | public: 68 | virtual void update() 69 | { 70 | cout << "foo update" << endl; 71 | } 72 | }; 73 | 74 | int main() 75 | { 76 | TEST_OBSERVER *t = new TEST_OBSERVER; 77 | OBSERVERABLE subject; 78 | t->observe(&subject); 79 | 80 | subject.notify(); 81 | 82 | delete t; 83 | subject.notify(); 84 | 85 | return 0; 86 | } -------------------------------------------------------------------------------- /example_code/epoll/client.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/example_code/epoll/client.c -------------------------------------------------------------------------------- /example_code/epoll/readme.md: -------------------------------------------------------------------------------- 1 | #### epoll的demo例子 2 | 3 | --server.cpp 服务器进程 4 | 5 | --client.cpp 客户端进程 -------------------------------------------------------------------------------- /example_code/epoll/server.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/example_code/epoll/server.c -------------------------------------------------------------------------------- /example_code/function/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int MyFunction(int x, int y); 11 | int MyFunctionNew(int x, int y); 12 | 13 | char new_func[] = 14 | { 15 | 0x55, 16 | 0x48, 0x89, 0xe5, 17 | 0x89, 0x7d, 0xec, 18 | 0x89, 0x75, 0xe8, 19 | 20 | 0xc7, 0x45, 0xfc, 0x0a, 0x00, 0x00, 0x00, 21 | 22 | 0xc7, 0x45, 0xf8, 0x01, 0x00, 0x00, 0x00, 23 | 24 | 0x8b, 0x45, 0xfc, 25 | 0x5d, 26 | 0xc3 27 | }; 28 | 29 | void sig_user1_handler(int sig, siginfo_t *si, void *data) 30 | { 31 | int pagesize = sysconf(_SC_PAGE_SIZE); 32 | if (pagesize < 0) { 33 | pagesize = 4096; 34 | } 35 | 36 | int len = sizeof(new_func); 37 | 38 | uintptr_t addr = (((uintptr_t)MyFunction) / pagesize) * pagesize; 39 | fprintf(stderr, "%s: iminus: %p, aligned: 0x%lx, sz %d\n", __func__, MyFunction, addr, len); 40 | if (mprotect((void*)addr, (uintptr_t)MyFunction - addr + len, PROT_WRITE|PROT_READ|PROT_EXEC) < 0) { 41 | fprintf(stderr, "%s\n", strerror(errno)); 42 | } 43 | 44 | memcpy((void*)MyFunction, (void*)new_func, len); 45 | 46 | if (mprotect((void*)addr, (uintptr_t)MyFunction - addr + len, PROT_READ|PROT_EXEC) < 0) { 47 | fprintf(stderr, "%s\n", strerror(errno)); 48 | } 49 | } 50 | 51 | int MyFunction(int x, int y) 52 | { 53 | int a, b; 54 | a = 10; 55 | b = 1; 56 | 57 | int val = a * x + b * y; 58 | return val; 59 | } 60 | 61 | int MyFunctionNew(int x, int y) 62 | { 63 | int a = 10; 64 | return a; 65 | } 66 | 67 | int main() 68 | { 69 | struct sigaction newact, oldact; 70 | sigemptyset(&newact.sa_mask); 71 | newact.sa_sigaction = sig_user1_handler; 72 | sigaction(SIGUSR1, &newact, &oldact); 73 | 74 | void * ptr = &MyFunction; 75 | printf("addr %p , sizeof %d\n", ptr, sizeof(new_func)); 76 | 77 | int a = 10; 78 | int b = 10; 79 | 80 | while (1) 81 | { 82 | int val = MyFunction(a, b); 83 | printf("val : %d \n", val); 84 | sleep(3); 85 | } 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /example_code/function/test_asm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void function() 6 | { 7 | while(1) 8 | { 9 | printf("hello,function!\n"); 10 | sleep(1); 11 | } 12 | } 13 | 14 | void test() 15 | { 16 | int val = 10; 17 | printf("val %d\n", val); 18 | 19 | // set val = 11 20 | asm("movl $0xb, -0x4(%rbp)"); 21 | printf("val %d\n", val); 22 | 23 | long addr = function; 24 | asm("movl $0x401156, 0x18(%rbp)"); 25 | } 26 | 27 | int main() 28 | { 29 | printf("addr %p \n", &function); 30 | test(); 31 | printf("hello,world!\n"); 32 | return 0; 33 | } 34 | 35 | // https://blog.csdn.net/yiftss/article/details/89474622 -------------------------------------------------------------------------------- /example_code/function/test_jmp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | jmp_buf env; 6 | 7 | int my_func(int a, int b) 8 | { 9 | if (b == 0) { 10 | printf("do not allow division by 0\n"); 11 | longjmp(env, 1); 12 | } 13 | return a / b; 14 | } 15 | 16 | int main(int argc, char const *argv[]) 17 | { 18 | int res = setjmp(env); 19 | if (res == 0) { 20 | printf("return from setjmp\n"); 21 | my_func(10, 0); 22 | } else { 23 | printf("return from longjmp: %d\n", res); 24 | } 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /example_code/grpc_demo/demo/customer/customer.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package customer; 3 | 4 | // The Customer sercie definition 5 | service Customer { 6 | // Get all Customers with filter - A server-to-client streaming RPC. 7 | rpc GetCustomers(CustomerFilter) returns (stream CustomerRequest) {} 8 | 9 | // Create a new Customer - A simple RPC 10 | rpc CreateCustomer (CustomerRequest) returns (CustomerResponse) {} 11 | } 12 | 13 | message CustomerRequest { 14 | int32 id = 1; // Unique ID number for a Customer. 15 | string name = 2; 16 | string email = 3; 17 | string phone = 4; 18 | 19 | message Address { 20 | string street = 1; 21 | string city = 2; 22 | string state = 3; 23 | string zip = 4; 24 | bool isShippingAddress = 5; 25 | } 26 | 27 | repeated Address addresses = 5; 28 | } 29 | 30 | message CustomerResponse { 31 | int32 id = 1; 32 | bool success = 2; 33 | } 34 | 35 | message CustomerFilter { 36 | string keyword = 1; 37 | } -------------------------------------------------------------------------------- /example_code/grpc_demo/demo/main.go: -------------------------------------------------------------------------------- 1 | // server/main.go 2 | package main 3 | 4 | import ( 5 | "log" 6 | "net" 7 | "strings" 8 | 9 | "golang.org/x/net/context" 10 | "google.golang.org/grpc" 11 | 12 | pb "./customer" 13 | ) 14 | 15 | const ( 16 | port = ":50051" 17 | ) 18 | 19 | // server is used to implement customer.CustomerServer. 20 | type server struct { 21 | savedCustomers []*pb.CustomerRequest 22 | } 23 | 24 | // CreateCustomer creates a new Customer 25 | func (s *server) CreateCustomer(ctx context.Context, in *pb.CustomerRequest) (*pb.CustomerResponse, error) { 26 | s.savedCustomers = append(s.savedCustomers, in) 27 | return &pb.CustomerResponse{Id: in.Id, Success: true}, nil 28 | } 29 | 30 | // GetCustomers returns all customers by given filter 31 | func (s *server) GetCustomers(filter *pb.CustomerFilter, stream pb.Customer_GetCustomersServer) error { 32 | for _, customer := range s.savedCustomers { 33 | if filter.Keyword != "" { 34 | if !strings.Contains(customer.Name, filter.Keyword) { 35 | continue 36 | } 37 | } 38 | if err := stream.Send(customer); err != nil { 39 | return err 40 | } 41 | } 42 | return nil 43 | } 44 | 45 | func main() { 46 | lis, err := net.Listen("tcp", port) 47 | if err != nil { 48 | log.Fatal("failed to listen: %v", err) 49 | } 50 | 51 | //Create a new grpc server 52 | s := grpc.NewServer() 53 | pb.RegisterCustomerServer(s, &server{}) 54 | s.Serve(lis) 55 | } 56 | -------------------------------------------------------------------------------- /example_code/grpc_demo/demo/readme.md: -------------------------------------------------------------------------------- 1 | ## rpc demo 2 | 3 | 一个简单的rpc demo 4 | 1. proto包含两个服务 5 | 2. proto里面包含了一个数组的定义方式 6 | 3. proto里面的两个rpc,一个是普通的rpc,一个是单边流的rpc -------------------------------------------------------------------------------- /example_code/grpc_demo/stream_rpc/client.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "io" 7 | "strconv" 8 | 9 | "time" 10 | 11 | pb "./hellostream" 12 | "google.golang.org/grpc" 13 | ) 14 | 15 | func main() { 16 | conn, e := grpc.Dial("localhost:6001", grpc.WithInsecure()) 17 | if e != nil { 18 | fmt.Println(e.Error()) 19 | return 20 | } 21 | defer conn.Close() 22 | c := pb.NewHelloServiceClient(conn) 23 | 24 | // // say hello 25 | // r, e := c.SayHello(context.Background(), &pb.HelloRequest{Username: "ft"}) 26 | // if e != nil { 27 | // fmt.Println(e.Error()) 28 | // return 29 | // } 30 | // fmt.Println(r.Message) 31 | 32 | // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 33 | // chat 34 | chatClilent, e := c.Chat(context.Background()) 35 | if e != nil { 36 | fmt.Println(e.Error()) 37 | return 38 | } 39 | go func() { 40 | for { 41 | time.Sleep(3 * time.Second) 42 | stream, e := chatClilent.Recv() 43 | if e == io.EOF { 44 | fmt.Println("EOF") 45 | return 46 | } 47 | if e != nil { 48 | fmt.Println("-----err:", e) 49 | return 50 | } 51 | fmt.Println("client recv:", string(stream.Stream)) 52 | } 53 | }() 54 | 55 | go func() { 56 | i := 0 57 | for { 58 | time.Sleep(3 * time.Second) 59 | chatClilent.Send(&pb.ClientStream{Stream: []byte("client send i:" + strconv.Itoa(i))}) 60 | i++ 61 | } 62 | }() 63 | select { 64 | case <-time.After(20 * time.Second): 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /example_code/grpc_demo/stream_rpc/hellostream/hellostream.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package pb; 3 | 4 | message HelloRequest { 5 | string username = 1; 6 | } 7 | 8 | message HelloResponse { 9 | string message = 1; 10 | } 11 | 12 | // + 13 | message ClientStream { 14 | bytes stream = 1; 15 | } 16 | message ServerStream { 17 | bytes stream = 1; 18 | } 19 | service HelloService { 20 | rpc SayHello(HelloRequest) returns (HelloResponse){} 21 | 22 | rpc Chat(stream ClientStream) returns (stream ServerStream){} 23 | } -------------------------------------------------------------------------------- /example_code/grpc_demo/stream_rpc/readme.md: -------------------------------------------------------------------------------- 1 | ## 双边stream的rpc demo 2 | -------------------------------------------------------------------------------- /example_code/grpc_demo/stream_rpc/server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "io" 7 | "net" 8 | "strconv" 9 | "time" 10 | 11 | pb "./hellostream" 12 | "google.golang.org/grpc" 13 | ) 14 | 15 | type HelloService struct { 16 | } 17 | 18 | func (hs *HelloService) SayHello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloResponse, error) { 19 | return &pb.HelloResponse{Message: fmt.Sprintf("hello ,%s", req.Username)}, nil 20 | } 21 | 22 | func (hs *HelloService) Chat(conn pb.HelloService_ChatServer) error { 23 | go func() { 24 | var i int = 100 25 | for { 26 | time.Sleep(2 * time.Second) 27 | conn.Send(&pb.ServerStream{Stream: []byte("server send i:" + strconv.Itoa(i))}) 28 | i++ 29 | } 30 | }() 31 | 32 | for { 33 | time.Sleep(2 * time.Second) 34 | stream, err := conn.Recv() 35 | if err == io.EOF { 36 | return nil 37 | } 38 | if err != nil { 39 | return err 40 | } 41 | fmt.Println("server recv:", string(stream.Stream)) 42 | // fmt.Println("receive from client:", stream.Stream) 43 | 44 | } 45 | 46 | return nil 47 | } 48 | 49 | // ++++++++++++++++++++ 50 | 51 | func main() { 52 | lis, err := net.Listen("tcp", ":6001") 53 | if err != nil { 54 | fmt.Println(err.Error()) 55 | return 56 | } 57 | s := grpc.NewServer() 58 | pb.RegisterHelloServiceServer(s, &HelloService{}) 59 | go func() { 60 | s.Serve(lis) 61 | }() 62 | 63 | fmt.Println("fmt info : ", s.GetServiceInfo()) 64 | select {} 65 | } 66 | 67 | // func newBytes(a ...byte) []byte { 68 | // return a 69 | // } 70 | -------------------------------------------------------------------------------- /example_code/linux_perf_example/high_iowait_process/app.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #define BUF_SIZE 64*1024*1024 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | char* select_disk() { 16 | DIR* dirptr = opendir("/dev/"); 17 | if (dirptr==NULL) { 18 | perror("Failed to open dir"); 19 | return NULL; 20 | } 21 | 22 | struct dirent *entry; 23 | char* result = (char*)calloc(512, sizeof(char)); 24 | const char* sd_prefix = "sd"; 25 | const char* xvd_prefix = "xvd"; 26 | while(entry=readdir(dirptr)) { 27 | if(strncmp(sd_prefix, entry->d_name, 2)==0 || strncmp(xvd_prefix, entry->d_name, 3)==0) { 28 | snprintf(result, 512*sizeof(char), "/dev/%s", entry->d_name); 29 | return result; 30 | } 31 | } 32 | 33 | free(result); 34 | return NULL; 35 | } 36 | 37 | void sub_process() 38 | { 39 | char* disk = select_disk(); 40 | if (disk == NULL) { 41 | _exit(1); 42 | } 43 | 44 | int fd = open(disk, O_RDONLY|O_DIRECT|O_LARGEFILE, 0755); 45 | if (fd<0) { 46 | perror("failed to open disk"); 47 | free(disk); 48 | _exit(1); 49 | } 50 | 51 | unsigned char* buf; 52 | posix_memalign((void **)&buf, 512, BUF_SIZE); 53 | int read_bytes=0; 54 | while (read_bytes < 20 * BUF_SIZE) 55 | { 56 | int ret = read(fd, buf, BUF_SIZE); 57 | if (ret < 0) 58 | { 59 | perror("failed to read contents"); 60 | close(fd); 61 | free(disk); 62 | free(buf); 63 | _exit(1); 64 | } 65 | read_bytes += ret; 66 | } 67 | 68 | close(fd); 69 | free(disk); 70 | free(buf); 71 | _exit(0); 72 | 73 | } 74 | 75 | int main(void) 76 | { 77 | int status = 0; 78 | for (;;) { 79 | for (int i = 0; i < 2; i++) { 80 | if(fork()== 0) { 81 | sub_process(); 82 | } 83 | } 84 | sleep(5); 85 | } 86 | 87 | while(wait(&status)>0); 88 | return 0; 89 | } -------------------------------------------------------------------------------- /example_code/linux_perf_example/perf_demo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | int func1() 12 | { 13 | int val = 0; 14 | for(int i=0;i<100000000;i++) 15 | { 16 | val = val * i; 17 | } 18 | return val; 19 | } 20 | 21 | int func2() 22 | { 23 | int val = 0; 24 | for (int i=0;i<50;i++) 25 | { 26 | val = val * func1(); 27 | usleep(100); 28 | printf("test print %d \n",i); 29 | } 30 | return val; 31 | } 32 | 33 | int main() 34 | { 35 | func2(); 36 | } -------------------------------------------------------------------------------- /example_code/linux_perf_example/readme.md: -------------------------------------------------------------------------------- 1 | # linux 性能优化 -------------------------------------------------------------------------------- /example_code/lua/build.sh: -------------------------------------------------------------------------------- 1 | dependencies_include_path=/data/home/your_path 2 | dependencies_lib_path=/data/home/your_lib 3 | 4 | g++ -g -I${dependencies_include_path}/lua-5.1.4/src -L ${dependencies_lib_path} -llua -Wl,-rpath=${dependencies_lib_path} test.cpp -o test -------------------------------------------------------------------------------- /example_code/lua/test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | extern "C" { 6 | #include "lua.h" 7 | #include "lualib.h" 8 | #include "lauxlib.h" 9 | } 10 | 11 | // c --> 调用lua --> add_exp --> 调用c 12 | class ACTOR 13 | { 14 | public: 15 | int id; 16 | int exp; 17 | std::string lua_str; 18 | }; 19 | 20 | struct USE_LUA_ENV 21 | { 22 | ACTOR * actor_ptr; 23 | }; 24 | 25 | // lua function 26 | USE_LUA_ENV g_use_lua_env; 27 | 28 | int init_lua_env(); 29 | int lua_env_set(ACTOR * actor); 30 | int lua_env_unset(); 31 | int addexp(lua_State* L); 32 | 33 | int exec_buff(ACTOR * actor) 34 | { 35 | lua_State* L = luaL_newstate(); 36 | luaL_openlibs(L); 37 | 38 | // 将指定的函数注册为Lua的全局函数变量,其中第一个字符串参数为Lua代码 39 | // 在调用C函数时使用的全局函数名,第二个参数为实际C函数的指针。 40 | lua_register(L, "addexp", addexp); 41 | 42 | lua_env_set(actor); 43 | 44 | // 在注册完所有的C函数之后,即可在Lua的代码块中使用这些已经注册的C函数了。 45 | if (luaL_dostring(L, actor->lua_str.c_str())) 46 | { 47 | printf("Failed to invoke.\n"); 48 | } 49 | 50 | lua_env_unset(); 51 | lua_close(L); 52 | printf("actor exec lua buff end \n"); 53 | return 0; 54 | } 55 | 56 | int main() 57 | { 58 | ACTOR * actor = new ACTOR(); 59 | actor->lua_str = "addexp(100)"; 60 | actor->exp = 5; 61 | actor->id = 10000; 62 | 63 | exec_buff(actor); 64 | return 0; 65 | } 66 | 67 | int init_lua_env() 68 | { 69 | memset(&g_use_lua_env, 0, sizeof(g_use_lua_env)); 70 | return 0; 71 | } 72 | 73 | int lua_env_set(ACTOR * actor) 74 | { 75 | g_use_lua_env.actor_ptr = actor; 76 | } 77 | 78 | int lua_env_unset() 79 | { 80 | g_use_lua_env.actor_ptr = 0; 81 | } 82 | 83 | int addexp(lua_State* L) 84 | { 85 | int exp = luaL_checknumber(L,1); 86 | 87 | ACTOR * actor = g_use_lua_env.actor_ptr; 88 | if (actor == NULL) {return -1;} 89 | 90 | actor->exp += exp; 91 | printf("id %d, add exp %d, cur exp %d\n", actor->id, exp, actor->exp); 92 | return 0; 93 | } -------------------------------------------------------------------------------- /example_code/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | // modify by github web 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /example_code/memleak_check/mem_hook/hook_demo/example/checkpasswd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/example_code/memleak_check/mem_hook/hook_demo/example/checkpasswd -------------------------------------------------------------------------------- /example_code/memleak_check/mem_hook/hook_demo/example/checkpasswd.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | int main(int argc, char **argv) 6 | { 7 | char passwd[] = "password"; 8 | if (argc < 2) 9 | { 10 | printf("Usage: %s \n", argv[0]); 11 | return 1; 12 | } 13 | 14 | if (!strcmp(passwd, argv[1])) 15 | { 16 | printf("Correct Password!\n"); 17 | return 0; 18 | } 19 | 20 | printf("Invalid Password!\n"); 21 | return 1; 22 | } 23 | 24 | // g++ -Wall -fPIC -shared -o hack.so hack.cpp -ldl 25 | // g++ checkpasswd.cpp -o checkpasswd 26 | // LD_PRELOAD=./hack.so ./checkpasswd 90 -------------------------------------------------------------------------------- /example_code/memleak_check/mem_hook/hook_demo/example/hack.cpp: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | 3 | #include 4 | #include 5 | 6 | extern "C" int strcmp(const char *s1, const char *s2) 7 | { 8 | printf("hack function invoked. s1=<%s> s2=<%s>\n", s1, s2); 9 | return 0; 10 | } -------------------------------------------------------------------------------- /example_code/memleak_check/mem_hook/hook_demo/example/hack.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/example_code/memleak_check/mem_hook/hook_demo/example/hack.so -------------------------------------------------------------------------------- /example_code/memleak_check/mem_hook/hook_demo/example2/myfopen.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | 3 | #include 4 | #include 5 | 6 | FILE *fopen(const char *path, const char *mode) { 7 | printf("In our own fopen, opening %s\n", path); 8 | 9 | FILE *(*original_fopen)(const char*, const char*); 10 | original_fopen = dlsym(RTLD_NEXT, "fopen"); 11 | return (*original_fopen)(path, mode); 12 | } 13 | 14 | int strcmp(const char *s1, const char *s2) 15 | { 16 | printf("hack function invoked. s1=<%s> s2=<%s>\n", s1, s2); 17 | return 0; 18 | } -------------------------------------------------------------------------------- /example_code/memleak_check/mem_hook/hook_demo/example2/myfopen.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/example_code/memleak_check/mem_hook/hook_demo/example2/myfopen.so -------------------------------------------------------------------------------- /example_code/memleak_check/mem_hook/hook_demo/example2/prog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/example_code/memleak_check/mem_hook/hook_demo/example2/prog -------------------------------------------------------------------------------- /example_code/memleak_check/mem_hook/hook_demo/example2/prog.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(void) { 5 | printf("Calling the fopen() function...\n"); 6 | 7 | FILE *fd = fopen("test.txt", "r"); 8 | if (!fd) { 9 | printf("fopen() returned NULL\n"); 10 | } 11 | 12 | printf("fopen() succeeded\n"); 13 | 14 | char passwd1[] = "password123"; 15 | char passwd2[] = "password3435"; 16 | if (!strcmp(passwd1, passwd2)) 17 | { 18 | printf("Correct Password!\n"); 19 | return 0; 20 | } 21 | printf("unCorrect Password!\n"); 22 | return 0; 23 | } 24 | 25 | // gcc -Wall -fPIC -shared -o myfopen.so myfopen.c -ldl 26 | // gcc prog.c -o prog 27 | // LD_PRELOAD=./myfopen.so ./prog 28 | // unset LD_PRELOAD -------------------------------------------------------------------------------- /example_code/memleak_check/mem_hook/macro.h: -------------------------------------------------------------------------------- 1 | #ifndef __MACRO_H__ 2 | #define __MACRO_H__ 3 | 4 | #define new new(__FILE__, __LINE__) 5 | 6 | #endif -------------------------------------------------------------------------------- /example_code/memleak_check/mem_hook/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "test1.h" 4 | #include "test2.h" 5 | 6 | using namespace std; 7 | 8 | struct A { 9 | int a; 10 | }; 11 | 12 | int main() 13 | { 14 | test_func1(); 15 | test_func2(); 16 | 17 | cout << "=====" << endl; 18 | { 19 | int * q1 = new int(); 20 | delete q1; 21 | } 22 | { 23 | std::cout <<"\nshared ptr" << std::endl; 24 | shared_ptr a = make_shared(); 25 | } 26 | 27 | // int * p = new(__FILE__, __LINE__) int; 28 | // int * q = new int(); 29 | // int * arr = new int[10]; 30 | 31 | // delete p; 32 | // delete q; 33 | // delete arr; 34 | 35 | // { 36 | // int * q1 = new int(); 37 | // delete q1; 38 | // } 39 | // { 40 | // int * q2 = new int(); 41 | // delete q2; 42 | // } 43 | 44 | // { 45 | // cout << "test shared ptr" < a = make_shared(); 47 | // } 48 | return 0; 49 | } 50 | 51 | // g++ main.cpp test1.cpp test2.cpp memory_op.cpp -Wl,-wrap=malloc -Wl,-wrap=free -------------------------------------------------------------------------------- /example_code/memleak_check/mem_hook/memory_op.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | extern "C" void * __real_malloc(size_t size); 9 | extern "C" void __real_free(void *ptr); 10 | 11 | void * operator new (size_t size) 12 | { 13 | cout << endl << "new size : " << size << endl ; 14 | void *p = malloc(size); 15 | return p; 16 | } 17 | 18 | void * operator new[] (size_t size) 19 | { 20 | cout << endl << "new size[] : " << size << endl ; 21 | void *p = malloc(size); 22 | return p; 23 | } 24 | 25 | void* operator new (size_t size , const char *file , 26 | unsigned int line ) { 27 | if (void *ptr = malloc (size)) 28 | { 29 | cout << endl << "new size : " << size <<", file : " << file << " "<< line << endl ; 30 | return ptr ; 31 | } 32 | throw std::bad_alloc () ; 33 | } 34 | 35 | void operator delete (void *ptr ) 36 | { 37 | if (ptr == nullptr) return ; 38 | 39 | cout << ptr << "\tsource has been released !" << endl ; 40 | free (ptr); 41 | ptr = nullptr; 42 | } 43 | 44 | 45 | extern "C" void * __wrap_malloc(size_t size) { 46 | printf("my malloc: %zu\n", size); 47 | return __real_malloc(size); 48 | } 49 | 50 | extern "C" void __wrap_free(void *ptr) { 51 | printf("my free: %p\n", ptr); 52 | __real_free(ptr); 53 | } -------------------------------------------------------------------------------- /example_code/memleak_check/mem_hook/memory_op.h: -------------------------------------------------------------------------------- 1 | #ifndef __MEM_H__ 2 | #define __MEM_H__ 3 | 4 | void* operator new (size_t size , const char *file , 5 | unsigned int line ); 6 | 7 | #endif -------------------------------------------------------------------------------- /example_code/memleak_check/mem_hook/test1.cpp: -------------------------------------------------------------------------------- 1 | #include "test1.h" 2 | 3 | int test_func1() 4 | { 5 | { 6 | int * q1 = new int(); 7 | delete q1; 8 | } 9 | return 0; 10 | } -------------------------------------------------------------------------------- /example_code/memleak_check/mem_hook/test1.h: -------------------------------------------------------------------------------- 1 | #ifndef __TEST1_H__ 2 | #define __TEST1_H__ 3 | 4 | int test_func1(); 5 | 6 | #endif -------------------------------------------------------------------------------- /example_code/memleak_check/mem_hook/test2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "memory_op.h" 3 | #include "macro.h" 4 | 5 | int test_func2() 6 | { 7 | { 8 | int * q1 = new int(); 9 | delete q1; 10 | } 11 | return 0; 12 | } -------------------------------------------------------------------------------- /example_code/memleak_check/mem_hook/test2.h: -------------------------------------------------------------------------------- 1 | #ifndef __TEST2_H__ 2 | #define __TEST2_H__ 3 | 4 | int test_func2(); 5 | 6 | #endif -------------------------------------------------------------------------------- /example_code/memleak_check/mem_leak_tool/macro.h: -------------------------------------------------------------------------------- 1 | #ifndef __MACRO_H__ 2 | #define __MACRO_H__ 3 | 4 | #define new new(__FILE__, __LINE__) 5 | 6 | #endif -------------------------------------------------------------------------------- /example_code/memleak_check/mem_leak_tool/memery_op.h: -------------------------------------------------------------------------------- 1 | #ifndef __MEMERY_OP_H__ 2 | #define __MEMERY_OP_H__ 3 | 4 | #include 5 | 6 | const int _DEBUG_NEW_FILENAME_LEN = 200; 7 | const int DEBUG_NEW_MAGIC = 0xFFFF; 8 | const int ALIGNED_LIST_ITEM_SIZE = 1024; 9 | 10 | struct new_ptr_list_t 11 | { 12 | new_ptr_list_t* next; 13 | new_ptr_list_t* prev; 14 | std::size_t size; 15 | union 16 | { 17 | char file[_DEBUG_NEW_FILENAME_LEN]; 18 | void* addr; 19 | }; 20 | unsigned line; 21 | bool is_array; 22 | int magic; 23 | 24 | new_ptr_list_t() 25 | { 26 | next = NULL; 27 | prev = NULL; 28 | } 29 | }; 30 | 31 | int checkLeaks(); 32 | void * operator new(size_t size); 33 | void * operator new(size_t size, const char *file, unsigned int line); 34 | #endif -------------------------------------------------------------------------------- /example_code/memleak_check/mem_leak_tool/prog.cpp: -------------------------------------------------------------------------------- 1 | #include "memery_op.h" 2 | #include 3 | #include 4 | #include "macro.h" 5 | 6 | using namespace std; 7 | 8 | struct A { 9 | int a; 10 | }; 11 | 12 | int main() 13 | { 14 | { 15 | int * q1 = new int(); 16 | // delete q1; 17 | 18 | // shared_ptr a = make_shared(); 19 | checkLeaks(); 20 | } 21 | 22 | // { 23 | // int * q1 = new int(); 24 | // delete q1; 25 | // } 26 | // checkLeaks(); 27 | return 0; 28 | } 29 | 30 | // g++ memery_op.cpp prog.cpp -------------------------------------------------------------------------------- /example_code/mult_file_no_static_obj_init/Makefile: -------------------------------------------------------------------------------- 1 | plan1: 2 | g++ -o plan1 main.cpp file2.cpp file1.cpp 3 | 4 | plan2: 5 | g++ -o plan2 main.cpp file1.cpp file2.cpp -------------------------------------------------------------------------------- /example_code/mult_file_no_static_obj_init/file1.cpp: -------------------------------------------------------------------------------- 1 | #include "file1.h" 2 | #include "file2.h" 3 | #include 4 | using namespace std; 5 | 6 | TEST1::TEST1() 7 | { 8 | val1 = test2.val1 * test2.val2; // 构造test1初始化依赖于test2对象 9 | cout << "init test1" << endl; 10 | } 11 | 12 | TEST1 test1; -------------------------------------------------------------------------------- /example_code/mult_file_no_static_obj_init/file1.h: -------------------------------------------------------------------------------- 1 | #ifndef __file_1_h_ 2 | #define __file_1_h_ 3 | 4 | class TEST1 5 | { 6 | public: 7 | int val1; 8 | int val2; 9 | TEST1(); 10 | }; 11 | 12 | extern TEST1 test1; 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /example_code/mult_file_no_static_obj_init/file2.cpp: -------------------------------------------------------------------------------- 1 | #include "file2.h" 2 | #include 3 | using namespace std; 4 | 5 | TEST2::TEST2() 6 | { 7 | val1 = 222; 8 | val2 = 222; 9 | cout << "init test2" << endl; 10 | } 11 | 12 | TEST2 test2; -------------------------------------------------------------------------------- /example_code/mult_file_no_static_obj_init/file2.h: -------------------------------------------------------------------------------- 1 | #ifndef __file_2_h_ 2 | #define __file_2_h_ 3 | 4 | class TEST2 5 | { 6 | public: 7 | int val1; 8 | int val2; 9 | TEST2(); 10 | }; 11 | 12 | extern TEST2 test2; 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /example_code/mult_file_no_static_obj_init/fix_bug_demo/Makefile: -------------------------------------------------------------------------------- 1 | plan1: 2 | g++ -o plan1 main.cpp file2.cpp file1.cpp 3 | 4 | plan2: 5 | g++ -o plan2 main.cpp file1.cpp file2.cpp -------------------------------------------------------------------------------- /example_code/mult_file_no_static_obj_init/fix_bug_demo/file1.cpp: -------------------------------------------------------------------------------- 1 | #include "file1.h" 2 | #include "file2.h" 3 | #include 4 | using namespace std; 5 | 6 | TEST1::TEST1() 7 | { 8 | val1 = get_test2_obj().val1 * get_test2_obj().val2; 9 | cout << "init test1" << endl; 10 | } 11 | 12 | TEST1 &get_test1_obj() 13 | { 14 | static TEST1 test1; 15 | return test1; 16 | } -------------------------------------------------------------------------------- /example_code/mult_file_no_static_obj_init/fix_bug_demo/file1.h: -------------------------------------------------------------------------------- 1 | #ifndef __file_1_h_ 2 | #define __file_1_h_ 3 | 4 | class TEST1 5 | { 6 | public: 7 | int val1; 8 | int val2; 9 | TEST1(); 10 | }; 11 | 12 | TEST1 &get_test1_obj(); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /example_code/mult_file_no_static_obj_init/fix_bug_demo/file2.cpp: -------------------------------------------------------------------------------- 1 | #include "file2.h" 2 | #include 3 | using namespace std; 4 | 5 | TEST2::TEST2() 6 | { 7 | val1 = 222; 8 | val2 = 222; 9 | cout << "init test2" << endl; 10 | } 11 | 12 | TEST2 &get_test2_obj() 13 | { 14 | static TEST2 test2; 15 | return test2; 16 | } -------------------------------------------------------------------------------- /example_code/mult_file_no_static_obj_init/fix_bug_demo/file2.h: -------------------------------------------------------------------------------- 1 | #ifndef __file_2_h_ 2 | #define __file_2_h_ 3 | 4 | class TEST2 5 | { 6 | public: 7 | int val1; 8 | int val2; 9 | TEST2(); 10 | }; 11 | 12 | TEST2 &get_test2_obj(); 13 | #endif 14 | -------------------------------------------------------------------------------- /example_code/mult_file_no_static_obj_init/fix_bug_demo/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "file1.h" 3 | #include "file2.h" 4 | 5 | using namespace std; 6 | 7 | int main() 8 | { 9 | cout << "enter main" << endl; 10 | cout << "test1 : " << get_test1_obj().val1 << " , " << get_test1_obj().val2 << endl; 11 | cout << "test2 : " << get_test2_obj().val1 << " , " << get_test2_obj().val2 << endl; 12 | return 0; 13 | } -------------------------------------------------------------------------------- /example_code/mult_file_no_static_obj_init/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "file1.h" 3 | #include "file2.h" 4 | 5 | using namespace std; 6 | 7 | int main() 8 | { 9 | cout << "enter main" << endl; 10 | cout << "test1 : " << test1.val1 << " , " << test1.val2 << endl; 11 | cout << "test2 : " << test2.val1 << " , " << test2.val2 << endl; 12 | return 0; 13 | } -------------------------------------------------------------------------------- /example_code/mult_file_no_static_obj_init/readme.md: -------------------------------------------------------------------------------- 1 | # 多个文件的全局变量初始化的顺序问题 2 | 3 | 对于同样的代码,执行make plan1,执行make plan2 编译出来的代码,执行的结果会有很大不同。 4 | 5 | 修改之后的代码在: 6 | ./fix_bug_demo 目录下面 -------------------------------------------------------------------------------- /example_code/network/test_tcp_connect_and_close/readme.md: -------------------------------------------------------------------------------- 1 | # 使用tcpdump 观察tcp连接建立和关闭的过程 2 | 3 | ## 问题 4 | 5 | 1. tcp如何建立连接? 6 | 2. 服务器端调用close的时候,会发生什么? 7 | 3. 服务器端close之后,服务器再次尝试发送数据会发生什么? 8 | 4. 服务器端close之后,服务器再试尝试接受数据会发生什么? 9 | 5. 服务器端close之后,client向fd发送数据,会发生什么? 10 | 6. 服务器端close之后,client向fd接受数据,会发生什么? 11 | 7. sigpipe信号什么时候产生?默认的处理是什么样子的? 12 | 13 | --- 14 | 15 | 测试的文件是: 16 | 17 | server.cc 18 | 19 | client.cc 20 | 21 | tcpdump观察9999端口 22 | ``` 23 | sudo tcpdump -n -i lo port 9999 24 | ``` 25 | 26 | * 问题1 : tcp如何建立连接? 27 | 28 | 可以明显的看出,是三次握手。 29 | ``` 30 | sudo tcpdump -n -i lo port 9999 31 | 32 | 18:45:44.988935 IP 127.0.0.1.54927 > 127.0.0.1.9999: Flags [S], seq 2973985528, win 43690, options [mss 65495,sackOK,TS val 6113144 ecr 0,nop,wscale 7], length 0 33 | 34 | 18:45:44.988951 IP 127.0.0.1.9999 > 127.0.0.1.54927: Flags [S.], seq 2517756569, ack 2973985529, win 43690, options [mss 65495,sackOK,TS val 6113144 ecr 6113144,nop,wscale 7], length 0 35 | 36 | 18:45:44.988967 IP 127.0.0.1.54927 > 127.0.0.1.9999: Flags [.], ack 1, win 342, options [nop,nop,TS val 6113144 ecr 6113144], length 0 37 | ``` 38 | 39 | * 问题2:服务器端调用close的时候,会发生什么? 40 | 41 | 当服务器调用close 的使用,tcpdump抓到的包。 42 | ``` 43 | 18:47:17.427152 IP 127.0.0.1.9999 > 127.0.0.1.54927: Flags [F.], seq 15, ack 15, win 342, options [nop,nop,TS val 6136253 ecr 6132295], length 0 44 | 45 | 18:47:17.464231 IP 127.0.0.1.54927 > 127.0.0.1.9999: Flags [.], ack 16, win 342, options [nop,nop,TS val 6136263 ecr 6136253], length 0 46 | ``` 47 | 可以看出,服务器向client发送了一个fin,client回复了一个ack。 48 | 49 | **但是,这个close只是表面上看上去很想四次挥手的前两次,但是,其实不是这样的。服务器这一头已经关闭了自己的读和写。**这也就是close和shutdown的区别。接下来,无论client发过来什么,服务器都不会回复了,只会回复rst。(因为,向一个关闭的端口发送数据,对方就会回复rst) 50 | 51 | 52 | 53 | * 问题3:服务器端close之后,服务器再次尝试发送数据会发生什么? 54 | 55 | send 函数,返回-1。 此时tcpdump没有任何输出。 56 | 57 | * 问题4:服务器端close之后,服务器再次尝试接收数据会发生什么? 58 | 59 | recv 函数,返回-1。此时tcpdump没有任何输出。(recv函数返回0,表示对方关闭,返回-1,表示出错。) 60 | 61 | * 问题5: 服务器端close之后,client向fd发送数据,会发生什么? 62 | 63 | 64 | ``` 65 | 19:05:02.818185 IP 127.0.0.1.47003 > 127.0.0.1.9999: Flags [P.], seq 15:29, ack 16, win 342, options [nop,nop,TS val 6402601 ecr 6400955], length 14 66 | 67 | 19:05:02.818206 IP 127.0.0.1.9999 > 127.0.0.1.47003: Flags [R], seq 1956113576, win 0, length 0 68 | ``` 69 | 70 | 可以看出,client向服务器发送了数据,但是服务器的读和写都关闭了,于是,服务器回复rst报文。 71 | 72 | 73 | * 问题6: 服务器端close之后,client向fd接收数据,会发生什么? 74 | 75 | recv 函数,返回0。此时tcpdump没有任何输出。(recv函数返回0,表示对方关闭,返回-1,表示出错。) 76 | 77 | * 问题7:sigpipe信号什么时候产生?默认的处理是什么样子的? 78 | 79 | 如果服务器close之后,client向fd写入两次数据之后,(调用两次send)会触发sigpipe。默认的sigpipe是退出程序。 -------------------------------------------------------------------------------- /example_code/obj_pool/README.md: -------------------------------------------------------------------------------- 1 | # 对象池 2 | 3 | https://mp.weixin.qq.com/s/bWe8dLs-sgoCI_5sQbeOaw -------------------------------------------------------------------------------- /example_code/obj_pool/pool.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | struct A { 11 | A(std::string s) { str_ = std::move(s); } 12 | 13 | void print() { std::cout << str_ << std::endl; } 14 | 15 | std::string str_; 16 | }; 17 | 18 | template > 19 | class ObjectPool { 20 | public: 21 | ObjectPool() = default; 22 | ~ObjectPool() { 23 | assert(freeObjects_.size() == kInitChunkSize * (std::pow(2, pool_.size()) - 1)); 24 | 25 | size_t chunkSize{kInitChunkSize}; 26 | for (auto* chunk : pool_) { 27 | allocator_.deallocate(chunk, chunkSize); 28 | chunkSize *= 2; 29 | } 30 | pool_.clear(); 31 | } 32 | 33 | template 34 | std::shared_ptr acquireObject(Args... args) { 35 | if (freeObjects_.empty()) { 36 | addChunk(); 37 | } 38 | 39 | T* object{freeObjects_.back()}; 40 | 41 | new (object) T{std::forward(args)...}; 42 | 43 | freeObjects_.pop_back(); 44 | 45 | return std::shared_ptr(object, [this](T* object) { 46 | std::_Destroy(object); 47 | freeObjects_.push_back(object); 48 | }); 49 | } 50 | 51 | private: 52 | std::vector pool_; 53 | 54 | std::vector freeObjects_; 55 | 56 | static const size_t kInitChunkSize{5}; 57 | 58 | size_t newChunkSize{kInitChunkSize}; 59 | 60 | void addChunk() { 61 | std::cout << "add Chunk \n"; 62 | 63 | auto* firstNewObject{allocator_.allocate(newChunkSize)}; 64 | pool_.push_back(firstNewObject); 65 | 66 | auto oldFreeObjectSize{freeObjects_.size()}; 67 | freeObjects_.resize(oldFreeObjectSize + newChunkSize); 68 | std::iota(std::begin(freeObjects_) + oldFreeObjectSize, std::end(freeObjects_), firstNewObject); 69 | 70 | newChunkSize *= 2; 71 | } 72 | 73 | Allocator allocator_; 74 | }; 75 | 76 | using APool = ObjectPool; 77 | 78 | int main() { 79 | APool pool; 80 | for (int i = 0; i < 20; i++) { 81 | auto x = pool.acquireObject(std::string("hello")); 82 | x->print(); 83 | } 84 | return 0; 85 | } -------------------------------------------------------------------------------- /example_code/pb_demo/heartbeat.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/example_code/pb_demo/heartbeat.db -------------------------------------------------------------------------------- /example_code/pb_demo/heartbeat.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package heartbeat; 3 | 4 | message HeartBeatMessage{ 5 | int64 dateTime = 1; 6 | string hostName = 2; 7 | string ip = 3; 8 | string info = 4; 9 | string info2 = 5; 10 | int64 info3 = 6; 11 | } -------------------------------------------------------------------------------- /example_code/pb_demo/protoc-gen/helloworld/build.sh: -------------------------------------------------------------------------------- 1 | # init go mod 2 | go mod init protoc-gen-helloworld 3 | 4 | # 查看结果 5 | # ls $GOPATH/bin 6 | 7 | # build 8 | # go install . 9 | 10 | # run 11 | protoc --helloworld_out=./out demo.proto -------------------------------------------------------------------------------- /example_code/pb_demo/protoc-gen/helloworld/demo.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | option go_package = ".;protocol"; 3 | 4 | message UserMsg 5 | { 6 | uint32 id = 1; 7 | uint32 age = 2; 8 | uint32 passwd = 3; 9 | } -------------------------------------------------------------------------------- /example_code/pb_demo/protoc-gen/helloworld/go.mod: -------------------------------------------------------------------------------- 1 | module protoc-gen-helloworld 2 | 3 | go 1.17 4 | 5 | require google.golang.org/protobuf v1.28.0 // indirect 6 | -------------------------------------------------------------------------------- /example_code/pb_demo/protoc-gen/helloworld/go.sum: -------------------------------------------------------------------------------- 1 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 2 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 3 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 4 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 5 | google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= 6 | google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 7 | -------------------------------------------------------------------------------- /example_code/pb_demo/protoc-gen/helloworld/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "io/ioutil" 7 | "os" 8 | 9 | "google.golang.org/protobuf/compiler/protogen" 10 | "google.golang.org/protobuf/proto" 11 | "google.golang.org/protobuf/types/pluginpb" 12 | ) 13 | 14 | func main() { 15 | // 1. 读取标准输入,接收proto 解析的文件内容,并解析成结构体 16 | input, _ := ioutil.ReadAll(os.Stdin) 17 | var req pluginpb.CodeGeneratorRequest 18 | proto.Unmarshal(input, &req) 19 | 20 | // 2. 生成插件 21 | opts := protogen.Options{} 22 | plugin, err := opts.New(&req) 23 | if err != nil { 24 | panic(err) 25 | } 26 | 27 | // 3. 写入内容 28 | var buf bytes.Buffer 29 | pkg := fmt.Sprintf("hello world") 30 | buf.Write([]byte(pkg)) 31 | 32 | // 指定输入文件名 33 | filename := "hello.txt" 34 | file := plugin.NewGeneratedFile(filename, ".") 35 | // 将内容写入插件文件内容 36 | file.Write(buf.Bytes()) 37 | 38 | // 4. 生成响应 39 | stdout := plugin.Response() 40 | out, err := proto.Marshal(stdout) 41 | if err != nil { 42 | panic(err) 43 | } 44 | 45 | // 5. 将响应写回标准输入, protoc会读取这个内容 46 | fmt.Fprintf(os.Stdout, string(out)) 47 | } 48 | -------------------------------------------------------------------------------- /example_code/pb_demo/protoc-gen/helloworld/out/hello.txt: -------------------------------------------------------------------------------- 1 | hello world -------------------------------------------------------------------------------- /example_code/pb_demo/protoc-gen/protoc-gen-pod/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: gen gen_cpp gen_go is clean 2 | 3 | gen_go: 4 | protoc --go_out=./out ./proto/*.proto 5 | 6 | gen_cpp: 7 | protoc --cpp_out=./out ./proto/*.proto 8 | 9 | is: 10 | go install . 11 | 12 | gen: 13 | protoc --demo_out=./out ./proto/*.proto 14 | 15 | clean: 16 | rm out/custom/*.cpp out/custom/*.h 17 | 18 | all: 19 | make gen_go 20 | make gen_protoc 21 | make gen_cpp 22 | make gen 23 | -------------------------------------------------------------------------------- /example_code/pb_demo/protoc-gen/protoc-gen-pod/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | go mod init protoc-gen-demo 3 | 4 | # ls $GOPATH/bin 5 | 6 | # go install github.com/golang/protobuf/protoc-gen-go -------------------------------------------------------------------------------- /example_code/pb_demo/protoc-gen/protoc-gen-pod/go.mod: -------------------------------------------------------------------------------- 1 | module protoc-gen-demo 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/golang/protobuf v1.5.2 // indirect 7 | google.golang.org/protobuf v1.28.0 // indirect 8 | ) 9 | -------------------------------------------------------------------------------- /example_code/pb_demo/protoc-gen/protoc-gen-pod/go.sum: -------------------------------------------------------------------------------- 1 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 2 | github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= 3 | github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 4 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 5 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 6 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 7 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 8 | google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= 9 | google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 10 | -------------------------------------------------------------------------------- /example_code/pb_demo/protoc-gen/protoc-gen-pod/out/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | rm test_main 3 | g++ *.cpp proto/*.cc -o test_main -L/usr/local/lib -lprotobuf -lpthread -I. -Iproto 4 | 5 | # g++ demo.cpp heartbeat.cpp machine.cpp test_main.cpp proto/custom_opt.pb.cc proto/demo.pb.cc proto/heartbeat.pb.cc proto/machine.pb.cc -o test_main -L/usr/local/lib -lprotobuf -lpthread -I. -Iproto -------------------------------------------------------------------------------- /example_code/pb_demo/protoc-gen/protoc-gen-pod/out/custom/custom_opt.cpp: -------------------------------------------------------------------------------- 1 | #include "custom_opt.h" 2 | #include "custom_opt.pb.h" 3 | -------------------------------------------------------------------------------- /example_code/pb_demo/protoc-gen/protoc-gen-pod/out/custom/custom_opt.h: -------------------------------------------------------------------------------- 1 | #ifndef __CUSTOM_OPT_H_ 2 | #define __CUSTOM_OPT_H_ 3 | 4 | #include 5 | #include "custom_opt.pb.h" 6 | #endif 7 | -------------------------------------------------------------------------------- /example_code/pb_demo/protoc-gen/protoc-gen-pod/out/demo.cpp: -------------------------------------------------------------------------------- 1 | #include "demo.h" 2 | #include "demo.pb.h" 3 | 4 | // method 5 | void PODUserMsg::clear() 6 | { 7 | id = 0; 8 | age = 0; 9 | passwd = 0; 10 | } 11 | 12 | int PODUserMsg::pb2pod(const UserMsg & pb) 13 | { 14 | id = pb.id(); 15 | age = pb.age(); 16 | passwd = pb.passwd(); 17 | return 0; 18 | } 19 | 20 | int PODUserMsg::pod2pb(UserMsg * pb) 21 | { 22 | pb->set_id(id); 23 | pb->set_age(age); 24 | pb->set_passwd(passwd); 25 | return 0; 26 | } 27 | 28 | 29 | // method 30 | void PODFamilyMsg::clear() 31 | { 32 | for (int i = 0; i < 10; i++) { 33 | familys[i].clear(); 34 | } 35 | for (int i = 0; i < 50; i++) { 36 | rid_arrs[i] = 0; 37 | } 38 | } 39 | 40 | int PODFamilyMsg::pb2pod(const FamilyMsg & pb) 41 | { 42 | for (int i = 0; i < 10; i++) { 43 | familys[i].pb2pod(pb.familys(i)); 44 | } 45 | for (int i = 0; i < 50; i++) { 46 | rid_arrs[i] = pb.rid_arrs(i); 47 | } 48 | return 0; 49 | } 50 | 51 | int PODFamilyMsg::pod2pb(FamilyMsg * pb) 52 | { 53 | for (int i = 0; i < 10; i++) { 54 | familys[i].pod2pb(pb->add_familys()); 55 | } 56 | for (int i = 0; i < 50; i++) { 57 | pb->add_rid_arrs(rid_arrs[i]); 58 | } 59 | return 0; 60 | } 61 | 62 | -------------------------------------------------------------------------------- /example_code/pb_demo/protoc-gen/protoc-gen-pod/out/demo.h: -------------------------------------------------------------------------------- 1 | #ifndef __DEMO_H_ 2 | #define __DEMO_H_ 3 | 4 | #include 5 | #include "demo.pb.h" 6 | struct PODUserMsg // pb name UserMsg 7 | { 8 | uint32_t id; // id = 1 9 | uint32_t age; // age = 2 10 | uint32_t passwd; // passwd = 3 11 | 12 | // method 13 | void clear(); 14 | int pb2pod(const UserMsg & pb); 15 | int pod2pb(UserMsg * pb); 16 | }; 17 | 18 | struct PODFamilyMsg // pb name FamilyMsg 19 | { 20 | PODUserMsg familys[10]; 21 | uint32_t rid_arrs[50]; // rid_arrs = 2 22 | 23 | // method 24 | void clear(); 25 | int pb2pod(const FamilyMsg & pb); 26 | int pod2pb(FamilyMsg * pb); 27 | }; 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /example_code/pb_demo/protoc-gen/protoc-gen-pod/out/heartbeat.cpp: -------------------------------------------------------------------------------- 1 | #include "heartbeat.h" 2 | #include "heartbeat.pb.h" 3 | 4 | // method 5 | void PODHeartBeatReqMessage::clear() 6 | { 7 | trace_id = 0; 8 | ip = 0; 9 | time = 0; 10 | type = HeartBeatReqMessage::E_PC; 11 | } 12 | 13 | int PODHeartBeatReqMessage::pb2pod(const HeartBeatReqMessage & pb) 14 | { 15 | trace_id = pb.trace_id(); 16 | ip = pb.ip(); 17 | time = pb.time(); 18 | type = pb.type(); 19 | return 0; 20 | } 21 | 22 | int PODHeartBeatReqMessage::pod2pb(HeartBeatReqMessage * pb) 23 | { 24 | pb->set_trace_id(trace_id); 25 | pb->set_ip(ip); 26 | pb->set_time(time); 27 | pb->set_type(type); 28 | return 0; 29 | } 30 | 31 | 32 | // method 33 | void PODHeartBeatRspMessage::clear() 34 | { 35 | trace_id = 0; 36 | ret = 0; 37 | } 38 | 39 | int PODHeartBeatRspMessage::pb2pod(const HeartBeatRspMessage & pb) 40 | { 41 | trace_id = pb.trace_id(); 42 | ret = pb.ret(); 43 | return 0; 44 | } 45 | 46 | int PODHeartBeatRspMessage::pod2pb(HeartBeatRspMessage * pb) 47 | { 48 | pb->set_trace_id(trace_id); 49 | pb->set_ret(ret); 50 | return 0; 51 | } 52 | 53 | -------------------------------------------------------------------------------- /example_code/pb_demo/protoc-gen/protoc-gen-pod/out/heartbeat.h: -------------------------------------------------------------------------------- 1 | #ifndef __HEARTBEAT_H_ 2 | #define __HEARTBEAT_H_ 3 | 4 | #include 5 | #include "heartbeat.pb.h" 6 | struct PODHeartBeatReqMessage // pb name HeartBeatReqMessage 7 | { 8 | uint32_t trace_id; // trace_id = 1 9 | uint32_t ip; // ip = 2 10 | uint32_t time; // time = 3 11 | HeartBeatReqMessage::MachineEnum type; // EnumValues{{Name: E_PC}, {Name: E_IOS, Number: 1}, {Name: E_ANDRIOD, Number: 2}} 12 | 13 | // method 14 | void clear(); 15 | int pb2pod(const HeartBeatReqMessage & pb); 16 | int pod2pb(HeartBeatReqMessage * pb); 17 | }; 18 | 19 | struct PODHeartBeatRspMessage // pb name HeartBeatRspMessage 20 | { 21 | uint32_t trace_id; // trace_id = 1 22 | uint32_t ret; // ret = 2 23 | 24 | // method 25 | void clear(); 26 | int pb2pod(const HeartBeatRspMessage & pb); 27 | int pod2pb(HeartBeatRspMessage * pb); 28 | }; 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /example_code/pb_demo/protoc-gen/protoc-gen-pod/out/machine.cpp: -------------------------------------------------------------------------------- 1 | #include "machine.h" 2 | #include "machine.pb.h" 3 | 4 | // method 5 | void PODInfoMessage::clear() 6 | { 7 | ip = 0; 8 | time = 0; 9 | } 10 | 11 | int PODInfoMessage::pb2pod(const InfoMessage & pb) 12 | { 13 | ip = pb.ip(); 14 | time = pb.time(); 15 | return 0; 16 | } 17 | 18 | int PODInfoMessage::pod2pb(InfoMessage * pb) 19 | { 20 | pb->set_ip(ip); 21 | pb->set_time(time); 22 | return 0; 23 | } 24 | 25 | 26 | // method 27 | void PODMachineInfoMessage::clear() 28 | { 29 | trace_id = 0; 30 | info.clear(); 31 | type = 0; 32 | } 33 | 34 | int PODMachineInfoMessage::pb2pod(const MachineInfoMessage & pb) 35 | { 36 | trace_id = pb.trace_id(); 37 | info.pb2pod(pb.info()); 38 | type = pb.type(); 39 | return 0; 40 | } 41 | 42 | int PODMachineInfoMessage::pod2pb(MachineInfoMessage * pb) 43 | { 44 | pb->set_trace_id(trace_id); 45 | info.pod2pb(pb->mutable_info()); 46 | pb->set_type(type); 47 | return 0; 48 | } 49 | 50 | -------------------------------------------------------------------------------- /example_code/pb_demo/protoc-gen/protoc-gen-pod/out/machine.h: -------------------------------------------------------------------------------- 1 | #ifndef __MACHINE_H_ 2 | #define __MACHINE_H_ 3 | 4 | #include 5 | #include "machine.pb.h" 6 | struct PODInfoMessage // pb name InfoMessage 7 | { 8 | uint32_t ip; // ip = 1 9 | uint32_t time; // time = 2 10 | 11 | // method 12 | void clear(); 13 | int pb2pod(const InfoMessage & pb); 14 | int pod2pb(InfoMessage * pb); 15 | }; 16 | 17 | struct PODMachineInfoMessage // pb name MachineInfoMessage 18 | { 19 | uint32_t trace_id; // trace_id = 1 20 | PODInfoMessage info; 21 | uint32_t type; // type = 3 22 | 23 | // method 24 | void clear(); 25 | int pb2pod(const MachineInfoMessage & pb); 26 | int pod2pb(MachineInfoMessage * pb); 27 | }; 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /example_code/pb_demo/protoc-gen/protoc-gen-pod/out/test_main: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/test_main -------------------------------------------------------------------------------- /example_code/pb_demo/protoc-gen/protoc-gen-pod/out/test_main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "demo.pb.h" 4 | #include "demo.h" 5 | #include "heartbeat.h" 6 | #include "heartbeat.pb.h" 7 | #include "machine.h" 8 | 9 | using namespace std; 10 | 11 | int main() 12 | { 13 | { 14 | UserMsg pb; 15 | PODUserMsg pod; 16 | pod.clear(); 17 | pod.id = 1; 18 | pod.age = 2; 19 | 20 | pod.pod2pb(&pb); 21 | assert(pb.id() == pod.id); 22 | assert(pb.age() == pod.age); 23 | 24 | pod.clear(); 25 | pod.pb2pod(pb); 26 | assert(pb.id() == pod.id); 27 | assert(pb.age() == pod.age); 28 | } 29 | 30 | { 31 | PODHeartBeatReqMessage pod; 32 | HeartBeatReqMessage pb; 33 | pod.clear(); 34 | pod.trace_id = 123; 35 | pod.ip = 456; 36 | pod.time = 789; 37 | pod.type = HeartBeatReqMessage_MachineEnum::HeartBeatReqMessage_MachineEnum_E_IOS; 38 | 39 | pod.pod2pb(&pb); 40 | assert(pb.trace_id() == pod.trace_id); 41 | assert(pb.ip() == pod.ip); 42 | assert(pb.time() == pod.time); 43 | assert(pb.type() == pod.type); 44 | 45 | pod.clear(); 46 | pod.pb2pod(pb); 47 | assert(pb.trace_id() == pod.trace_id); 48 | assert(pb.ip() == pod.ip); 49 | assert(pb.time() == pod.time); 50 | assert(pb.type() == pod.type); 51 | } 52 | 53 | { 54 | PODMachineInfoMessage pod; 55 | MachineInfoMessage pb; 56 | pod.clear(); 57 | pod.trace_id = 123; 58 | pod.info.ip = 456; 59 | pod.info.time = 789; 60 | pod.type = 1000; 61 | 62 | pod.pod2pb(&pb); 63 | assert(pb.trace_id() == pod.trace_id); 64 | assert(pb.info().ip() == pod.info.ip); 65 | assert(pb.info().time() == pod.info.time); 66 | assert(pb.type() == pod.type); 67 | } 68 | 69 | { 70 | PODFamilyMsg pod; 71 | FamilyMsg pb; 72 | pod.clear(); 73 | pod.familys[0].id = 100; 74 | pod.familys[0].age = 123; 75 | pod.familys[1].id = 200; 76 | pod.familys[2].age = 456; 77 | 78 | // rt to pb 79 | pod.pod2pb(&pb); 80 | assert(pb.familys(0).age() == pod.familys[0].age); 81 | assert(pb.familys(0).id() == pod.familys[0].id); 82 | assert(pb.familys(1).age() == pod.familys[1].age); 83 | assert(pb.familys(1).id() == pod.familys[1].id); 84 | 85 | // pb to rt 86 | pod.clear(); 87 | pod.pb2pod(pb); 88 | assert(pb.familys(0).age() == pod.familys[0].age); 89 | assert(pb.familys(0).id() == pod.familys[0].id); 90 | assert(pb.familys(1).age() == pod.familys[1].age); 91 | assert(pb.familys(1).id() == pod.familys[1].id); 92 | } 93 | cout << "pass" < 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | using namespace heartbeat; 8 | 9 | void traceMsg(const HeartBeatMessage &msg) 10 | { 11 | cout << msg.datetime() << endl; 12 | cout << msg.hostname() << endl; 13 | cout << msg.ip() << endl; 14 | cout << msg.info() << endl; 15 | cout << msg.info2() << endl; 16 | cout << msg.info3() << endl; 17 | 18 | cout <<"========"<FindFieldByName(name); 26 | assert(fdes != nullptr); 27 | const google::protobuf::Reflection* ref = hb_msg.GetReflection(); 28 | cout << ref->GetString(hb_msg, fdes) << endl; 29 | return 0; 30 | } 31 | 32 | int main(void) 33 | { 34 | HeartBeatMessage msg; 35 | 36 | fstream input("./heartbeat.db",ios::in|ios::binary); 37 | 38 | if(!msg.ParseFromIstream(&input)) 39 | { 40 | cerr << "read data from file error." << endl; 41 | return -1; 42 | } 43 | traceMsg(msg); 44 | get_feature(msg, "hostName"); 45 | return 0; 46 | } -------------------------------------------------------------------------------- /example_code/pb_demo/readme.md: -------------------------------------------------------------------------------- 1 | ### protobuff 序列化、反序列化 2 | 3 | https://www.jianshu.com/p/131f0bf218ef -------------------------------------------------------------------------------- /example_code/pb_demo/reflect/demo1/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all proto clean run 2 | 3 | all: 4 | g++ main.cpp ./out/person.pb.cc -o main -I./out -lprotobuf -lpthread -L/usr/local/lib -g 5 | 6 | proto: 7 | protoc --cpp_out=./out *.proto 8 | 9 | run: 10 | ./main 11 | 12 | clean: 13 | rm main -------------------------------------------------------------------------------- /example_code/pb_demo/reflect/demo1/build.sh: -------------------------------------------------------------------------------- 1 | g++ main.cpp -------------------------------------------------------------------------------- /example_code/pb_demo/reflect/demo1/main: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/example_code/pb_demo/reflect/demo1/main -------------------------------------------------------------------------------- /example_code/pb_demo/reflect/demo1/person.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | message PersonInfo 3 | { 4 | uint32 id = 1; 5 | uint32 age = 2; 6 | uint32 passwd = 3; 7 | string name = 4; 8 | } -------------------------------------------------------------------------------- /example_code/pb_demo/reflect/demo2/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all proto clean run 2 | 3 | all: 4 | g++ main.cpp ./out/person.pb.cc -o main -I./out -lprotobuf -lpthread -L/usr/local/lib -g 5 | 6 | proto: 7 | protoc --cpp_out=./out *.proto 8 | 9 | run: 10 | ./main 11 | 12 | clean: 13 | rm main -------------------------------------------------------------------------------- /example_code/pb_demo/reflect/demo2/main: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/example_code/pb_demo/reflect/demo2/main -------------------------------------------------------------------------------- /example_code/pb_demo/reflect/demo2/main.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/example_code/pb_demo/reflect/demo2/main.cpp -------------------------------------------------------------------------------- /example_code/pb_demo/reflect/demo2/person.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | import "google/protobuf/descriptor.proto"; 4 | 5 | message PersonInfo 6 | { 7 | uint32 id = 1; 8 | uint32 age = 2; 9 | uint32 passwd = 3; 10 | string name = 4; 11 | } 12 | 13 | message FieldRule{ 14 | uint32 length_min = 1; // 字段最小长度 15 | uint32 id = 2; // 字段映射id 16 | } 17 | 18 | extend google.protobuf.FieldOptions{ 19 | FieldRule field_rule = 50000; 20 | } 21 | 22 | message Student{ 23 | string name =1 [(field_rule).length_min = 5, (field_rule).id = 1]; 24 | string email = 2 [(field_rule).length_min = 10, (field_rule).id = 2]; 25 | } -------------------------------------------------------------------------------- /example_code/pb_demo/writter: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/example_code/pb_demo/writter -------------------------------------------------------------------------------- /example_code/pb_demo/writter.cc: -------------------------------------------------------------------------------- 1 | #include "heartbeat.pb.h" 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | using namespace heartbeat; 8 | 9 | int main(void){ 10 | HeartBeatMessage msg; 11 | 12 | const long dateTime = 100100; 13 | std::cout << dateTime << std::endl; 14 | 15 | msg.set_datetime(dateTime); 16 | msg.set_hostname("dataNode-1000"); 17 | msg.set_ip("192.168.0.128"); 18 | msg.set_info("Everything is normal, I'm healthy"); 19 | 20 | fstream output("./heartbeat.db",ios::out|ios::trunc|ios::binary); 21 | if (!msg.SerializeToOstream(&output)) 22 | { 23 | cerr << "save data error." << endl; 24 | return -1; 25 | } 26 | return 0; 27 | } 28 | 29 | // protoc --cpp_out=. heartbeat.proto 30 | // export LD_LIBRARY_PATH=/usr/local/lib 31 | // g++ writter.cc heartbeat.pb.cc -lprotobuf -std=c++11 -g -lpthread -------------------------------------------------------------------------------- /example_code/pdf/C++11的内存数据1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/example_code/pdf/C++11的内存数据1.pdf -------------------------------------------------------------------------------- /example_code/pdf/C++11的内存数据2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/example_code/pdf/C++11的内存数据2.pdf -------------------------------------------------------------------------------- /example_code/perd_record/perf_collector.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/example_code/perd_record/perf_collector.h -------------------------------------------------------------------------------- /example_code/perd_record/perf_stat.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/example_code/perd_record/perf_stat.h -------------------------------------------------------------------------------- /example_code/perd_record/perf_stat_def.h: -------------------------------------------------------------------------------- 1 | #ifndef __PERF_STAT_DEF_H__ 2 | #define __PERF_STAT_DEF_H__ 3 | 4 | #ifdef PERF_DECLARE_STAT_TYPE 5 | #undef PERF_DECLARE_STAT_TYPE 6 | #endif 7 | 8 | #define PERF_DECLARE_STAT_TYPE(x) x, 9 | 10 | enum stat_type_t 11 | { 12 | #include "perf_stat_type_def.h" 13 | _type_max, 14 | }; 15 | 16 | #endif -------------------------------------------------------------------------------- /example_code/perd_record/perf_stat_str_def.h: -------------------------------------------------------------------------------- 1 | #ifndef __PERF_STAT_STR_DEF_H__ 2 | #define __PERF_STAT_STR_DEF_H__ 3 | 4 | #ifdef PERF_DECLARE_STAT_TYPE 5 | #undef PERF_DECLARE_STAT_TYPE 6 | #endif 7 | 8 | #define PERF_DECLARE_STAT_TYPE(x) #x, 9 | 10 | const char * stat_type_str[] = 11 | { 12 | #include "perf_stat_type_def.h" 13 | "_type_max", 14 | }; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /example_code/perd_record/perf_stat_type_def.h: -------------------------------------------------------------------------------- 1 | PERF_DECLARE_STAT_TYPE(_type_test_func) -------------------------------------------------------------------------------- /example_code/perd_record/readme.md: -------------------------------------------------------------------------------- 1 | #### 统计函数执行时间 2 | 3 | ``` 4 | g++ test_main.c -o test_main 5 | ``` -------------------------------------------------------------------------------- /example_code/perd_record/test_main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "perf_stat_def.h" 4 | #include "perf_collector.h" 5 | 6 | int test_func() 7 | { 8 | CYCLE_PROFILER((int)_type_test_func); 9 | 10 | int times = 1000000; 11 | while (times > 0) 12 | { 13 | int value = times * times; 14 | times--; 15 | }; 16 | } 17 | 18 | int main() 19 | { 20 | test_func(); 21 | return 0; 22 | } -------------------------------------------------------------------------------- /example_code/readme.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/example_code/readme.md -------------------------------------------------------------------------------- /example_code/reflect/dep.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "helper.h" 4 | 5 | class COMM_DEPENDENCY 6 | { 7 | public: 8 | std::string _name; 9 | }; 10 | 11 | class RPC: public COMM_DEPENDENCY 12 | { 13 | public: 14 | virtual void send(const std::string& text) = 0; 15 | }; 16 | 17 | class GRPC final : public RPC 18 | { 19 | public: 20 | void send(const std::string& text) override 21 | { 22 | std::cout << "[GRPC] " << text << std::endl; 23 | // todo 24 | // use grpc to send data 25 | } 26 | }; 27 | 28 | class TRPC final : public RPC 29 | { 30 | public: 31 | void send(const std::string& text) override 32 | { 33 | std::cout << "[TRPC] " << text << std::endl; 34 | // todo 35 | // use trpc to send data 36 | } 37 | }; 38 | 39 | class LOG: public COMM_DEPENDENCY 40 | { 41 | public: 42 | virtual void print_log(const std::string& text) = 0; 43 | }; 44 | 45 | class GLOG final : public LOG 46 | { 47 | public: 48 | void print_log(const std::string& text) override 49 | { 50 | std::cout << "[GLOG] " << text << std::endl; 51 | } 52 | }; 53 | 54 | class XXLOG final: public LOG 55 | { 56 | public: 57 | void print_log(const std::string& text) override 58 | { 59 | std::cout << "[XXLOG] " << text << std::endl; 60 | } 61 | }; 62 | 63 | REGISTER(GRPC); 64 | REGISTER(TRPC); 65 | REGISTER(GLOG); 66 | REGISTER(XXLOG); 67 | -------------------------------------------------------------------------------- /example_code/reflect/helper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class COMM_DEPENDENCY; 7 | 8 | class DEPENDENCY_HELPER 9 | { 10 | private: 11 | std::map _map_str2obj; 12 | static DEPENDENCY_HELPER* helper; 13 | DEPENDENCY_HELPER() {} 14 | 15 | public: 16 | static DEPENDENCY_HELPER* inst() 17 | { 18 | if (!helper) 19 | { 20 | helper = new DEPENDENCY_HELPER(); 21 | } 22 | return helper; 23 | } 24 | 25 | COMM_DEPENDENCY* get_by_name(std::string name) 26 | { 27 | if (_map_str2obj.find(name) != _map_str2obj.end()) 28 | { 29 | return _map_str2obj[name]; 30 | } 31 | return nullptr; 32 | } 33 | 34 | void push(std::string name, COMM_DEPENDENCY * obj) 35 | { 36 | _map_str2obj[name] = obj; 37 | } 38 | }; 39 | 40 | DEPENDENCY_HELPER* DEPENDENCY_HELPER::helper = nullptr; 41 | 42 | #define REGISTER(CLASS_TYPE) \ 43 | class CLASS_TYPE##Generator {\ 44 | public:\ 45 | CLASS_TYPE##Generator() {\ 46 | DEPENDENCY_HELPER::inst()->push(#CLASS_TYPE, new CLASS_TYPE());\ 47 | }\ 48 | };\ 49 | CLASS_TYPE##Generator* CLASS_TYPE##Inst = new CLASS_TYPE##Generator(); 50 | -------------------------------------------------------------------------------- /example_code/reflect/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "helper.h" 5 | #include "dep.h" 6 | 7 | class MY_SERVICE 8 | { 9 | public: 10 | int deps_init() 11 | { 12 | std::vector name = 13 | { 14 | "GRPC", 15 | "GLOG", 16 | }; 17 | 18 | for (int i = 0; i < name.size(); i++) 19 | { 20 | COMM_DEPENDENCY* obj = DEPENDENCY_HELPER::inst()->get_by_name(name[i]); 21 | if (obj) 22 | { 23 | // init xxx 24 | } 25 | } 26 | return 0; 27 | } 28 | 29 | RPC* get_rpc() 30 | { 31 | RPC* obj = static_cast(DEPENDENCY_HELPER::inst()->get_by_name("GRPC")); 32 | return obj; 33 | } 34 | 35 | LOG* get_log() 36 | { 37 | LOG* obj = static_cast(DEPENDENCY_HELPER::inst()->get_by_name("GLOG")); 38 | return obj; 39 | } 40 | }; 41 | 42 | int main() 43 | { 44 | MY_SERVICE s; 45 | s.get_rpc()->send("HELLO RPC"); 46 | s.get_log()->print_log("HELLO LOG"); 47 | return 0; 48 | } -------------------------------------------------------------------------------- /example_code/shell/cpu.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | PID=18493 3 | 4 | while getopts "p:" option 5 | do 6 | case "$option" in 7 | p) 8 | PID=$OPTARG 9 | ;; 10 | :|\?) 11 | echo "invalid option: '$option'" 12 | exit 1; 13 | ;; 14 | esac 15 | done 16 | 17 | cpu_core_num=`cat /proc/cpuinfo|grep processor|wc|awk '{print $1}'` 18 | 19 | print_process_cpu_precent() 20 | { 21 | cpu_total_time1=`cat /proc/stat | head -n1 |awk '{print $2+$3+$4+$5+$6+$7+$8}'` 22 | process_time1=`cat /proc/${PID}/stat | head -n1 | awk '{print $14+$15+$16+$17}'` 23 | sleep 1 24 | 25 | cpu_total_time2=`cat /proc/stat | head -n1 |awk '{print $2+$3+$4+$5+$6+$7+$8}'` 26 | process_time2=`cat /proc/${PID}/stat | head -n1 | awk '{print $14+$15+$16+$17}'` 27 | 28 | cpu_time=$((cpu_total_time2 - cpu_total_time1)) 29 | process_time=$((process_time2 - process_time1)) 30 | 31 | cpu_percent=$((100 * process_time * cpu_core_num / cpu_time)) 32 | 33 | echo "process : $PID, cpu percent : $cpu_percent" 34 | } 35 | 36 | print_cpu_precent() 37 | { 38 | n=1 39 | while [ $n -le $cpu_core_num ] 40 | do 41 | cpu_total_time1=`cat /proc/stat | head -${n} |awk '{print $2+$3+$4+$5+$6+$7+$8}' | tail -1` 42 | cpu_user_time1=`cat /proc/stat | head -${n} |awk '{print $2}' | tail -1` 43 | cpu_sys_time1=`cat /proc/stat | head -${n} |awk '{print $4}' | tail -1` 44 | 45 | sleep 0.2 46 | cpu_total_time2=`cat /proc/stat | head -${n} |awk '{print $2+$3+$4+$5+$6+$7+$8}' | tail -1` 47 | cpu_user_time2=`cat /proc/stat | head -${n} |awk '{print $2}' | tail -1` 48 | cpu_sys_time2=`cat /proc/stat | head -${n} |awk '{print $4}' | tail -1` 49 | 50 | cpu_time=$((cpu_total_time2 - cpu_total_time1)) 51 | user_time=$((cpu_user_time2 - cpu_user_time1)) 52 | sys_time=$((cpu_sys_time2 - cpu_sys_time1)) 53 | 54 | cpu_user_percent=$((100 * user_time / cpu_time)) 55 | cpu_sys_percent=$((100 * sys_time / cpu_time)) 56 | 57 | echo "[cpu $n] user percent : $cpu_user_percent, syc percent $cpu_sys_percent" 58 | 59 | let n++ 60 | done 61 | sleep 1 62 | } 63 | 64 | while((1)) 65 | do 66 | print_process_cpu_precent 67 | print_cpu_precent 68 | done -------------------------------------------------------------------------------- /example_code/test/coverage/bin/main: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/example_code/test/coverage/bin/main -------------------------------------------------------------------------------- /example_code/test/coverage/src/.main.c.gcov.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/example_code/test/coverage/src/.main.c.gcov.swp -------------------------------------------------------------------------------- /example_code/test/coverage/src/Makefile: -------------------------------------------------------------------------------- 1 | APP_EXE=../bin/main 2 | 3 | all: $(APP_EXE) 4 | 5 | CFLAGS += -Wsign-conversion -Wpedantic -Wall -DNDEBUG -O3 6 | CFLAGS += -g --coverage 7 | 8 | $(APP_EXE):main.c module_a.c module_b.c Makefile 9 | g++ -std=c++11 $(CFLAGS) main.c module_a.c module_b.c -o $(APP_EXE) 10 | 11 | clean: 12 | rm $(APP_EXE) 13 | rm *.gcno 14 | 15 | start: 16 | ./$(APP_EXE) 17 | 18 | coverage: 19 | gcov module_a.c 20 | gcov module_b.c 21 | gcov main.c -------------------------------------------------------------------------------- /example_code/test/coverage/src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "module_a.h" 3 | #include "module_b.h" 4 | 5 | int main() 6 | { 7 | int val = 50; 8 | func_a(val); 9 | func_b(val); 10 | 11 | return 0; 12 | } -------------------------------------------------------------------------------- /example_code/test/coverage/src/main.c.gcov: -------------------------------------------------------------------------------- 1 | -: 0:Source:main.c 2 | -: 0:Graph:main.gcno 3 | -: 0:Data:main.gcda 4 | -: 0:Runs:1 5 | -: 0:Programs:1 6 | -: 1:#include 7 | -: 2:#include "module_a.h" 8 | -: 3:#include "module_b.h" 9 | -: 4: 10 | 1: 5:int main() 11 | -: 6:{ 12 | 1: 7: int val = 50; 13 | 1: 8: func_a(val); 14 | 1: 9: func_b(val); 15 | -: 10: 16 | 1: 11: return 0; 17 | -: 12:} 18 | -------------------------------------------------------------------------------- /example_code/test/coverage/src/main.gcda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/example_code/test/coverage/src/main.gcda -------------------------------------------------------------------------------- /example_code/test/coverage/src/main.gcno: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/example_code/test/coverage/src/main.gcno -------------------------------------------------------------------------------- /example_code/test/coverage/src/module_a.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "module_a.h" 3 | 4 | int func_a(int &val) 5 | { 6 | if (val > 100) 7 | { 8 | val = val * 100; 9 | } 10 | else 11 | { 12 | val++; 13 | } 14 | return 0; 15 | } -------------------------------------------------------------------------------- /example_code/test/coverage/src/module_a.c.gcov: -------------------------------------------------------------------------------- 1 | -: 0:Source:module_a.c 2 | -: 0:Graph:module_a.gcno 3 | -: 0:Data:module_a.gcda 4 | -: 0:Runs:1 5 | -: 0:Programs:1 6 | -: 1:#include 7 | -: 2:#include "module_a.h" 8 | -: 3: 9 | 1: 4:int func_a(int &val) 10 | -: 5:{ 11 | 1: 6: if (val > 100) 12 | -: 7: { 13 | #####: 8: val = val * 100; 14 | -: 9: } 15 | -: 10: else 16 | -: 11: { 17 | 1: 12: val++; 18 | -: 13: } 19 | 1: 14: return 0; 20 | -: 15:} 21 | -------------------------------------------------------------------------------- /example_code/test/coverage/src/module_a.gcda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/example_code/test/coverage/src/module_a.gcda -------------------------------------------------------------------------------- /example_code/test/coverage/src/module_a.gcno: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/example_code/test/coverage/src/module_a.gcno -------------------------------------------------------------------------------- /example_code/test/coverage/src/module_a.h: -------------------------------------------------------------------------------- 1 | #ifndef __MODULE_A_H__ 2 | #define __MODULE_A_H__ 3 | 4 | int func_a(int &val); 5 | 6 | #endif -------------------------------------------------------------------------------- /example_code/test/coverage/src/module_b.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "module_b.h" 3 | 4 | int func_b(int &val) 5 | { 6 | if (val > 500) 7 | { 8 | val = val * 500; 9 | } 10 | else 11 | { 12 | val++; 13 | } 14 | return 0; 15 | } -------------------------------------------------------------------------------- /example_code/test/coverage/src/module_b.gcda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/example_code/test/coverage/src/module_b.gcda -------------------------------------------------------------------------------- /example_code/test/coverage/src/module_b.gcno: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/example_code/test/coverage/src/module_b.gcno -------------------------------------------------------------------------------- /example_code/test/coverage/src/module_b.h: -------------------------------------------------------------------------------- 1 | #ifndef __MODULE_B_H__ 2 | #define __MODULE_B_H__ 3 | 4 | int func_b(int &val); 5 | 6 | #endif -------------------------------------------------------------------------------- /example_code/test/gmock/FooInterface.h: -------------------------------------------------------------------------------- 1 | #ifndef FOOINTERFACE_H_ 2 | #define FOOINTERFACE_H_ 3 | 4 | #include 5 | 6 | namespace seamless { 7 | 8 | class FooInterface { 9 | public: 10 | virtual ~FooInterface() {} 11 | 12 | public: 13 | virtual std::string get_from_rpc() = 0; 14 | 15 | std::string get_result() 16 | { 17 | std::string str = "reuslt is "; 18 | return str + get_from_rpc(); 19 | } 20 | }; 21 | 22 | } // namespace seamless 23 | 24 | #endif // FOOINTERFACE_H_ -------------------------------------------------------------------------------- /example_code/test/gmock/FooMain.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "FooMock.h" 8 | 9 | using namespace seamless; 10 | using namespace std; 11 | 12 | using ::testing::Return; 13 | 14 | TEST(mock_test, get_result) 15 | { 16 | MockFoo mockFoo; 17 | string value = "Hello World!"; 18 | EXPECT_CALL(mockFoo, get_from_rpc()) 19 | .WillRepeatedly(Return(value)); 20 | 21 | string result1 = mockFoo.get_from_rpc(); 22 | string result2 = mockFoo.get_result(); 23 | 24 | cout << "get_result() return : " << result1 << endl; 25 | cout << "get_result() return : " << result2 << endl; 26 | 27 | EXPECT_EQ(value, result1); 28 | EXPECT_EQ("reuslt is " + value, result2); 29 | } 30 | 31 | int main(int argc, char** argv) 32 | { 33 | ::testing::InitGoogleMock(&argc, argv); 34 | return RUN_ALL_TESTS(); 35 | } 36 | 37 | // g++ FooMain.cc -lpthread -lgtest -lgmock -------------------------------------------------------------------------------- /example_code/test/gmock/FooMock.h: -------------------------------------------------------------------------------- 1 | #ifndef MOCKFOO_H_ 2 | #define MOCKFOO_H_ 3 | 4 | #include 5 | #include 6 | #include "FooInterface.h" 7 | 8 | namespace seamless { 9 | 10 | class MockFoo: public FooInterface 11 | { 12 | public: 13 | MOCK_METHOD0(get_from_rpc, std::string()); 14 | }; 15 | 16 | } // namespace seamless 17 | 18 | #endif // MOCKFOO_H_ -------------------------------------------------------------------------------- /note/C++字节对齐.md: -------------------------------------------------------------------------------- 1 | # c++ 字节对齐 2 | 3 | ## 目录 4 | * [为什么需要字节对齐](#为什么需要字节对齐) 5 | * [字节对齐的原理](#字节对齐的原理) 6 | 7 | --- 8 | 9 | ## 为什么需要字节对齐 10 | 11 | 在cpu访问内存的时候,访问内存的最小单位不是字节,而是字长(4个字节,8个字节,或其他)。如果没有字节对齐的机制,可能访问一个int(4字节的)在某些情况需要cpu访问两次内存,而且需要多余的cpu指令剔除掉不需要的数据。 12 | 13 | 而在网络的传输中,就一般不需要字节对齐。因为,在网络中需要尽可能的降低数据传输的流量。字节对齐的机制,会加入多余的填充字节,导致网络流量变大。 14 | 15 | ## 字节对齐的原理 16 | 17 | 对齐系数,gcc的默认对对齐系数是4,#pragma pack(4)。 18 | 19 | 假设 对齐系数 = N, 结构体中最长数据类型 = m; 20 | 21 | 对齐单位 n = min{N,m} 22 | 23 | 字节对齐的规则: 24 | 1. 成员对齐值: 25 | 26 | 首个成员的偏置地址(offset) = 0。 27 | 28 | 假定该成员的类型占字节数 j,那么本成员的偏移地址(offset):min{n, j}的整数倍。 29 | 30 | 2. 整体对齐值: 31 | 32 | 结构体的总大小为 有效对齐值n 的整数倍。如果不是的话,需要进行填充字节。 33 | 34 | ## 验证一下 35 | 36 | 我的机器默认是pack(8), 我先改成pack(4) 37 | ``` 38 | #pragma pack(4) 39 | #include 40 | 41 | struct TEST 42 | { 43 | int val1; 44 | double val2; 45 | char c; 46 | }; 47 | 48 | struct TEST2 49 | { 50 | char val1; 51 | char val2; 52 | char val3; 53 | char val4; 54 | char val5; 55 | }; 56 | 57 | int main() 58 | { 59 | TEST test; 60 | memset(&test, 0, sizeof(test)); 61 | 62 | test.val1 = 1; 63 | test.val2 = 2; 64 | test.c = 'a'; 65 | 66 | std::cout << sizeof(test) << std::endl; // 输出 16 67 | std::cout << sizeof(test2) << std::endl; // 输出 5 68 | return 0; 69 | } 70 | ``` 71 | 72 | 如果改成pack(1),就是13。 73 | 74 | 使用gdb看一下具体的内存分布: 75 | ``` 76 | (gdb) p/x test 77 | $3 = {val1 = 0x1, val2 = 0x2, c = 0x61} 78 | 79 | (gdb) x/16xb &test 80 | 0x7ffffffee270: 0x01 0x00 0x00 0x00 0x02 0x00 0x00 0x00 81 | 0x7ffffffee278: 0x00 0x00 0x00 0x00 0x61 0x00 0x00 0x00 82 | ^ ^ 83 | | <--padding--> | 84 | 85 | ``` 86 | 87 | 88 | 关于gdb的几个命令: 89 | ``` 90 | # 打印变量 91 | gdb 92 | p/x 以16进制打印结构体 93 | ``` 94 | 95 | 96 | examine查看内存,缩写是x 97 | 命令的格式是: 98 | ``` 99 | x/ 100 | * n表示要打印的多少个单位的内存,默认是1,单位由u定义 101 | * f表示打印的格式,格式有: 102 | o,octal,八进制; 103 | x,hex,十六进制; 104 | d,decimal,十进制; 105 | u,unsigned decimal,无符号十进制; 106 | t,binary,二进制; 107 | f,float; 108 | a,address; 109 | i,instruction,指令; 110 | c,char,字符; 111 | s,string,字符串 112 | * u定义单位,b表示1字节,h表示2字节,w表示4字节,g表示8字节 113 | 114 | 示例: 115 | x/16xb 指针 // 打印后面16的字节的数据 116 | ``` 117 | 118 | test branch 119 | -------------------------------------------------------------------------------- /note/CMAKE教程.md: -------------------------------------------------------------------------------- 1 | # CMAKE 教程 2 | 3 | * 一个最简单的例子 4 | 5 | 目录结构 6 | ``` 7 | . 8 | ├── CMakeLists.txt 9 | └── main.cc 10 | 11 | 0 directories, 2 files 12 | ``` 13 | 14 | main.cc 15 | ``` 16 | #include 17 | 18 | int main (int argc, char *argv[]) 19 | { 20 | printf("ok \n"); 21 | return 0; 22 | } 23 | ``` 24 | 25 | CMakeLists.txt 26 | ``` 27 | PROJECT(main) # 名称是 PROJECT ,参数是 main ,该命令表示项目的名称是 main 28 | CMAKE_MINIMUM_REQUIRED(VERSION 2.6) # 第二行的命令限定了 CMake 的版本 29 | AUX_SOURCE_DIRECTORY(. DIR_SRCS) # AUX_SOURCE_DIRECTORY 将当前目录中的源文件名称赋值给变量 DIR_SRCS 30 | ADD_EXECUTABLE(main ${DIR_SRCS}) # 源文件需要编译 成一个名称为 main 的可执行文件 31 | ``` 32 | 33 | ``` 34 | cmake . # 注意 这里有一个点 . , 这个指明了CMakeLists.txt 文件的路径 35 | make # make 36 | ``` 37 | 38 | * Step 2 处理多源文件目录的方法 39 | 40 | ``` 41 | . 42 | ├── CMakeLists.txt 43 | ├── main.cc 44 | └── src 45 | ├── CMakeLists.txt 46 | ├── test1.cc 47 | └── test1.h 48 | 49 | 1 directory, 5 files 50 | ``` 51 | 52 | main.cc 文件 53 | ``` 54 | #include 55 | #include "./src/test1.h" 56 | 57 | int main (int argc, char *argv[]) 58 | { 59 | int val = test(); 60 | printf("ok , val [%d] \n",val); 61 | return 0; 62 | } 63 | ``` 64 | 65 | test1.cc 66 | ``` 67 | int test() 68 | { 69 | return 1; 70 | } 71 | ``` 72 | 73 | test1.h 74 | ``` 75 | int test(); 76 | ``` 77 | 78 | CMakeLists.txt 79 | ``` 80 | PROJECT(main) 81 | CMAKE_MINIMUM_REQUIRED(VERSION 2.6) 82 | ADD_SUBDIRECTORY( src ) 83 | AUX_SOURCE_DIRECTORY(. DIR_SRCS) 84 | ADD_EXECUTABLE(main ${DIR_SRCS}) 85 | TARGET_LINK_LIBRARIES(main Test) 86 | ``` 87 | 88 | src/CMakeLists.txt 89 | ``` 90 | AUX_SOURCE_DIRECTORY(. DIR_TEST1_SRCS) 91 | ADD_LIBRARY (Test ${DIR_TEST1_SRCS}) 92 | ``` 93 | 94 | 95 | ``` 96 | # 执行 97 | cmake . #在执行 cmake 的过程中,首先解析目录 step2 中的 CMakeLists.txt ,当程序执行命令 ADD_SUBDIRECTORY( src ) 时进入目录 src 对其中的 CMakeLists.txt 进行解析。 98 | make 99 | ``` 100 | 101 | * 参考 102 | 103 | 翻译自 https://cmake.org/cmake-tutorial/ 104 | 105 | https://www.ibm.com/developerworks/cn/linux/l-cn-cmake/index.html 106 | -------------------------------------------------------------------------------- /note/bash&shell编程.md: -------------------------------------------------------------------------------- 1 | # bash&shell 编程 2 | 3 | ## 目录 4 | * [hello_world](#hello_world) 5 | * [定义变量](#定义变量) 6 | * [字符串运算](#字符串运算) 7 | * [获得输入](#获得输入) 8 | 9 | --- 10 | 11 | ## hello_world 12 | 13 | 一个简单的demo,输出一个hello world。 14 | ``` 15 | #!/bin/bash 16 | echo "hello world" 17 | ``` 18 | 19 | ## 定义变量 20 | 21 | 注意 : var=hello world **等号两边不能有空格** 22 | ``` 23 | var=hello world #等号两边不能有空格 24 | echo $var 25 | echo ${var} #两种打印变量的方式 26 | 27 | echo "this is : $var" # 感觉都想php了 28 | ``` 29 | 30 | ## 字符串运算 31 | 注意 : [ $a1 = $b1 ] **等号两边必须有空格** 32 | ``` 33 | a1="123" 34 | b1="dsafdakjkl" 35 | 36 | #判断等于 37 | if [ $a1 = $b1 ] 38 | then 39 | echo "eq" 40 | else 41 | echo "not eq" 42 | fi 43 | 44 | # 判断不等于 45 | if [ $a1 != $b1 ] 46 | then 47 | echo "not eq" 48 | fi 49 | ``` 50 | 51 | ## 数学运算 52 | 53 | ``` 54 | num1=100 55 | num2=200 56 | 57 | if [ $num1 == $num2 ] 58 | then 59 | echo "$num1 等于 $num2" 60 | else 61 | echo "$num1 不等于 $num2" 62 | fi 63 | 64 | if [ $num1 != $num2 ] 65 | then 66 | echo "$num1 等于 $num2" 67 | fi 68 | 69 | # 大于小于 70 | if [ $num1 -lt $num2 ] # -gt 大于 ; -eq等于 -ne 不等于; 71 | then 72 | echo "$num1 小于 $num2" 73 | fi 74 | 75 | # 与 和 或运算 76 | 77 | num3=300 78 | num4=400 79 | 80 | if [[ $num3 -lt $num4 && $num1 -lt $num2 ]] 81 | then 82 | echo "yes" 83 | fi 84 | ``` 85 | 86 | ## 条件和分支 87 | 88 | if-else 89 | ``` 90 | if condition 91 | then 92 | command1 93 | command2 94 | ... 95 | commandN 96 | else 97 | command 98 | fi 99 | ``` 100 | 101 | if else-if else 102 | ``` 103 | if condition1 104 | then 105 | command1 106 | elif condition2 107 | then 108 | command2 109 | else 110 | commandN 111 | fi 112 | ``` 113 | 114 | 115 | ## 获得输入 116 | ``` 117 | echo "1 : $1" 118 | echo "2 : $2" 119 | echo "3 : $3" 120 | ``` 121 | 122 | ``` 123 | ./bash_test.sh 100 200 300 124 | ``` 125 | 126 | 127 | ### 写个小demo 128 | ``` 129 | #!/bin/bash 130 | 131 | flag1="make" 132 | flag2="clean" 133 | flag3="run" 134 | 135 | if [ $flag1 = $1 ] 136 | then 137 | echo "flag1 = $1" 138 | g++ main.cc 139 | elif [ $flag2 = $1 ] 140 | then 141 | rm a.out 142 | else 143 | ./a.out 144 | fi 145 | ``` 146 | 147 | ``` 148 | ./bash_test.sh make #编译 149 | ./bash_test.sh run #运行 150 | ``` 151 | 152 | 153 | 154 | 155 | ## 参考 156 | 157 | http://www.runoob.com/linux/linux-shell.html 158 | 159 | 《linux shell脚本攻略》 -------------------------------------------------------------------------------- /note/c++.md: -------------------------------------------------------------------------------- 1 | # c++ 2 | 3 | ## 目录 4 | 5 | * [语法基础](#语法基础) 6 | 7 | * [STL](#STL) 8 | 9 | * [c++字节对齐](#c++字节对齐) 10 | 11 | * [多个文件链接的初始化顺序](#多个文件链接的初始化顺序) 12 | 13 | * [内存分配](#内存分配) 14 | 15 | * [面向对象](#面向对象) 16 | 17 | * [多线程](#多线程) 18 | 19 | * [模板与泛型编程](#模板与泛型编程) 20 | 21 | * [其他](#其他) 22 | 23 | --- 24 | 25 | #### 语法基础 26 | 27 | > [c++语法基础](./C++学习.md) 28 | 29 | #### STL 30 | 31 | > [c++ STL](./C++STL.md) 32 | 33 | #### 内存分配 34 | 35 | > [c++内存管理](./c++内存管理.md) 36 | 37 | > [智能指针](./c++智能指针.md) 38 | 39 | #### 面向对象 40 | 41 | >[c++面向对象](./c++面向对象.md) 42 | 43 | >[c++的多态和虚函数](./c++的多态和虚函数.md) 44 | 45 | #### 多线程 46 | 47 | > [多线程](./c++11多线程.md) 48 | 49 | > [线程同步](./线程同步.md) 50 | 51 | #### 模板与泛型编程 52 | 53 | > [模板](./c++模板与泛型编程.md) 54 | 55 | #### 其他 56 | 57 | > [c++字节对齐](./C++字节对齐.md) 58 | 59 | > [c++多个文件链接的时候no_static多个文件链接变量初始化顺序问题](./c++多个文件链接初始化顺序问题.md) 60 | 61 | > [c++ 关于我用到的static 和 const的一些场景](./c++类中使用static和const.md) 62 | 63 | > [线程同步](./线程同步.md) 64 | 65 | > [c++的前置声明](./c++的前置声明.md) 66 | 67 | > [c++面向对象](./c++面向对象.md) 68 | 69 | > [c++类型转换cast](./c++类中使用static和const.md) 70 | 71 | > [没想好名字的一些东西](./c++其他.md) -------------------------------------------------------------------------------- /note/c++其他.md: -------------------------------------------------------------------------------- 1 | # c++ 一些乱七八糟的东西整理 2 | 3 | 4 | * 看到一个来自知乎的问题,https://zhuanlan.zhihu.com/p/82895086 5 | ``` 6 | // Version 1, by-value copy name to the function. 7 | void addName(std::string name) { 8 | names_.push_back(std::move(name)); 9 | } 10 | 11 | // Version 2, provide two overloads, one with const reference, another with rvalue reference. 12 | void addName(const std::string& name) { 13 | names_.push_back(name); 14 | } 15 | void addName(std::string&& name) { 16 | names_.push_back(std::move(name)); 17 | } 18 | 19 | // Version 3, use universal reference to integrate lvalue reference and rvalue reference. 20 | template 21 | void addName(T&& name) { 22 | names_.push_back(std::forward(name)); 23 | } 24 | 25 | 作者:王金戈 26 | 链接:https://zhuanlan.zhihu.com/p/82895086 27 | 来源:知乎 28 | 著作权归作者所有,转载请联系作者获得授权。 29 | ``` 30 | 31 | 这里没有最优解,版本2和版本3最节约性能,但可能会导致源码或二进制码体积较大,版本1最简洁,但会多出一个移动构造。取舍的关键在于具体的应用场景,假如对象的移动构造非常廉价,完全不耗费性能,那就选择版本1,否则就选择版本2或3。 32 | 33 | 说到这里,便又涉及到另一个问题,你是否清楚对象拷贝构造和移动构造的代价?对于自定义类,如果没有手动声明这些构造函数和赋值运算符,编译器会为我们自动生成。但编译器自动生成的这些函数长什么样?如果我们需要自定义这些函数,应该遵循什么规则?答案很繁琐,但我们必须逐一理清。 -------------------------------------------------------------------------------- /note/c++多个文件链接初始化顺序问题.md: -------------------------------------------------------------------------------- 1 | # c++ 多个文件链接的时候非static变量初始化顺序问题 2 | 3 | 这是一个非常需要注意的坑,在多个文件链接的时候,文件a定义了test1对象,文件b定义了test2对象。那么,问题来了,test1对象先初始化,还是test2对象先初始化? 4 | 5 | 答:其实是不一定的。当然,这个可能没有问题,但是如果test2对象的初始化依赖于test1,或者是test1的对象依赖于test2,那么,问题就来了。举个例子,如果test1的初始化依赖于test2,但是编译器先初始化了test1,test1初始化的时候test2还没有初始化,那么test1的初始化就会失败。 6 | 7 | 举个例子: 8 | show_code_here -> https://github.com/zhaozhengcoder/CoderNoteBook/tree/master/example_code/mult_file_no_static_obj_init 9 | 10 | **这个问题出现在程序执行main函数之前,初始化“全局变量”(数据段的成员)之前,如果在代码里面出现了一个no-static变量的初始化依赖于另外一个,这个的代码估计是要除问题的,需要做检查。** 11 | 12 | 13 | * 解决的办法 14 | 15 | 如果在程序中出现全局变量的初始化依赖问题,那么ok,不需要关心这个问题。如果在代码中,写了类似于**一个对象的初始化**依赖于**另外一个全局变量的对象**,那么就需要注意了。 16 | 17 | 解决的办法: 18 | 19 | ``` 20 | # 原来初始化对象的方法 21 | # TEST test1 22 | 23 | # 修改办的创建对象的方法 24 | TEST1 &get_test1_obj() 25 | { 26 | static TEST1 test1; 27 | return test1; 28 | } 29 | 30 | # 这样如果需要访问一个对象的话,那么一定要通过访问这个函数 31 | # 那么c++的机制可以保证访问函数的时候,static变量一定会函数被调用的时候初始化 32 | ``` 33 | 34 | show_code_here -> https://github.com/zhaozhengcoder/CoderNoteBook/tree/master/example_code/mult_file_no_static_obj_init/fix_bug_demo -------------------------------------------------------------------------------- /note/c++模板与泛型编程.md: -------------------------------------------------------------------------------- 1 | # 模板与泛型编程 2 | 3 | https://www.jianshu.com/p/57baa98fa337 -------------------------------------------------------------------------------- /note/c++的前置声明.md: -------------------------------------------------------------------------------- 1 | # 前置声明 2 | 3 | 举个例子 4 | 5 | ``` 6 | void func(DATA data,ADDRESS address) 7 | { 8 | cout<<"func"< 38 | #include 39 | #include 40 | using namespace std; 41 | 42 | // 前置声明 43 | class DATA; 44 | class ADDRESS; 45 | 46 | // 改成指针或引用 47 | void func(DATA * data,ADDRESS * address) 48 | { 49 | cout<<"func"< 5 | using namespace std; 6 | 7 | class OLD_CLASS 8 | { 9 | public: 10 | virtual void dosomething() {cout<<"do something OLD_CLASS"<dosomething(); 31 | } 32 | 33 | private: 34 | NEW_CLASS * _new_obj; 35 | }; 36 | 37 | #endif -------------------------------------------------------------------------------- /note/design_pattern/example_code/command.c: -------------------------------------------------------------------------------- 1 | #include "command.h" 2 | #include 3 | 4 | int func() 5 | { 6 | Receiver r; 7 | ADD_COMMAND c1(&r); 8 | MULT_COMMAND c2(&r); 9 | 10 | c1.exec(); 11 | c2.exec(); 12 | return 0; 13 | } -------------------------------------------------------------------------------- /note/design_pattern/example_code/command.h: -------------------------------------------------------------------------------- 1 | #ifndef __COMMAND_H__ 2 | #define __COMMAND_H__ 3 | 4 | #include 5 | using namespace std; 6 | 7 | class Receiver 8 | { 9 | public: 10 | void add() {cout << "add" << endl;} 11 | void multi() {cout << "multi" << endl;} 12 | }; 13 | 14 | class COMMAND 15 | { 16 | public: 17 | virtual void exec() = 0; 18 | }; 19 | 20 | class ADD_COMMAND : public COMMAND 21 | { 22 | public: 23 | ADD_COMMAND(Receiver * r):_r(r) {}; 24 | void exec() {_r->add();}; 25 | 26 | private: 27 | Receiver * _r; 28 | }; 29 | 30 | class MULT_COMMAND : public COMMAND 31 | { 32 | public: 33 | MULT_COMMAND(Receiver * r) : _r(r) {}; 34 | void exec() {_r->multi();}; 35 | 36 | private: 37 | Receiver * _r; 38 | }; 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /note/design_pattern/example_code/deco.c: -------------------------------------------------------------------------------- 1 | #include "deco.h" 2 | #include 3 | using namespace std; 4 | 5 | -------------------------------------------------------------------------------- /note/design_pattern/example_code/deco.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/note/design_pattern/example_code/deco.h -------------------------------------------------------------------------------- /note/design_pattern/example_code/factory.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | #include "factory.h" 6 | 7 | string FRUIT::get_name() const 8 | { 9 | return _name; 10 | } 11 | string FRUIT::name() const 12 | { 13 | return _name; 14 | } 15 | 16 | string APPLE::get_name() const 17 | { 18 | string tmp = "apple + : " + name(); 19 | return tmp; 20 | } 21 | 22 | FRUIT* APPLE_FACTORY::build_obj(const string & name) 23 | { 24 | FRUIT * fruit = new APPLE(name); 25 | cout << fruit->get_name() << endl; 26 | return fruit; 27 | } -------------------------------------------------------------------------------- /note/design_pattern/example_code/factory.h: -------------------------------------------------------------------------------- 1 | #ifndef __FACTORY_H__ 2 | #define __FACTORY_H__ 3 | 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | class FRUIT 9 | { 10 | public: 11 | FRUIT(const string &name):_name(name) {} 12 | ~FRUIT() {} 13 | 14 | public: 15 | virtual string get_name() const; 16 | string name() const; 17 | 18 | private: 19 | string _name; 20 | }; 21 | 22 | class APPLE : public FRUIT 23 | { 24 | public: 25 | APPLE(string name):FRUIT(name) {} 26 | ~APPLE() {} 27 | 28 | public: 29 | string get_name() const; 30 | }; 31 | 32 | class FACTORY 33 | { 34 | public: 35 | virtual FRUIT * build_obj(const string & name) = 0; 36 | }; 37 | 38 | class APPLE_FACTORY : public FACTORY 39 | { 40 | public: 41 | FRUIT * build_obj(const string & name); 42 | }; 43 | 44 | #endif -------------------------------------------------------------------------------- /note/design_pattern/example_code/fecade.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "fecade.h" 3 | 4 | FECADE_OBJ* FECADE::build_obj() 5 | { 6 | FECADE_OBJ * obj = new FECADE_OBJ(); 7 | 8 | // 1. step 1 9 | obj->set_name(); 10 | 11 | // 2. step 2 12 | obj->set_attr(); 13 | 14 | // 3. step 3 15 | obj->set_info(); 16 | 17 | return obj; 18 | } -------------------------------------------------------------------------------- /note/design_pattern/example_code/fecade.h: -------------------------------------------------------------------------------- 1 | #ifndef __FECADE_H__ 2 | #define __FECADE_H__ 3 | 4 | #include 5 | using namespace std; 6 | 7 | class FECADE_OBJ 8 | { 9 | public: 10 | int _data; 11 | 12 | public: 13 | void set_name() {cout << "set name" << endl;} 14 | void set_attr() {cout << "set attr" << endl;} 15 | void set_info() {cout << "set info" << endl;} 16 | }; 17 | 18 | class FECADE 19 | { 20 | public: 21 | FECADE_OBJ* build_obj(); 22 | }; 23 | 24 | 25 | #endif -------------------------------------------------------------------------------- /note/design_pattern/example_code/fecade2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "fecade2.h" 3 | 4 | FECADE2* FECADE2::build_obj() 5 | { 6 | FECADE2 * obj = new FECADE2(); 7 | 8 | // 1. step 1 9 | obj->set_name(); 10 | 11 | // 2. step 2 12 | obj->set_attr(); 13 | 14 | // 3. step 3 15 | obj->set_info(); 16 | 17 | return obj; 18 | } -------------------------------------------------------------------------------- /note/design_pattern/example_code/fecade2.h: -------------------------------------------------------------------------------- 1 | #ifndef __FECADE2_H__ 2 | #define __FECADE2_H__ 3 | 4 | #include 5 | using namespace std; 6 | 7 | class FECADE2 8 | { 9 | public: 10 | void set_name() {cout << "set name" << endl;} 11 | void set_attr() {cout << "set attr" << endl;} 12 | void set_info() {cout << "set info" << endl;} 13 | 14 | public: 15 | static FECADE2* build_obj(); 16 | 17 | public: 18 | int _data; 19 | }; 20 | 21 | 22 | #endif -------------------------------------------------------------------------------- /note/design_pattern/example_code/flyweight.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "flyweight.h" 5 | 6 | using namespace std; 7 | 8 | FLYWEIGHT_OBJ* FLYWEIGHT::build_obj(int key) 9 | { 10 | if (_map.find(key) == _map.end()) 11 | { 12 | FLYWEIGHT_OBJ * obj = new FLYWEIGHT_OBJ(); 13 | _map[key] = obj; 14 | return obj; 15 | } 16 | else 17 | { 18 | return _map[key]; 19 | } 20 | } 21 | 22 | int FLYWEIGHT::clear() 23 | { 24 | map::iterator iter = _map.begin(); 25 | for (; iter != _map.end(); iter++) 26 | { 27 | FLYWEIGHT_OBJ * obj = iter->second; 28 | delete obj; 29 | } 30 | return 0; 31 | } -------------------------------------------------------------------------------- /note/design_pattern/example_code/flyweight.h: -------------------------------------------------------------------------------- 1 | #ifndef __FLY_WEIGHT_H__ 2 | #define __FLY_WEIGHT_H__ 3 | 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | class FLYWEIGHT_OBJ 10 | { 11 | public: 12 | FLYWEIGHT_OBJ():_data(0) {cout << "create obj" < _map; 25 | }; 26 | 27 | #endif -------------------------------------------------------------------------------- /note/design_pattern/example_code/observer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "observer.h" 5 | using namespace std; 6 | 7 | int TOPIC::notfiy() 8 | { 9 | cout << "TOPIC::notfiy" << endl; 10 | return 0; 11 | } 12 | 13 | int NEWS::notfiy() 14 | { 15 | cout << "TOPIC::notfiy" << endl; 16 | return 0; 17 | } 18 | 19 | int MUSIC::notfiy() 20 | { 21 | cout << "TOPIC::notfiy" << endl; 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /note/design_pattern/example_code/observer.h: -------------------------------------------------------------------------------- 1 | #ifndef __OBSERVER_H__ 2 | #define __OBSERVER_H__ 3 | 4 | #include 5 | #include 6 | 7 | class TOPIC 8 | { 9 | public: 10 | TOPIC() {} 11 | ~TOPIC() {} 12 | 13 | public: 14 | virtual int notfiy(); 15 | }; 16 | 17 | class NEWS : public TOPIC 18 | { 19 | public: 20 | NEWS() {} 21 | ~NEWS() {} 22 | 23 | public: 24 | virtual int notfiy(); 25 | }; 26 | 27 | class MUSIC : public TOPIC 28 | { 29 | public: 30 | MUSIC(){} 31 | ~MUSIC(){} 32 | 33 | public: 34 | virtual int notfiy(); 35 | }; 36 | 37 | class OBSERVER 38 | { 39 | public: 40 | OBSERVER() {} 41 | ~OBSERVER() {} 42 | 43 | public: 44 | int add(TOPIC*) {return 0;} 45 | int rm(TOPIC*) {return 0;} 46 | 47 | private: 48 | std::vector topic_vec; 49 | }; 50 | 51 | #endif -------------------------------------------------------------------------------- /note/design_pattern/example_code/proxy.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "proxy.h" 3 | using namespace std; 4 | 5 | int REQUEST::do_requst() 6 | { 7 | cout << "do request" << endl; 8 | return 0; 9 | } 10 | 11 | int PROXY::do_request_proxy() 12 | { 13 | pre_request(); 14 | do_requst(); 15 | post_request(); 16 | return 0; 17 | } -------------------------------------------------------------------------------- /note/design_pattern/example_code/proxy.h: -------------------------------------------------------------------------------- 1 | #ifndef __PROYX_H__ 2 | #define __PROYX_H__ 3 | 4 | #include 5 | using namespace std; 6 | 7 | class REQUEST 8 | { 9 | public: 10 | REQUEST() {} 11 | ~REQUEST() {} 12 | 13 | public: 14 | int do_requst(); 15 | }; 16 | 17 | 18 | class PROXY : public REQUEST 19 | { 20 | public: 21 | int do_request_proxy(); 22 | 23 | void pre_request() {cout<<"pre"< 2 | #include "singleton.h" 3 | 4 | SINGLETON * SINGLETON::_instance = get_instance(); 5 | 6 | SINGLETON* SINGLETON::get_instance() 7 | { 8 | if (_instance == NULL) 9 | { 10 | LOCK guard; 11 | if (_instance == NULL) 12 | { 13 | _instance = new SINGLETON(); 14 | } 15 | } 16 | return _instance; 17 | } -------------------------------------------------------------------------------- /note/design_pattern/example_code/singleton.h: -------------------------------------------------------------------------------- 1 | #ifndef __SINGLETON_H__ 2 | #define __SINGLETON_H__ 3 | 4 | #include 5 | using namespace std; 6 | 7 | class LOCK 8 | { 9 | public: 10 | LOCK(){} 11 | ~LOCK(){} 12 | }; 13 | 14 | class SINGLETON 15 | { 16 | public: 17 | static SINGLETON * get_instance(); 18 | ~SINGLETON() {} 19 | private: 20 | SINGLETON() { cout <<"SINGLETON()"< 2 | #include "strategy.h" 3 | using namespace std; 4 | 5 | int TAX::cal_tax() 6 | { 7 | cout << "TAX cal_tax" << endl; 8 | return 0; 9 | } 10 | 11 | int CHINA_TAX::cal_tax() 12 | { 13 | cout << "CHINA_TAX cal_tax" << endl; 14 | return 0; 15 | } -------------------------------------------------------------------------------- /note/design_pattern/example_code/strategy.h: -------------------------------------------------------------------------------- 1 | #ifndef __STRATEGY_H__ 2 | #define __STRATEGY_H__ 3 | 4 | class TAX 5 | { 6 | public: 7 | TAX(){} 8 | ~TAX(){} 9 | public: 10 | virtual int cal_tax(); 11 | }; 12 | 13 | class CHINA_TAX : public TAX 14 | { 15 | public: 16 | CHINA_TAX(){} 17 | ~CHINA_TAX(){} 18 | 19 | public: 20 | virtual int cal_tax(); 21 | }; 22 | 23 | 24 | #endif -------------------------------------------------------------------------------- /note/design_pattern/example_code/template.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "template.h" 3 | 4 | using namespace std; 5 | 6 | int FRAMEWORK::init() 7 | { 8 | cout << "frame work init" << endl; 9 | return 0; 10 | } 11 | 12 | int FRAMEWORK::load() 13 | { 14 | cout << "frame work load" << endl; 15 | return 0; 16 | } 17 | 18 | int FRAMEWORK::work() 19 | { 20 | cout << "frame work work" << endl; 21 | return 0; 22 | } 23 | 24 | int FRAMEWORK::fini() 25 | { 26 | cout << "frame work fini" << endl; 27 | return 0; 28 | } 29 | 30 | // BUSINESS 31 | int BUSINESS::init() 32 | { 33 | cout << "business work init" << endl; 34 | return 0; 35 | } 36 | 37 | int BUSINESS::load() 38 | { 39 | cout << "business work load" << endl; 40 | return 0; 41 | } 42 | 43 | int BUSINESS::work() 44 | { 45 | cout << "business work work" << endl; 46 | return 0; 47 | } 48 | 49 | int BUSINESS::fini() 50 | { 51 | cout << "business work fini" << endl; 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /note/design_pattern/example_code/template.h: -------------------------------------------------------------------------------- 1 | #ifndef __TEMPLATE_H__ 2 | #define __TEMPLATE_H__ 3 | 4 | 5 | class FRAMEWORK 6 | { 7 | public: 8 | FRAMEWORK() {} 9 | ~FRAMEWORK(){} 10 | 11 | public: 12 | virtual int init(); 13 | virtual int load(); 14 | virtual int work(); 15 | virtual int fini(); 16 | }; 17 | 18 | class BUSINESS : public FRAMEWORK 19 | { 20 | public: 21 | BUSINESS() {} 22 | ~BUSINESS(){} 23 | 24 | public: 25 | virtual int init(); 26 | virtual int load(); 27 | virtual int work(); 28 | virtual int fini(); 29 | }; 30 | 31 | #endif -------------------------------------------------------------------------------- /note/design_pattern/example_code/test_main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "singleton.h" 3 | #include "template.h" 4 | #include "factory.h" 5 | #include "flyweight.h" 6 | #include "fecade.h" 7 | #include "fecade2.h" 8 | #include "proxy.h" 9 | 10 | using namespace std; 11 | 12 | int main() 13 | { 14 | cout << "main" << endl; 15 | 16 | SINGLETON * instance = SINGLETON::get_instance(); 17 | if (instance != NULL) 18 | { 19 | cout << "get instance" << endl; 20 | } 21 | 22 | FRAMEWORK * business = new BUSINESS(); 23 | business->init(); 24 | business->load(); 25 | business->work(); 26 | business->fini(); 27 | 28 | FACTORY * f = new APPLE_FACTORY(); 29 | f->build_obj("hahah"); 30 | 31 | FLYWEIGHT mgr; 32 | int key1 = 100; 33 | FLYWEIGHT_OBJ * obj1 = mgr.build_obj(key1); 34 | FLYWEIGHT_OBJ * obj2 = mgr.build_obj(key1); 35 | 36 | // FECADE fecade; 37 | // fecade.build_obj(); 38 | 39 | FECADE2 f2; 40 | f2.build_obj(); 41 | 42 | PROXY proxy; 43 | proxy.do_request_proxy(); 44 | 45 | return 0; 46 | } -------------------------------------------------------------------------------- /note/design_pattern/note/0模板模式.md: -------------------------------------------------------------------------------- 1 | ## 模板模式 2 | 3 | 在日常的开发中,经常遇到的场景是: 4 | ``` 5 | int main() 6 | { 7 | library lib(); // 框架层逻辑 8 | application app(); // 应用层逻辑 9 | 10 | lib.step1(); 11 | lib.step2(); 12 | 13 | if(app.step3()) 14 | { 15 | lib.step4(); 16 | app.step5(); 17 | } 18 | 19 | // xxx 20 | } 21 | ``` 22 | --- 23 | 24 | 如果把代码写成下面的样子,看看会不会更好? 25 | ``` 26 | class library 27 | { 28 | public: 29 | void step1(); 30 | void step2(); 31 | void step3(); 32 | 33 | // 提供给app实现 34 | virtual void step3() = 0; 35 | virtual void step5() = 0; 36 | 37 | // 逻辑 38 | void run() 39 | { 40 | step1(); 41 | step2(); 42 | 43 | if(step3()) 44 | { 45 | step4(); 46 | step5(); 47 | } 48 | } 49 | }; 50 | 51 | class app : public library 52 | { 53 | public: 54 | void step3() 55 | { 56 | // dosomething 57 | } 58 | 59 | void step5() 60 | { 61 | // dosomething 62 | } 63 | }; 64 | 65 | int main() 66 | { 67 | library lib(); 68 | lib.run(); 69 | 70 | 71 | return 0; 72 | } 73 | ``` 74 | 75 | 对比一下,这样的好处是: 76 | 77 | lib层面提供抽象的接口,step3(), step5(),继承的app类可以提供自己的实现。这样对于频繁的变化的app类,修改自己实现的step3,step5函数即可。 78 | 79 | 这样可能更加符合基本的设计原则,开放封闭原则 和 依赖倒置原则(依赖于抽象而不是依赖于具体)。 80 | 81 | 实际上,在现在的各种框架里面都可以看到这样的影子。lib层面在开发的层面上,已经提供了相关的逻辑的接口,app层面只需要继承这个接口,实现里面的逻辑即可。 -------------------------------------------------------------------------------- /note/design_pattern/note/10装饰器模式.md: -------------------------------------------------------------------------------- 1 | ## 装饰器模式 2 | 3 | 对于一个class的设计,如果需要引入一个新的功能,比如企鹅类添加一个会飞的方法。加入这个方法会破环原有的类的设计,另外一个方法就是引入装饰器模式。 4 | 5 | 这个模式在很多的项目可以看到,**最明显的一个标志是,一个Decrator的class,持有基类class的指针。** 6 | 7 | 补充一个图: 8 | 9 | 10 | ``` 11 | class Decrator :public BASE 12 | { 13 | protected: 14 | BASE* base; //维护一个base对象的引用,为bass对象添加装饰 15 | public: 16 | 17 | }; 18 | ``` 19 | 20 | ----------- 21 | 22 | 基类对象: 23 | ``` 24 | //定义一个原始的抽象类蛋糕,装饰器的功能是给蛋糕加上各种装饰,如奶油,巧克力,瓜子仁,花生米等 25 | class Cake 26 | { 27 | public: 28 | virtual void showCake()=0; 29 | virtual ~Cake(){}; 30 | std::string name; 31 | }; 32 | 33 | class ConcreteCake :public Cake 34 | { 35 | public: 36 | ConcreteCake() 37 | { 38 | name = "原始蛋糕"; 39 | } 40 | void showCake(){ std::cout << name.c_str() << std::endl; }; 41 | virtual ~ConcreteCake(){}; 42 | }; 43 | 44 | // 装饰器类 45 | class CakeDecrator :public Cake 46 | { 47 | protected: 48 | Cake* pCake; //维护一个Cake对象的引用,为Cake对象添加装饰 49 | public: 50 | virtual void showCake() = 0; 51 | virtual ~CakeDecrator(){}; 52 | }; 53 | 54 | class CakeDecratorMilk : public CakeDecrator 55 | { 56 | public: 57 | CakeDecratorMilk(Cake* pCake) 58 | { 59 | this->pCake = pCake; 60 | } 61 | void showCake() 62 | { 63 | this->name = pCake->name + "加奶油"; 64 | std::cout << name.c_str()<showCake(); 73 | 74 | CakeDecratorMilk* pDecMilk = new CakeDecratorMilk(pConCake); 75 | pDecMilk->showCake(); 76 | 77 | // xxx 78 | } 79 | ``` -------------------------------------------------------------------------------- /note/design_pattern/note/11命令模式.md: -------------------------------------------------------------------------------- 1 | ## 命令模式 2 | 3 | 命令模式核心的是把不同的操作行为都封装为command的派生类。然后提供一个exec()函数,把自己的行为实现在这个函数内部。这样上层只需要关系exec函数就可以。 4 | 5 | 不过,命令模式我还没有体会它的博大精深,感觉一个类要被拆分为更多的类,把他们都封装为command类的派生类。 6 | 看起来反而更复杂了。 7 | 8 | ``` 9 | int func() 10 | { 11 | SHIT shit_obj; 12 | shit_obj.do_copy(); 13 | shit_obj.do_paste(); 14 | } 15 | ``` 16 | 17 | // command模式改良 18 | ``` 19 | class COMMAMD 20 | { 21 | 22 | }; 23 | 24 | class CO 25 | ``` -------------------------------------------------------------------------------- /note/design_pattern/note/12门面fecade模式.md: -------------------------------------------------------------------------------- 1 | ## 门面Fecade模式 2 | 3 | 门面模式很像一个中介,帮client把一些逻辑隐藏起来,对外提供简洁的接口。其实,这个不仅仅是一个设计模式,更多的表现的是设计的分层。 4 | 5 | ``` 6 | { 7 | WORKER work; 8 | 9 | work.init(); 10 | work.load(); 11 | work.do(); 12 | } 13 | ``` 14 | 15 | 16 | ``` 17 | class FECADE 18 | { 19 | int do() 20 | { 21 | work->init(); 22 | work->load(); 23 | work->do(); 24 | } 25 | }; 26 | 27 | { 28 | WORKER work; 29 | FECADE fecade(work); 30 | 31 | // 32 | fecade.do(); 33 | } 34 | ``` -------------------------------------------------------------------------------- /note/design_pattern/note/1策略模式.md: -------------------------------------------------------------------------------- 1 | ## 策略模式 2 | 3 | 策略模式使用的一个常见的场景: 4 | 5 | 6 | 如果你的代码里面有大量的if-else, switch-case, 那么可能是一个需要考虑策略模式了。 7 | 8 | ``` 9 | int main() 10 | { 11 | if (type == "中国") 12 | { 13 | // 使用中国的方式计算税务 14 | } 15 | else if (type == "美国") 16 | { 17 | // 使用美国的方式计算税务 18 | } 19 | else if (type == "xxx") 20 | { 21 | // 其他xxx 22 | } 23 | else 24 | { 25 | // 其他 26 | } 27 | } 28 | ``` 29 | 30 | 31 | 这是一种看起来具有 “坏味道”的代码。 32 | 33 | 如果把代码写成下面的样子,看看会不会更好? 34 | ``` 35 | class TAX 36 | { 37 | public: 38 | virtual void calc_tax() = 0; 39 | }; 40 | 41 | class TAX_CHINA : public TAX 42 | { 43 | public: 44 | void calc_tax(); 45 | }; 46 | 47 | class TAX_US : public TAX 48 | { 49 | public: 50 | void calc_tax(); 51 | }; 52 | 53 | int main() 54 | { 55 | TAX_CHINA tax; 56 | tax.calc_tax(); 57 | } 58 | ``` 59 | 60 | 对比一下,这种模式的好处显而易见,通过使用多态的方式来控制“变化”。将变化控制在多态的函数里面。这是典型的开放封闭原则和依赖抽象的原则。 61 | 62 | 如果有一天一个人跳出来多,我还要新家几个类型,那对于这个模式来说,只需要新加一个class 继承一把,把逻辑写进行就可以。 63 | 64 | -------------------------------------------------------------------------------- /note/design_pattern/note/2观察者模式.md: -------------------------------------------------------------------------------- 1 | ## 观察者模式 2 | 3 | 观察者模式是一个非常经典的模式。在大量的软件中都会使用。这个就不举例子了,直接写这个模式的demo了。 4 | 5 | ``` 6 | class SUBJECT 7 | { 8 | vector observer_vector; 9 | public: 10 | void add_ob(); 11 | void rm_ob(); 12 | 13 | void update() 14 | { 15 | for (xxx) 16 | { 17 | ob->notify(); 18 | } 19 | } 20 | }; 21 | 22 | class OBSERVER 23 | { 24 | public: 25 | vitual void notify () = 0; 26 | }; 27 | 28 | class OBSERVER_V1: public OBSERVER 29 | { 30 | public: 31 | void notify () 32 | { 33 | // do something 34 | } 35 | }; 36 | ``` 37 | 38 | 不同类型的observer可以继承基类observer,实现自己不同的notify函数。 -------------------------------------------------------------------------------- /note/design_pattern/note/3工厂模式.md: -------------------------------------------------------------------------------- 1 | ## 工厂模式 2 | 3 | 工厂模式的作用是绕开new的一种设计模式 4 | 5 | ``` 6 | class FRUIT 7 | { 8 | public: 9 | virtual void show_name() = 0; 10 | virtual ~FRUIT() {}; 11 | }; 12 | 13 | class APPLE_FRUIT: public FRUIT 14 | { 15 | public: 16 | void show_name() 17 | { 18 | cout << "apple" << endl; 19 | } 20 | }; 21 | 22 | class BANAN_FRUIT: public FRUIT 23 | { 24 | public: 25 | void show_name() 26 | { 27 | cout << "banan" << endl; 28 | } 29 | }; 30 | 31 | class FACTORY 32 | { 33 | public: 34 | virtual FRUIT* build_fruit() = 0; 35 | }; 36 | 37 | class APPLE_FACTORY: public FACTORY 38 | { 39 | public: 40 | FRUIT * build_fruit() 41 | { 42 | return new APPLE_FRUIT(); 43 | } 44 | }; 45 | 46 | class BANAN_FACTORY: public FACTORY 47 | { 48 | public: 49 | FRUIT * build_fruit() 50 | { 51 | return new BANAN_FRUIT(); 52 | } 53 | }; 54 | 55 | int main() 56 | { 57 | // factory (工厂的这一层还是需要new的) 58 | FACTORY * factory = new BANAN_FACTORY(); 59 | 60 | { 61 | // 水果这一层是看不到new的 62 | // 工厂的基类指针指到了什么类型的工厂对象,就会build出什么类型的水果 63 | FRUIT * fruit = factory->build_fruit(); 64 | fruit->show_name(); 65 | 66 | // todo 67 | // ... 68 | } 69 | 70 | return 0; 71 | } 72 | ``` -------------------------------------------------------------------------------- /note/design_pattern/note/5享元模式.md: -------------------------------------------------------------------------------- 1 | ## 享元模式 2 | 3 | --- 4 | 5 | 享元模式的思路常见。就是当有可能重复创建对象的时候,对相同或相似对象的重用。 6 | 7 | 比如: 8 | ``` 9 | int create_obj(int key) 10 | { 11 | if (_map.find(key) == _map.end()) 12 | { 13 | // 创建对象 14 | // 插入map 15 | } 16 | else 17 | { 18 | // 直接返回对象 19 | } 20 | } 21 | ``` 22 | 23 | cpp文件 24 | ``` 25 | FLYWEIGHT_OBJ* FLYWEIGHT::build_obj(int key) 26 | { 27 | if (_map.find(key) == _map.end()) 28 | { 29 | FLYWEIGHT_OBJ * obj = new FLYWEIGHT_OBJ(); 30 | _map[key] = obj; 31 | return obj; 32 | } 33 | else 34 | { 35 | return _map[key]; 36 | } 37 | } 38 | 39 | int FLYWEIGHT::clear() 40 | { 41 | map::iterator iter = _map.begin(); 42 | for (; iter != _map.end(); iter++) 43 | { 44 | FLYWEIGHT_OBJ * obj = iter->second; 45 | delete obj; 46 | } 47 | return 0; 48 | } 49 | ``` 50 | 51 | hpp文件 52 | ``` 53 | #ifndef __FLY_WEIGHT_H__ 54 | #define __FLY_WEIGHT_H__ 55 | 56 | #include 57 | #include 58 | 59 | using namespace std; 60 | 61 | class FLYWEIGHT_OBJ 62 | { 63 | public: 64 | FLYWEIGHT_OBJ():_data(0) {cout << "create obj" < _map; 77 | }; 78 | 79 | #endif 80 | ``` -------------------------------------------------------------------------------- /note/design_pattern/note/6代理模式.md: -------------------------------------------------------------------------------- 1 | ## 代理模式 PROXY模式 2 | 3 | proxy最常见的使用场景是,当开发的时候,看到一坨像shit一样的老代码,里面有一个函数func,需要调整or修改里面的部分逻辑。但是这个函数有无数个被引用的地方。直接改动func里面的逻辑,危险并且进一步使shit上再加shit。 4 | 5 | 因此,可以不去修改func内部的逻辑。可以重新写一个PROXY类继承原来的类,重新实现里面的逻辑。 6 | ``` 7 | class OLD_CLASS 8 | { 9 | int func() 10 | { 11 | // shit 12 | } 13 | }; 14 | 15 | class PROXY_SHIT : public OLD_CLASS 16 | { 17 | int proy_func() 18 | { 19 | pre_invoke(); 20 | 21 | // invoke shit 22 | old_class->func(); 23 | 24 | post_invoke(); 25 | } 26 | 27 | private: 28 | OLD_CLASS * old_class; 29 | } 30 | 31 | ``` -------------------------------------------------------------------------------- /note/design_pattern/note/7适配器模式.md: -------------------------------------------------------------------------------- 1 | ## 适配器模式 Adapter 2 | 3 | 使用的场景: 4 | 5 | 将一个类的接口转换为 用户希望的接口。可以是原本不兼容的接口 放到一起来使用。 6 | 7 | 举个栗子 8 | ``` 9 | // 开发的时候看到一个接口 10 | int func(OLD_CLASS * a) 11 | { 12 | a->dosomething(); 13 | } 14 | 15 | // 但是手上有的对象是B * b 16 | int foo() 17 | { 18 | NEW_CLASS b; 19 | func(&b); // complier error 20 | } 21 | ``` 22 | 23 | 如果让类型B转换为类型A, 适配器翻译的很准确,就是一个转换的插座。解决不同接口的类型的问题。 24 | 25 | ``` 26 | class OLD_CLASS 27 | { 28 | public: 29 | virtual void dosomething() {cout<<"do something OLD_CLASS"<dosomething(); 50 | } 51 | 52 | private: 53 | NEW_CLASS * _new_obj; 54 | }; 55 | ``` 56 | 57 | ``` 58 | int func(OLD_CLASS * old) 59 | { 60 | old->dosomething(); 61 | return 0; 62 | } 63 | 64 | int adapter_demo(NEW_CLASS * new_obj) 65 | { 66 | // 比如说直接调用因为参数不对而报错 67 | // func(new) 68 | 69 | Adapter adapter(new_obj); 70 | adapter.dosomething(); 71 | 72 | return 0; 73 | } 74 | ``` -------------------------------------------------------------------------------- /note/design_pattern/note/8状态机模式.md: -------------------------------------------------------------------------------- 1 | ## 状态机模式 2 | 3 | 状态机模式可以被用在 软件设计中维护复杂的异步逻辑。 4 | ``` 5 | class STATE_MACHINE 6 | { 7 | int msg; 8 | int state; 9 | int next_stat; 10 | }; 11 | ``` 12 | 13 | 基本的思路是维护一张函数表,在当前的state下,收到什么样的消息(或超时),执行什么样的逻辑,进入的下一个状态是什么。 14 | -------------------------------------------------------------------------------- /note/design_pattern/note/9责任链模式.md: -------------------------------------------------------------------------------- 1 | ## 责任链模式 2 | 3 | 责任链模式可以用于的场景是: 4 | 5 | 对于一个对象req,可以定义一系列的class(责任链)来处理它。感觉对于一个http的请求,或者是一个客户端上行来的请求,可以使用这种模式,来定义一条流水线(责任链)进行处理。 6 | 7 | ``` 8 | #include 9 | #include 10 | 11 | using namespace std; 12 | 13 | enum class RequestType 14 | { 15 | REQ_HANDLER1, 16 | REQ_HANDLER2, 17 | REQ_HANDLER3 18 | }; 19 | 20 | class Reqest 21 | { 22 | string description; 23 | RequestType reqType; 24 | public: 25 | Reqest(const string & desc, RequestType type) : description(desc), reqType(type) {} 26 | RequestType getReqType() const { return reqType; } 27 | const string& getDescription() const { return description; } 28 | }; 29 | 30 | class ChainHandler{ 31 | 32 | ChainHandler *nextChain; 33 | void sendReqestToNextHandler(const Reqest & req) 34 | { 35 | if (nextChain != nullptr) 36 | nextChain->handle(req); 37 | } 38 | protected: 39 | virtual bool canHandleRequest(const Reqest & req) = 0; 40 | virtual void processRequest(const Reqest & req) = 0; 41 | public: 42 | ChainHandler() { nextChain = nullptr; } 43 | void setNextChain(ChainHandler *next) { nextChain = next; } 44 | 45 | 46 | void handle(const Reqest & req) 47 | { 48 | if (canHandleRequest(req)) 49 | processRequest(req); 50 | else 51 | sendReqestToNextHandler(req); 52 | } 53 | }; 54 | 55 | 56 | class Handler1 : public ChainHandler{ 57 | protected: 58 | bool canHandleRequest(const Reqest & req) override 59 | { 60 | return req.getReqType() == RequestType::REQ_HANDLER1; 61 | } 62 | void processRequest(const Reqest & req) override 63 | { 64 | cout << "Handler1 is handle reqest: " << req.getDescription() << endl; 65 | } 66 | }; 67 | 68 | class Handler2 : public ChainHandler{ 69 | protected: 70 | bool canHandleRequest(const Reqest & req) override 71 | { 72 | return req.getReqType() == RequestType::REQ_HANDLER2; 73 | } 74 | void processRequest(const Reqest & req) override 75 | { 76 | cout << "Handler2 is handle reqest: " << req.getDescription() << endl; 77 | } 78 | }; 79 | 80 | class Handler3 : public ChainHandler{ 81 | protected: 82 | bool canHandleRequest(const Reqest & req) override 83 | { 84 | return req.getReqType() == RequestType::REQ_HANDLER3; 85 | } 86 | void processRequest(const Reqest & req) override 87 | { 88 | cout << "Handler3 is handle reqest: " << req.getDescription() << endl; 89 | } 90 | }; 91 | 92 | int main(){ 93 | Handler1 h1; 94 | Handler2 h2; 95 | Handler3 h3; 96 | h1.setNextChain(&h2); 97 | h2.setNextChain(&h3); 98 | 99 | Reqest req("process task ... ", RequestType::REQ_HANDLER3); 100 | h1.handle(req); 101 | return 0; 102 | } 103 | ``` -------------------------------------------------------------------------------- /note/jemalloc.md: -------------------------------------------------------------------------------- 1 | ## Jemalloc 2 | 3 | ## 目录 4 | 5 | * [简介](#简介) 6 | * [hello-world实例](#hello-world实例) 7 | 8 | --- 9 | 10 | https://www.jianshu.com/p/4f9689ffca2d -------------------------------------------------------------------------------- /note/limiter.md: -------------------------------------------------------------------------------- 1 | # 限流 2 | 3 | ## 目录 4 | 5 | * [令牌桶算法](#令牌桶算法) 6 | * [时间漏桶](#时间漏桶) 7 | 8 | --- 9 | 10 | 重要的服务需要做流量控制,保证服务正常工作。常见的招数有如下: 11 | 12 | ## 令牌桶算法 13 | 14 | 1. 每秒会有 r 个令牌放入桶中,或者说,每过 1/r 秒桶中增加一个令牌 15 | 2. 桶中最多存放 b 个令牌,如果桶满了,新放入的令牌会被丢弃 16 | 3. 当一个 n 字节的数据包到达时,消耗 n 个令牌,然后发送该数据包 17 | 4. 如果桶中可用令牌小于 n,则该数据包将被缓存或丢弃 18 | 19 | ![tu](../pic/rate_limit_1.PNG) 20 | 21 | 22 | ## 时间漏桶 23 | 24 | 1. 数据被填充到桶中,并以固定速率注入网络中,而不管数据流的突发性 25 | 2. 如果桶是空的,不做任何事情 26 | 3. 主机在每一个时间片向网络注入一个数据包,因此产生一致的数据流 27 | 28 | ![tu](../pic/rate_limit_2.PNG) 29 | 30 | 小结: 31 | 32 | 如果是一个服务希望限流的话,可以在服务的上游使用时间漏桶,在服务的接口上使用令牌桶。 33 | 34 | 调用方(使用漏桶)--> (使用令牌桶) 限流服务 35 | -------------------------------------------------------------------------------- /note/linux命令_gcc.md: -------------------------------------------------------------------------------- 1 | # gcc 的参数 2 | 3 | 总结一些我用到的一些参数 4 | 5 | -E 6 | 7 | 预处理(但是,它的输出是直接输出到终端,最好重定向一下) 8 | 9 | (对于学c++的同学,可以留意一些这个文件,c++的这个include的机制,展开之后是会编程一个比较大的文件) 10 | ``` 11 | gcc -E hello.c > hello.txt 12 | ``` 13 | 14 | -c 15 | 16 | 只激活预处理,编译,和汇编,也就是他只把程序做成obj文件 17 | ``` 18 | gcc -c hello.c 19 | ``` 20 | 21 | -o 22 | 23 | 制定目标名称,缺省的时候,gcc 编译出来的文件是a.out 24 | 25 | 26 | -I 27 | 28 | 指定查找头文件的路径 29 | 30 | -L 31 | 32 | 指定链接文件或者是库的路径 33 | 34 | -l 35 | 36 | 链接库的名字,比如 -lpthread ,lmuduo 37 | 38 | -M 39 | 40 | 目标文件所依赖的所有源代码 41 | 42 | -O 43 | 44 | -O0 45 | 46 | -O1 47 | 48 | -O2 49 | 50 | -O3 51 | 52 | 编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高 53 | 54 | -Wall 55 | 56 | 生成所有警告信息 57 | 58 | -fno-elide-constructors 59 | 60 | 关闭返回值优化效果 61 | -------------------------------------------------------------------------------- /note/linux命令_linux性能分析和优化3.md: -------------------------------------------------------------------------------- 1 | ## linux性能优化整理一个例子 2 | 3 | ## 目录 4 | * [内存泄漏](#内存泄漏) 5 | 6 | ---- 7 | 8 | 9 | ## 内存泄漏 10 | 11 | ### 1. 内存泄漏导致的问题 12 | 13 | 简单的讲,内存泄漏指的是在堆上面分配的内存没有被free或是delete。 14 | 这样导致的问题是,系统的可用内存不断减少,于是导致: 15 | * 系统启用swap的空间,然后导致性能变差 16 | * 系统开始回收cache和buffer的空间,然后导致性能变差 17 | 18 | ### 2. 如何发现内存泄漏 19 | 20 | 使用memleak工具和valgrind工具可以分析。 21 | 22 | 简单的思路,比如说: 23 | 1. 发现问题,程序oom (out of memory)。 24 | 2. 或者使用free 观察到 可用内存在不停的降低 25 | 3. 使用 memleak 定位 26 | ``` 27 | $ /usr/share/bcc/tools/memleak -p $(pidof app) -a 28 | Attaching to pid 12512, Ctrl+C to quit. 29 | [03:00:41] Top 10 stacks with outstanding allocations: 30 | addr = 7f8f70863220 size = 8192 31 | addr = 7f8f70861210 size = 8192 32 | addr = 7f8f7085b1e0 size = 8192 33 | addr = 7f8f7085f200 size = 8192 34 | addr = 7f8f7085d1f0 size = 8192 35 | 40960 bytes in 5 allocations from stack 36 | fibonacci+0x1f [app] 37 | child+0x4f [app] 38 | start_thread+0xdb [libpthread-2.27.so] 39 | ``` -------------------------------------------------------------------------------- /note/linux命令_make教程.md: -------------------------------------------------------------------------------- 1 | # Make 构建工具 2 | 3 | ## 基本规则 4 | 5 | * make的规则是 6 | ``` 7 | : 8 | [tab] 9 | 10 | # target 表示目标 11 | # prerequisites 表示前置条件 12 | ``` 13 | * 变量 14 | * 定义变量 15 | ``` 16 | cc = g++ 17 | output:p1.txt p2.txt 18 | $(cc) -o ouput test_cast.cpp 19 | ``` 20 | * 调用shell的变量 21 | 调用shell变量,需要加上两个$$ 22 | ``` 23 | test: 24 | echo $$HOME 25 | ``` 26 | 27 | * 自动变量 28 | * $@ 29 | 30 | $@ 指代**当前目标**,就是Make命令当前构建的那个目标。 31 | ``` 32 | a.txt: 33 | touch $@ 34 | 35 | # 约等于 36 | a.txt: 37 | touch a.txt 38 | ``` 39 | 40 | * $< 指代**第一个前置条件**。比如,规则为 t: p1 p2,那么$< 就指代p1。 41 | 42 | ``` 43 | a.txt:p1.txt p2.txt 44 | touch $< 45 | ``` 46 | 47 | * $^ 指代**所有前置条件** 48 | ``` 49 | 比如,规则为 t: p1 p2,那么 $^ 就指代 p1 p2 。 50 | ``` 51 | 52 | * 函数 53 | 54 | * wildcard 函数 55 | ``` 56 | srcfiles := $(wildcard src/*.txt) 57 | ``` 58 | 59 | 一个目录下面所有的.c 文件 60 | ``` 61 | src = $(wildcard *.c ./sub/*.c) 62 | ``` 63 | 64 | ## 简单的例子 65 | 66 | 来自于muduo的make文件 67 | ``` 68 | # 举一个例子 69 | MUDUO_DIRECTORY ?= $(HOME)/code_test/muduo/build/release-install 70 | #MUDUO_DIRECTORY ?= $(HOME)/build/install 71 | MUDUO_INCLUDE = $(MUDUO_DIRECTORY)/include 72 | MUDUO_LIBRARY = $(MUDUO_DIRECTORY)/lib 73 | SRC = ./ 74 | 75 | CXXFLAGS = -g -O0 -Wall -Wextra -Werror \ 76 | -Wconversion -Wno-unused-parameter \ 77 | -Wold-style-cast -Woverloaded-virtual \ 78 | -Wpointer-arith -Wshadow -Wwrite-strings \ 79 | -march=native -rdynamic \ 80 | -I$(MUDUO_INCLUDE) 81 | 82 | LDFLAGS = -L$(MUDUO_LIBRARY) -lmuduo_net -lmuduo_base -lpthread -lrt 83 | 84 | # lmuduo_inspect 85 | all: hub sub pub 86 | clean: 87 | rm -f hub core 88 | 89 | hub: $(SRC)/hub.cc codec.cc 90 | g++ $(CXXFLAGS) -o $@ $^ $(LDFLAGS) 91 | 92 | sub: $(SRC)/sub.cc codec.cc pubsub.cc 93 | g++ $(CXXFLAGS) -o $@ $^ $(LDFLAGS) 94 | 95 | pub: $(SRC)/pub.cc codec.cc pubsub.cc 96 | g++ $(CXXFLAGS) -o $@ $^ $(LDFLAGS) 97 | 98 | .PHONY: all clean 99 | ``` 100 | 101 | * 其他 102 | >[makefile自动推导](https://www.jianshu.com/p/27070bbcba4d) 103 | 104 | -------------------------------------------------------------------------------- /note/linux命令_常用.md: -------------------------------------------------------------------------------- 1 | # Linux 命令 2 | 3 | ## 目录 4 | 5 | * [alias](#alias) 6 | 7 | --- 8 | 9 | ## alias 10 | 11 | 设置alias 12 | 13 | ``` 14 | alias 别名='原命令 -选项/参数' 15 | 16 | 比如: 17 | alias ll='ls -l --color=auto' 18 | ``` 19 | 20 | 查看已经设置的别名列表 21 | ``` 22 | alias -p 23 | ``` 24 | 25 | 删除别名 26 | ``` 27 | unalias 别名 28 | ``` 29 | 30 | 设置别名每次登入可用 31 | 在 ~/.bashrc 文件中 添加 32 | ``` 33 | source ~/.bashrc 34 | ``` -------------------------------------------------------------------------------- /note/linux命令整理.md: -------------------------------------------------------------------------------- 1 | # Linux 乱七八糟的整理 2 | 3 | ## 目录 4 | 5 | * [常用命令](#常用命令) 6 | * [gcc](#gcc命令) 7 | * [机器配置的命令](#配置命令) 8 | * [shell语法](#shell语法) 9 | * [tcpdump](#tcpdump命令) 10 | * [linux系统编程](#linux系统编程) 11 | 12 | ---- 13 | 14 | blog上也整理过一部分: 15 | https://www.jianshu.com/p/f475023f5c8a 16 | 17 | ## 常用命令 18 | > [linux 常用命令](./linux命令_常用.md) 19 | 20 | ## gcc命令 21 | > [linux gcc命令](./linux命令_gcc.md) 22 | 23 | ## 配置命令 24 | > [linux 关于配置的命令](./linux配置.md) 25 | 26 | ## shell语法 27 | > [bash&shell 编程](./bash&shell编程.md) 28 | 29 | ## 让shell跑的更快 shell并行 30 | > [todo](todo) 31 | 32 | ## tcpdump命令 33 | > [linux tcpdump命令](./linux命令_tcpdump.md) 34 | 35 | ## linux系统编程 36 | > [unix环境高级编程](./note/unix环境高级编程.md) 37 | 38 | > [linux网络编程](./note/TCP和网络编程.md) -------------------------------------------------------------------------------- /note/linux配置.md: -------------------------------------------------------------------------------- 1 | ## linux 配置 2 | 3 | ## 目录 4 | * [linux产生core文件](#linux产生core文件) 5 | * [zsh](#zsh) 6 | 7 | --- 8 | 9 | ## linux产生core文件 10 | 11 | 1. 修改corefile文件的大小 12 | ``` 13 | vi /etc/profile 14 | 然后再文件里面添加一句 15 | ulimit -c unlimited 16 | 17 | source /etc/profile #使配置生效 18 | ``` 19 | 20 | ``` 21 | ulimit -c unlimited 22 | # 查看 23 | # 这个时候,已经会产生core文件了 24 | ``` 25 | 26 | 2. 修改配置 27 | ``` 28 | sudo su root 29 | sudo /sbin/sysctl -w kernel.core_pattern=core-%e-%p-%t 30 | ``` 31 | 32 | ``` 33 | # 查看 34 | cat /proc/sys/kernel/core_pattern 35 | core-%e-%p-%t 36 | ``` 37 | 38 | ## zsh 39 | ``` 40 | # 1. 安装zsh 41 | yum -y install zsh 42 | 43 | # 切换sh 44 | chsh -s /bin/zsh 45 | 46 | # 安装oh-my-zsh 47 | sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)" 48 | 49 | # 安装zsh插件 50 | git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting 51 | 52 | git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions 53 | 54 | # 在vim ~/.zshrc添加插件 55 | plugins=( 56 | git 57 | zsh-autosuggestions 58 | zsh-syntax-highlighting 59 | ) 60 | 61 | # 62 | source ~/.zshrc 63 | ``` 64 | 65 | -------------------------------------------------------------------------------- /note/protobuff_with_golang_tutorial.md: -------------------------------------------------------------------------------- 1 | # golang 使用 protobuff hello world 教程 2 | 3 | ## 为什么要protobuff ? 4 | 5 | protobuff的序列化和反序列化编码实现: 6 | https://www.jianshu.com/p/131f0bf218ef 7 | 8 | ## hello world 9 | 10 | 目录结构: 11 | ``` 12 | . 13 | ├── person.pb.go 14 | ├── person.proto 15 | └── server.go 16 | ``` 17 | 18 | person.proto 19 | ``` 20 | syntax = "proto3"; 21 | 22 | package main; 23 | 24 | message Person { 25 | string name = 1; 26 | int32 age = 2; 27 | } 28 | ``` 29 | 30 | server.go 31 | ``` 32 | package main 33 | 34 | import ( 35 | "fmt" 36 | "log" 37 | 38 | proto "github.com/golang/protobuf/proto" 39 | ) 40 | 41 | func main() { 42 | fmt.Println("hello proto") 43 | 44 | elliot := &Person{ 45 | Name: "elliot", 46 | Age: 24, 47 | } 48 | 49 | data, err := proto.Marshal(elliot) 50 | if err != nil { 51 | log.Fatal("Marshal error : ", err) 52 | } 53 | fmt.Println(data) 54 | 55 | newElliot := &Person{} 56 | err = proto.Unmarshal(data, newElliot) 57 | if err != nil { 58 | log.Fatal("unmarshal error : ", err) 59 | } 60 | 61 | fmt.Println(newElliot.GetAge()) 62 | fmt.Println(newElliot.GetName()) 63 | } 64 | ``` 65 | 66 | 构建: 67 | ``` 68 | # 根据proto,导出.go 文件 69 | protoc --go_out=./ *.proto 70 | 71 | # run 72 | go run server.go person.pb.go 73 | ``` -------------------------------------------------------------------------------- /note/reactor模型.md: -------------------------------------------------------------------------------- 1 | # reactor 模型 2 | 3 | * 什么是reactor模型? 4 | 5 | * reactor模型和proactor模型的区别? 6 | 7 | 8 | 我的认识(可能不全面/可能有错误): 9 | ``` 10 | 标准/典型的Reactor: 11 |   - 步骤1:等待事件到来(Reactor负责) 12 |   - 步骤2:将读就绪事件分发给用户定义的处理器(Reactor负责) 13 |   - 步骤3:读数据(用户处理器负责) 14 |   - 步骤4:处理数据(用户处理器负责) 15 | 16 | 改进实现的模拟Proactor: 17 |   - 步骤1:等待事件到来(Proactor负责) 18 |   - 步骤2:得到读就绪事件,执行读数据(现在由Proactor负责) 19 |   - 步骤3:将读完成事件分发给用户处理器(Proactor负责) 20 |   - 步骤4:处理数据(用户处理器负责)  21 | ``` 22 | 23 | 也不知道写的对不对,我觉得类似于学习设计模式这种东西,看一个符合某种模式开发的代码,比学习某一个模式的理论和特点要容易理解一点。 24 | 对于reactor模式,我觉得muduo和redis都可以符合ractor的理念的,尤其是muduo。 -------------------------------------------------------------------------------- /note/一致性哈希.md: -------------------------------------------------------------------------------- 1 | ## 一致性哈希 2 | 3 | 为了保序和充分利用缓存,我们通常希望相同请求 key 的请求总是会被分配到同一个服务节点上,以保持请求的一致性,既有了一致性哈希的调度方式。 4 | 5 | * 割环法 6 | 7 | 割环法将 N 台服务节点地址哈希成 N 组整型值,该组整型即为该服务节点的所有虚拟节点,将所有虚拟节点打散在一个环上。 8 | 9 | ![一致性哈希](../pic/%E4%B8%80%E8%87%B4%E6%80%A7%E5%93%88%E5%B8%8C.png) 10 | 11 | 请求分配过程中,对于给定的对象 key 也哈希映射成整型值,在环上搜索大于该值的第一个虚拟节点,虚拟节点对应的实际节点即为该对象需要映射到的服务节点。 12 | 13 | [代码实现](../example_code/cpp/ConsistentHash.cpp) 14 | 15 | ---- 16 | 17 | * Jump Consistent Hash 18 | 19 | 跳跃哈希 jump consistent hash是由谷歌发明的一致性哈希算法,这个算法的牛逼之处在于,相比传统的环形一致性哈希,空间复杂度更低,根本无内存占用,而且算法非常简洁。计算复杂度为O(logn) 空间复杂度为O(1)。 20 | 21 | ``` 22 | int JumpConsistentHash(unsigned long long key, int num_buckets) 23 | { 24 | long long b = -1, j = 0; 25 | while (j < num_buckets) { 26 | b = j; 27 | key = key * 2862933555777941757ULL + 1; 28 | j = (b + 1) * (double(1LL << 31) / double((key >> 33) + 1)); 29 | } 30 | return b; 31 | } 32 | ``` 33 | 34 | 优点: 35 | 36 | 1. 当桶的数量从 N − 1 增加至 N时, 有 1 / N 的映射结果发生改变。 37 | 38 | 缺点: 39 | 40 | 1. 每个节点的权重相同 41 | 42 | 2. 仅支持在槽位尾端增加或删除节点 43 | 44 | 更多细节: 45 | 46 | https://luyuhuang.tech/2021/06/13/jump-consistent-hash.html 47 | 48 | https://zhuanlan.zhihu.com/p/104124045 -------------------------------------------------------------------------------- /note/书单_技术类_自己整理的.md: -------------------------------------------------------------------------------- 1 | # 技术类书单 2 | 3 | ### cpp 类 4 | 5 | * 《c++ primer》 6 | 7 | * 《more / effective c++》 8 | 9 | * 《深度搜索c++对象模型》 10 | 11 | * 《stl源码分析》 12 | 13 | * 《c++编程规范》 14 | 15 | * 《linux多线程服务器编程——muduo c++网络库》 16 | 17 | * 《c++并发编程实战》 18 | 19 | 这本书的翻译很烂,可以看下面的这个或者英文版 20 | https://chenxiaowei.gitbooks.io/cpp_concurrency_in_action/content/ 21 | 22 | * 《程序员的自我修养》 23 | 24 | ### linux 25 | 26 | * 《unix 环境高级编程》 27 | 28 | * 《linux高性能服务器编程》 29 | 30 | * 《鸟哥的linux私房菜》 31 | 32 | * 《性能之巅》 33 | 34 | 35 | ### 基础类 36 | 37 | * 《深入理解计算机系统》 38 | 39 | * 《编码:隐匿在计算机软硬件背后的语言》 40 | 41 | ### web 42 | 43 | * 《大型网站技术架构核心原理与案例分析》 44 | 45 | 阿里的一位工程师写的,读完这本书,非常非常开阔视野。 46 | 47 | * 《白帽子讲web安全》 48 | 49 | ### other 50 | 51 | * 《改变未来的九大算法》 52 | 53 | 很有趣的一本书,算得上一本很有意思的科普读物。 54 | 55 | * 《淘宝技术十年》 56 | 57 | * 一个Gitbook的书单 58 | 59 | https://legacy.gitbook.com/@wizardforcel 60 | 61 | https://github.com/lizhenghn123/StudyBooks 62 | 63 | 64 | ### 刷题找工作类 65 | 66 | * 《剑指offer》 67 | 68 | 69 | ### 其他教程 70 | 71 | - [学习python,git等都是看的是廖雪峰的教程](https://www.liaoxuefeng.com/) 72 | 73 | 74 | ### 腾讯后台开发推荐书单 75 | 76 | 这是我在腾讯游戏实习的时候,部门推荐的书单。 77 | 78 | 1. 编程基础 79 | 80 | * Thinking in c++ 81 | * effective c++ 82 | * 深入理解C++对象模型 83 | * Google的C++编码规范 84 | 85 | 2. 操作系统 86 | 87 | * apue 88 | * 深入理解计算机系统 89 | * 程序员的自我修养 90 | 91 | 3. 网络 92 | 93 | * UNP1 94 | * TCP/IP1 95 | 96 | 4. 设计 97 | 98 | * 敏捷软件开发 99 | * 重构-改善既有代码的设计 100 | * 设计模式(GOF) 101 | * head first设计模式 102 | 103 | 5. 存储 104 | * mysql manual 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /note/书单和博客.md: -------------------------------------------------------------------------------- 1 | # 书单和博客 2 | 3 | ### 书单 4 | 5 | * [技术类的书单](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/%E4%B9%A6%E5%8D%95_%E6%8A%80%E6%9C%AF%E7%B1%BB_%E8%87%AA%E5%B7%B1%E6%95%B4%E7%90%86%E7%9A%84.md) 6 | 7 | * [江湖上面有人整理出来的技术类书单](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/%E4%B9%A6%E5%8D%95_%E6%8A%80%E6%9C%AF%E7%B1%BB_%E5%88%AB%E4%BA%BA%E6%95%B4%E7%90%86%E7%9A%84%E4%B9%A6%E5%8D%95.md) 8 | 9 | --- 10 | 11 | ### 博客BLOG 12 | 13 | 一些有意思的BLOG 14 | 15 | * [左耳朵耗子的博客](https://coolshell.cn/) 16 | 17 | * [张洋的blog](http://blog.codinglabs.org/pages/about-me.html) 18 | 19 | * [果冻想](https://www.jellythink.com/) 20 | 21 | * [lifeofzjs](http://lifeofzjs.com/) 22 | 23 | * [tiankonguse](http://github.tiankonguse.com/) 24 | 25 | * [关于机器学习的算法的blog](liuyaolei.com/archives/) 26 | 27 | * [阮一峰](http://www.ruanyifeng.com/blog/archives.html) 28 | 29 | * [selfboot](https://selfboot.cn/) 30 | 31 | * [cizixs](https://cizixs.com/) 32 | 33 | * [c++的一个blog — watson2016](https://blog.csdn.net/watson2016/article/list/6) 34 | 35 | * [c++的一个blog — senlinzhan](http://senlinzhan.github.io/) 36 | 37 | * [c++做游戏开发的一个人](https://me.csdn.net/wallwind) -------------------------------------------------------------------------------- /note/工具栈.md: -------------------------------------------------------------------------------- 1 | # 我的工具栈 [ubuntu子系统 + cmder] 2 | 3 | ## 目录 4 | 5 | * [win10 ubuntu子系统](#ubuntu子系统) 6 | * [cmder](#cmder) 7 | * [vscode](#vscode) 8 | * [xshell&crt](xshell&crt) 9 | 10 | --- 11 | ## ubuntu子系统 12 | 13 | window 10 对于我来说,最棒的更新就是加入了ubuntu的子系统。对于我来说,日常写代码是在linux下面,而处理文档,干其他的事情,我又习惯于在winodw下面。这样一个单独的linux和一个单独的window,都没有办法满足我的需求。于是,一直都是window下面开个ssh的终端,连到实验室的服务器上面或者是开虚拟机。window 10 在新的更新里面,加入了ubuntu的子系统。这样就可以非常方便的满足我的全部需求。简直太开心啦。 14 | 15 | * 安装ubuntu子系统 16 | 17 | * 第一步 18 | 19 | 在设置的开发者选项里面,开启开发者模式 20 | ![tu](../pic/工具栈_1.png) 21 | 22 | * 第二步 23 | 24 | 在控制面板的程序里面,开始ubuntu子系统 25 | ![tu](../pic/工具栈_2.png) 26 | 27 | * 第三步 28 | 在window的商店里面 安装ubuntu就可以了 29 | ![tu](../pic/工具栈_3.png) 30 | 31 | * 安装成功,启动ubuntu 32 | 33 | ![tu](../pic/工具栈_4.png) 34 | 35 | * 如何共享文件 36 | 37 | window的磁盘默认挂在ubuntu的 /mnt下面,切换到这个目录下面会找到window的c,d盘。 38 | 39 | 如果想共享一个文件夹,可以创建一个软连接 40 | ``` 41 | sudo ln -s /mnt/d/Downloads Downloads 42 | ``` 43 | 44 | ## cmder 45 | 46 | 安装好ubuntu子系统之后,就可以使用Ubuntu了。但是这个终端的这个字体和配色,并不是很友好。所以,这个cmder的工具就可以发挥出用途。 47 | 48 | cmnder是一个window的下面的一个终端工具,类似于git bash的感觉。通过它来登陆ubuntu,就基本上可以获得一个ubuntu终端的体验。 49 | 50 | ![tu](../pic/工具栈_5.png) 51 | 52 | * 安装和配置的步骤 53 | 54 | * 下载 55 | 56 | http://cmder.net/ 57 | 58 | * 把 cmder 加到环境变量 59 | 60 | 可以把Cmder.exe存放的目录添加到系统环境变量;加完之后,Win+r一下输入cmder,即可。 61 | 62 | * 添加 cmder 到右键菜单 63 | 64 | 在某个文件夹中打开终端, 这个是一个(超级)痛点需求, 实际上上一步的把 cmder 加到环境变量就是为此服务的, 在管理员权限的终端输入以下语句即可: 65 | 66 | ``` 67 | Cmder.exe /REGISTER ALL 68 | ``` 69 | 70 | * 配置进入ubuntu的快捷方式 71 | ``` 72 | %windir%\system32\bash.exe ~ -cur_console:p:n 73 | ``` 74 | 75 | ![tu](../pic/工具栈_6.png) 76 | 77 | * 将ubuntu设置为默认的启动选项 78 | 79 | ![tu](../pic/工具栈_7.png) 80 | 81 | * 修改 $ 的符号 82 | 83 | 设置界面 > mian > font > monospce,去掉那勾勾即可。 84 | 85 | -------------------------------------------------------------------------------- /note/开源项目.md: -------------------------------------------------------------------------------- 1 | # 开源项目 2 | 3 | ## 目录 4 | 5 | * 微信C++协程库 [腾讯Libco](https://github.com/Tencent/libco) | [民间版本](https://github.com/linw7/Libco-Reading) 6 | * Http 服务器 [TKeed](https://github.com/linw7/TKeed) 7 | * [WebBench](https://github.com/zhaozhengcoder/rebuild-the-wheel) 8 | * [tinyhttp](https://github.com/zhaozhengcoder/rebuild-the-wheel) 9 | * [cjson](https://github.com/zhaozhengcoder/rebuild-the-wheel) 10 | * [muduo](https://github.com/zhaozhengcoder/muduo) 11 | --- 12 | -------------------------------------------------------------------------------- /note/收集见到过的一些工具和轮子.md: -------------------------------------------------------------------------------- 1 | # 收集见到过的一些小工具,代码片段或轮子 2 | 3 | ## 目录 4 | 5 | * STL中的string没有默认的split方法 [提供一些相关的字符串split实现](https://mp.weixin.qq.com/s/LdiMuhY0IDFCP8V1dPxg-g) 6 | 7 | * [cpp线程池](https://mp.weixin.qq.com/s/uz85-w9ZfwRP0ZZCI7jOzQ) 8 | 9 | * [c98实现的线程池](../example_code/thread_pool/README.md) 10 | 11 | * [cpp对象池](https://mp.weixin.qq.com/s/bWe8dLs-sgoCI_5sQbeOaw) -------------------------------------------------------------------------------- /note/数据库_mvcc.md: -------------------------------------------------------------------------------- 1 | # 数据库MVCC机制 2 | 3 | ## 目录 4 | 5 | * [mvcc的具体实现原理](#mvcc的具体实现原理) 6 | 7 | * [mvcc是否可以解决幻读?](#mvcc是否可以解决幻读) 8 | 9 | --- 10 | 11 | ## mvcc的具体实现原理? 12 | 13 | * mvcc的两种读模式 14 | 1. 当前读 15 | 16 | 读最新版本是数据,主要应用于更新操作。 17 | 18 | ``` 19 | select * from table where xxx lock in share mode, 20 | select * from table where xxx for update, 21 | update table set.... 22 | insert into table (xxx,xxx) values (xxx,xxx) 23 | delete from table where id = xxx 24 | ``` 25 | 26 | 2. 快照读 27 | 28 | 比如开启一个select查询的事务的时候,读取的只是当前事务的可见版本. 29 | 30 | * mvcc实现的原理 31 | 32 | 每行记录携带几个隐藏字段 33 | 34 | |isDelete |DB_TRX_ID |DB_ROLL_PTR| 35 | | ---- | ---- | ---- | 36 | |true/false| 事务id |回滚指针 | 37 | 38 | 示意图如下: 39 | ![tu](../pic/mvcc.png) 40 | 41 | * mvcc如何解决脏读,不可重复读? 42 | 43 | todo 44 | 45 | ## mvcc是否可以解决幻读? 46 | 47 | 那么说RR模式下利用MVCC可以解决一定程度上的幻读,但是MySQL没有使用,利用了GAP锁来保证了严格的幻读,其实也就是串行化的一种实现方式吧吗。 48 | 49 | 如下面的例子,有两个事务,在RR隔离级别下, select是没有幻读的,但select for update却会产生幻读。因为select是读,通过时间戳读快照,事务2读不到事务1的写入。**而select for update被认为是写,是可以更新已提交数据的,所以读到的是最新版本,事务2可以读到事务1的写入。** 50 | 51 | ``` 52 | 事务1 事务2 53 | 54 | mysql> start transaction; mysql> start transaction; 55 | Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.00 sec) 56 | 57 | 58 | mysql> select * from t; 59 | Empty set (0.00 sec) 60 | mysql> insert into t values(1); 61 | Query OK, 1 row affected (0.00 sec) 62 | mysql> commit; 63 | Query OK, 0 rows affected (0.01 sec) 64 | // no phantom 65 | mysql> select * from t; 66 | Empty set (0.00 sec) 67 | 68 | // phantom 69 | mysql> select * from t for update; 70 | +------+ 71 | | c | 72 | +------+ 73 | | 1 | 74 | +------+ 75 | 1 row in set (0.00 sec) 76 | // update committed row 77 | mysql> update t set c=2; 78 | Query OK, 0 rows affected (0.00 sec) 79 | Rows matched: 1 Changed: 0 Warnings: 0 80 | 81 | mysql> commit; 82 | Query OK, 0 rows affected (0.01 sec) 83 | ``` 84 | 85 | 86 | --- 87 | 88 | ## 参考 89 | 90 | 1. https://www.zhihu.com/question/334408495/answer/745098902 -------------------------------------------------------------------------------- /note/系统设计.md: -------------------------------------------------------------------------------- 1 | 2 | # 系统设计 3 | 4 | 系统设计需要考虑的三点: 5 | 6 | * 高性能 7 | 8 | * 高可用 9 | 10 | * 可扩展 11 | 12 | ----- 13 | 14 | ## 高性能 15 | 16 | 性能优化首先要有一个完善的监控体系来度量性能指标。 17 | 18 | 比如 19 | * 机器层面的 cpu,内存,io,网络等指标; 20 | 21 | * 应用层面的 请求的平均响应时间(处理时间) 22 | 23 | 24 | 性能优化的“八二原则”, 25 | 大概的意思就是,少量的热点逻辑 消耗的大量的性能。所以,性能优化的第一部就是定位到热点,然后结合业务去优化和取舍(时间换空间,空间换时间,限流,降级,平滑等) 26 | 27 | 28 | 大部分的接口的性能都遵守这种图: 29 | ![](../pic/%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A11.png) 30 | 31 | ---- 32 | 33 | ## 高可用 34 | 35 | 1. 如何量化高可用性,评价指标是什么? 36 | 37 | GOOGLE SRE 里面提及了很多指标,大概就是系统是几个9,比如99%,99.9%, 99.99% 等。 38 | 39 | 2. 设计系统的时候,需要在可靠性方面 注意什么? (design for failure) 40 | 41 | 在设计系统的时候,把发生故障作为一个重要的考虑点,预先考虑如何自动化地发现故障,发生故障之后要如何解决。 42 | 43 | 当然,除了要有未雨绸缪外,我们还需要掌握一些具体的优化方法,比如 failover(故障转移)、超时控制以及降级和限流。 44 | 45 | * 故障转移 46 | 47 | 一个节点挂了,可以切换到其他的节点,或者可以重新拉起,或者有重试机制等。 48 | 49 | 最广泛的故障检测机制是“心跳”,一个很经典的问题,就是系统的超时时间要设为多少? 50 | 51 | 很多时候都是拍脑门,随便定一个。 52 | 53 | GOOGLE SRE 里面也提到这个事,比较科学的办法是,可以看下这台机器(或者这个接口)正常情况下,一个请求的响应时间是多少,拉出来一个分布图,大于99%或者是超过个比例 作为参考。 54 | 55 | * 服务降级 56 | 57 | 当机器进入一个危险状态,丢弃掉或者拒绝掉一些不重要的服务,保证核心功能正常。 58 | 59 | * 限流 (平滑队列)等 60 | 61 | 请求进行限速来保护系统 62 | 63 | ------ 64 | 65 | ### 可扩展性 66 | 67 | 我理解,可扩展性是希望可以通过平行扩展(加机器的方式,而不是提供单台机器性能的方式)去提高性能的性能。或者是提供系统的可用性。 68 | 69 | 不过,这个话题更多的是要结合业务的特性去考虑,比如是否是有状态服务或无状态服务。如果是无状态的服务,那问题就会好很多。 70 | 71 | 尝试从几个方面去思考,比如: 72 | 73 | 1. 从数据的层面 74 | 75 | 分库分表,水平拆分,垂直拆分 76 | 77 | 2. 从应用的层面 78 | 79 | 按照有无状态,业务的功能(类似微服务的思想),进程的重要性 等角度去拆分 -------------------------------------------------------------------------------- /note/系统设计类的问题.md: -------------------------------------------------------------------------------- 1 | # 系统设计类的问题 2 | 3 | ## 目录 4 | 5 | * [QPS限流](#QPS限流) 6 | 7 | --- 8 | 9 | ## QPS限流 10 | 11 | 设计一个接口,接口的输入是任意一个url,使得url的qps被限制在1000 QPS 以内。(即每秒的调用此时小于1000) 12 | 13 | 14 | * 方法一:time-bucket 15 | ``` 16 | int url_bucket_time = getCurrentSecond(); //记录的秒 17 | int url_bucket_num = 0; //在当前的秒内被访问的次数 18 | 19 | bool Acquire(string url,int qps) 20 | { 21 | now = getCurrentSecond(); 22 | if( now - url_bucket_time < 1) //如果是同一秒,那么可以确定url_bucket_num表示的是这一秒被访问的次数 23 | { 24 | if (url_bucket_num >= qps) 25 | return false; 26 | else 27 | { 28 | url_bucket_num++; 29 | return true; 30 | } 31 | } 32 | else 33 | { 34 | url_bucket_time = getCurrentSecond(); 35 | url_bucket_num = 0; 36 | 37 | url_bucket_num++; 38 | return true; 39 | } 40 | } 41 | ``` 42 | 43 | * 方法二:队列算法 44 | 45 | 开辟一个大小为1000的队列(在这里requestList其实一个循环数组) 46 | 47 | **这个可以确保在任何一秒的qps都是1000以内** 48 | ``` 49 | int qps = 1000; 50 | requestList = new requestList[qps]; // 并将它初始化为0 51 | int index = 0; 52 | 53 | Acquire(): 54 | curSecond = getCurrentSecond(); 55 | if (curSecond - requestList[index]) > 1) 56 | { 57 | requestList[index] = curSecond; 58 | index = (index+1)%qps; 59 | return true; 60 | } 61 | else 62 | { 63 | return false; 64 | } 65 | ``` 66 | 67 | ## 改进版 68 | 69 | 设计一个接口,接口的输入是一个url,**每个url**的qps被限制在1000 QPS 以内。 70 | 71 | (和上一个的区别是,这个是每个url分别都要小于1000 qps,上一个问题是,不区分url,只是确保url总的被调用次数小于1000 qps) 72 | 73 | ``` 74 | int url_bucket_time = getCurrentSecond(); 75 | map url_bucket; 76 | 77 | bool Acquire(string url,int qps) 78 | { 79 | now = getCurrentSecond(); 80 | if( now - url_bucket_time < 1) 81 | { 82 | // 在同一秒之内 83 | if (counter[url] >= qps) 84 | return false; 85 | else 86 | { 87 | counter[url]++; 88 | return true; 89 | } 90 | } 91 | else 92 | { 93 | //不在同一秒之内 94 | //清空桶 95 | url_bucket_time = getCurrentSecond(); 96 | url_bucket.erase(); 97 | 98 | counter[url]++; 99 | eturn true; 100 | } 101 | } 102 | ``` 103 | 104 | 105 | --- -------------------------------------------------------------------------------- /note/缓存系统.md: -------------------------------------------------------------------------------- 1 | # 缓存系统 2 | 3 | https://www.jianshu.com/p/057da7850c93 -------------------------------------------------------------------------------- /note/编码需要注意的问题.md: -------------------------------------------------------------------------------- 1 | # 编码需要注意的问题 2 | 3 | ## 编码规范 4 | 5 | * 空格 6 | ``` 7 | if (a == b) 8 | ``` 9 | 10 | ``` 11 | for (int i = 0; i < 100; i++) 12 | { 13 | 14 | } 15 | ``` 16 | 17 | ``` 18 | int val = 100; 19 | ``` 20 | * 换行 21 | ``` 22 | // 换行 23 | mailsvr_xxxx_xxxx_xxxx(id 24 | , send_time, cb); 25 | ``` 26 | 27 | 28 | ## 语法 29 | 30 | * 尽可能的不要传递值,而是传递引用或指针 31 | 32 | * log尽量打的全面一点,不要很草率的写log 33 | 34 | 比如,rid是多少,xxxid是多少,ret是多少。原则上可以根据这条log发现足够多的bug信息。而不是没有意义的log。 35 | 36 | **举个例子** 37 | 写代码的逻辑的时候,是针对某一个用户id去是思考这个逻辑。(也可以理解为人在写代码的时候,是同步的思考逻辑。)但是,机器执行代码的时候,是异步的逻辑,同时会有无数个用户在跑这一份代码,每个用户执行这段代码顺序的先后也是不一样的。 38 | 39 | 也就是说,如果代码里面是这样写的: 40 | ``` 41 | print("last login time : %d", last_login_time); 42 | ``` 43 | 44 | 如果测试的时候,只有一个用户登陆,那么没有问题。可以看到这个用户的上次登陆时间。但是,如果切换到正式的环境,这条log的信息,打出来的信息基本上是没有参考意义的。当一百个用户开始登陆,每个用户都打印出一条信息,debug的时候,还是不知道那个用户上次登陆的时间是什么时候。 45 | 46 | * 函数里面的比较大的结构体,使用stattic去创建。 47 | 48 | ``` 49 | struct LARGE_STRUCT 50 | { 51 | // XXXX 52 | }; 53 | 54 | int func() 55 | { 56 | static LARGE_STRUCT large_struct; 57 | memset(&large_struct, 0, sizeof(large_strut)); 58 | 59 | } 60 | ``` 61 | 62 | 这样的好处是large_struct变量不会被频繁的创建。 63 | 64 | * 函数的接口设计,起码让调用的人 比较好理解。 65 | 66 | ``` 67 | int rt_dump_to_db(IN const RT & rt, OUT DB & db) 68 | { 69 | 70 | } 71 | ``` 72 | 73 | * 两个结构体赋值的时候,记得memset一下。除非你可以保证里面的两个结构体的字段可以完全被赋值过。 74 | ``` 75 | int rt_dump_to_db(IN const RT & rt, OUT DB & db) 76 | { 77 | memset(&rt, 0, sizeof(rt)); 78 | } 79 | ``` 80 | 81 | * 循环语句记得要留意边界条件 82 | ``` 83 | int target_arr[len]; 84 | int target_idx = 0; 85 | for (int i = 0; i < count; i++) 86 | { 87 | target_arr[target_idx] = i; 88 | 89 | 90 | target_idx++; 91 | } 92 | ``` 93 | 94 | * 条件语句要检查不同的分支 95 | ``` 96 | if (val达到上限) 97 | { 98 | val = 上限 99 | } 100 | val = val + 100 // fix me 应该走不同的分支,漏掉else了 101 | ``` -------------------------------------------------------------------------------- /note/设计模式.md: -------------------------------------------------------------------------------- 1 | ## 设计模式 2 | 3 | 一个非常强的分享设计模式的网站,居然还tm支持了中文。 4 | 5 | https://refactoringguru.cn/ 6 | 7 | ---- 8 | 9 | >[《重构》的笔记](./《重构》的笔记.md) 10 | 11 | >[设计模型的几个原则](./设计模式的基本原则.md) 12 | 13 | #### 1. 创建型模式 14 | >[单例模式](./design_pattern/note/4单例模式.md) 15 | 16 | >[工厂模式](./design_pattern/note/3工厂模式.md) 17 | 18 | 19 | #### 2. 结构型模式 20 | 21 | 结构型模式(Structural Pattern)描述如何将类或者对 象结合在一起形成更大的结构,就像搭积木,可以通过 简单积木的组合形成复杂的、功能更为强大的结构。 22 | 23 | >[装饰器模式](./design_pattern/note/10装饰器模式.md) 24 | 25 | >[facade模式](./design_pattern/note/12门面fecade模式.md) 26 | 27 | >[proxy模式](./design_pattern/note/6代理模式.md) 28 | 29 | >[adapter模式](./design_pattern/note/7适配器模式.md) 30 | 31 | >[享元模式](./design_pattern/note/5享元模式.md) 32 | 33 | #### 3. 行为型模式 34 | 35 | 行为型模式(Behavioral Pattern)是对在不同的对象之间划分责任和算法的抽象化。 36 | 37 | >[模板方法模式](./design_pattern/note/0模板模式.md) 38 | 39 | >[策略模式](./design_pattern/note/1策略模式.md) 40 | 41 | >[观察者模式](./design_pattern/note/2观察者模式.md) 42 | 43 | >[责任链模式](./design_pattern/note/9责任链模式.md) 44 | 45 | #### 参考: 46 | 47 | gof 设计模式 48 | 49 | https://www.liaoxuefeng.com/wiki/1252599548343744/1264742167474528 50 | 51 | https://github.com/rhyspang/CPP-Design-Patterns 52 | 53 | https://design-patterns.readthedocs.io/zh_CN/latest/index.html -------------------------------------------------------------------------------- /pic/Linux性能分析2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/Linux性能分析2.jpg -------------------------------------------------------------------------------- /pic/Linux性能分析3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/Linux性能分析3.jpg -------------------------------------------------------------------------------- /pic/Linux性能分析4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/Linux性能分析4.jpg -------------------------------------------------------------------------------- /pic/apue笔记.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/apue笔记.jpg -------------------------------------------------------------------------------- /pic/brk1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/brk1.png -------------------------------------------------------------------------------- /pic/docker_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/docker_1.png -------------------------------------------------------------------------------- /pic/docker_pic.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/docker_pic.PNG -------------------------------------------------------------------------------- /pic/git_1.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/git_1.JPG -------------------------------------------------------------------------------- /pic/git_2.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/git_2.JPG -------------------------------------------------------------------------------- /pic/git_3.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/git_3.JPG -------------------------------------------------------------------------------- /pic/git_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/git_4.png -------------------------------------------------------------------------------- /pic/git_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/git_5.png -------------------------------------------------------------------------------- /pic/git_6.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/git_6.JPG -------------------------------------------------------------------------------- /pic/innodb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/innodb.png -------------------------------------------------------------------------------- /pic/innodb2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/innodb2.png -------------------------------------------------------------------------------- /pic/linux性能分析1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/linux性能分析1.PNG -------------------------------------------------------------------------------- /pic/make_pic1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/make_pic1.png -------------------------------------------------------------------------------- /pic/malloc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/malloc.png -------------------------------------------------------------------------------- /pic/malloc2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/malloc2.png -------------------------------------------------------------------------------- /pic/malloc3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/malloc3.png -------------------------------------------------------------------------------- /pic/mvcc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/mvcc.png -------------------------------------------------------------------------------- /pic/myisam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/myisam.png -------------------------------------------------------------------------------- /pic/mysql.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/mysql.png -------------------------------------------------------------------------------- /pic/perf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/perf.png -------------------------------------------------------------------------------- /pic/px_pic1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/px_pic1.png -------------------------------------------------------------------------------- /pic/px_pic2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/px_pic2.png -------------------------------------------------------------------------------- /pic/px_pic3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/px_pic3.png -------------------------------------------------------------------------------- /pic/rate_limit_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/rate_limit_1.png -------------------------------------------------------------------------------- /pic/rate_limit_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/rate_limit_2.png -------------------------------------------------------------------------------- /pic/tcp1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/tcp1.PNG -------------------------------------------------------------------------------- /pic/tcp2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/tcp2.PNG -------------------------------------------------------------------------------- /pic/tcp3.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/tcp3.PNG -------------------------------------------------------------------------------- /pic/uml_aggregation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/uml_aggregation.png -------------------------------------------------------------------------------- /pic/uml_assocation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/uml_assocation.png -------------------------------------------------------------------------------- /pic/uml_composition.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/uml_composition.png -------------------------------------------------------------------------------- /pic/uml_dependency.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/uml_dependency.png -------------------------------------------------------------------------------- /pic/uml_inhert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/uml_inhert.png -------------------------------------------------------------------------------- /pic/一致性哈希.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/一致性哈希.png -------------------------------------------------------------------------------- /pic/内存_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/内存_1.png -------------------------------------------------------------------------------- /pic/函数调用1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/函数调用1.png -------------------------------------------------------------------------------- /pic/函数调用2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/函数调用2.png -------------------------------------------------------------------------------- /pic/函数调用3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/函数调用3.png -------------------------------------------------------------------------------- /pic/函数调用4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/函数调用4.png -------------------------------------------------------------------------------- /pic/函数调用简单的汇编介绍.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/函数调用简单的汇编介绍.pdf -------------------------------------------------------------------------------- /pic/多态和虚函数_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/多态和虚函数_1.jpg -------------------------------------------------------------------------------- /pic/多态和虚函数_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/多态和虚函数_2.jpg -------------------------------------------------------------------------------- /pic/工具栈_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/工具栈_1.png -------------------------------------------------------------------------------- /pic/工具栈_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/工具栈_2.png -------------------------------------------------------------------------------- /pic/工具栈_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/工具栈_3.png -------------------------------------------------------------------------------- /pic/工具栈_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/工具栈_4.png -------------------------------------------------------------------------------- /pic/工具栈_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/工具栈_5.png -------------------------------------------------------------------------------- /pic/工具栈_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/工具栈_6.png -------------------------------------------------------------------------------- /pic/工具栈_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/工具栈_7.png -------------------------------------------------------------------------------- /pic/数据库_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/数据库_1.jpg -------------------------------------------------------------------------------- /pic/数据库_2ACID.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/数据库_2ACID.png -------------------------------------------------------------------------------- /pic/数据库_3隔离等级.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/数据库_3隔离等级.png -------------------------------------------------------------------------------- /pic/数据库索引_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/数据库索引_1.jpg -------------------------------------------------------------------------------- /pic/系统设计1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaozhengcoder/CoderNoteBook/a43add2f7eee10dab723c8c76621f9e4a641c6cc/pic/系统设计1.png --------------------------------------------------------------------------------