Skip to content

Commit c2980a0

Browse files
committed
加入chrono模块,函数变参,async,类概念等内容,未来将移除算法模版模块,移动到go仓库中
1 parent a45f728 commit c2980a0

File tree

32 files changed

+1484
-17
lines changed

32 files changed

+1484
-17
lines changed

.DS_Store

-10 KB
Binary file not shown.

.gitignore

-8
This file was deleted.

2-function/exercise-8-可变参数/main.cpp

+19-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
#include <iostream>
22
#include <initializer_list>
3+
#include <string>
34
#include <cstdarg>
45

56
// C 风格获取可变参数
67
void print_age(int length, bool sex, ...){
78
va_list list;
89
// 告诉list,可变参数有多少个
9-
va_start(list, length);
10+
va_start(list, sex);
1011

1112
std::cout<< "可变参数总数: " << length << std::endl;
1213
std::cout << "性别男?" << sex << std::endl;
@@ -24,7 +25,8 @@ void print_age(int length, bool sex, ...){
2425
va_end(list);
2526
}
2627

27-
28+
// C++风格
29+
// 缺点是传入的是 {} 列表,不是变长参数
2830
void print_age(std::initializer_list<int> list) {
2931

3032
auto start = list.begin();
@@ -33,13 +35,28 @@ void print_age(std::initializer_list<int> list) {
3335
for( ; start != end; start += 1) std::cout << "age: " << *start << std::endl;
3436
}
3537

38+
// C++风格
39+
// 模版方式
40+
template<typename T>
41+
void print_name(const T& value) {
42+
std::cout << value << " " ;
43+
}
44+
45+
template<typename K , typename... T>
46+
void print_name(const K& value, const T& ...args) {
47+
std::cout << value << " ";
48+
print_name(args...);
49+
}
50+
3651

3752
int main() {
3853
print_age(4, false, 10, 34, 23, 17);
3954

4055
std::cout << std::endl;
4156

4257
print_age({24, 21, 26, 15, 19, 12});
58+
59+
print_name("Jack", "Peter", "Nancy");
4360
}
4461

4562
//

27-epoll/main.cpp

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
#include <sys/socket.h>
2+
#include <sys/epoll.h>
3+
#include <netinet/in.h>
4+
#include <arpa/inet.h>
5+
#include <fcntl.h>
6+
#include <unistd.h>
7+
#include <stdio.h>
8+
#include <errno.h>
9+
#include <string.h>
10+
#include <stdlib.h>
11+
12+
#define exit_if(r, ...) if(r) {printf(__VA_ARGS__); printf("error no: %d error msg %s\n", errno, strerror(errno)); exit(1);}
13+
14+
void setNonBlock(int fd) {
15+
int flags = fcntl(fd, F_GETFL, 0);
16+
exit_if(flags<0, "fcntl failed");
17+
int r = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
18+
exit_if(r<0, "fcntl failed");
19+
}
20+
21+
void updateEvents(int efd, int fd, int events, int op) {
22+
struct epoll_event ev;
23+
memset(&ev, 0, sizeof(ev));
24+
ev.events = events;
25+
ev.data.fd = fd;
26+
printf("%s fd %d events read %d write %d\n",
27+
op==EPOLL_CTL_MOD?"mod":"add", fd, ev.events & EPOLLIN, ev.events & EPOLLOUT);
28+
int r = epoll_ctl(efd, op, fd, &ev);
29+
exit_if(r, "epoll_ctl failed");
30+
}
31+
32+
void handleAccept(int efd, int fd) {
33+
struct sockaddr_in raddr;
34+
socklen_t rsz = sizeof(raddr);
35+
int cfd = accept(fd,(struct sockaddr *)&raddr,&rsz);
36+
exit_if(cfd<0, "accept failed");
37+
sockaddr_in peer, local;
38+
socklen_t alen = sizeof(peer);
39+
int r = getpeername(cfd, (sockaddr*)&peer, &alen);
40+
exit_if(r<0, "getpeername failed");
41+
printf("accept a connection from %s\n", inet_ntoa(raddr.sin_addr));
42+
setNonBlock(cfd);
43+
updateEvents(efd, cfd, EPOLLIN|EPOLLOUT, EPOLL_CTL_ADD);
44+
}
45+
46+
void handleRead(int efd, int fd) {
47+
char buf[4096];
48+
int n = 0;
49+
while ((n=::read(fd, buf, sizeof buf)) > 0) {
50+
printf("read %d bytes\n", n);
51+
int r = ::write(fd, buf, n); //写出读取的数据
52+
//实际应用中,写出数据可能会返回EAGAIN,此时应当监听可写事件,当可写时再把数据写出
53+
exit_if(r<=0, "write error");
54+
}
55+
if (n<0 && (errno == EAGAIN || errno == EWOULDBLOCK))
56+
return;
57+
exit_if(n<0, "read error"); //实际应用中,n<0应当检查各类错误,如EINTR
58+
printf("fd %d closed\n", fd);
59+
close(fd);
60+
}
61+
62+
void handleWrite(int efd, int fd) {
63+
//实际应用应当实现可写时写出数据,无数据可写才关闭可写事件
64+
updateEvents(efd, fd, EPOLLIN, EPOLL_CTL_MOD);
65+
}
66+
67+
void loop_once(int efd, int lfd, int waitms) {
68+
const int kMaxEvents = 20;
69+
struct epoll_event activeEvs[100];
70+
int n = epoll_wait(efd, activeEvs, kMaxEvents, waitms);
71+
printf("epoll_wait return %d\n", n);
72+
for (int i = 0; i < n; i ++) {
73+
int fd = activeEvs[i].data.fd;
74+
int events = activeEvs[i].events;
75+
if (events & (EPOLLIN | EPOLLERR)) {
76+
if (fd == lfd) {
77+
handleAccept(efd, fd);
78+
} else {
79+
handleRead(efd, fd);
80+
}
81+
} else if (events & EPOLLOUT) {
82+
handleWrite(efd, fd);
83+
} else {
84+
exit_if(1, "unknown event");
85+
}
86+
}
87+
}
88+
89+
int main() {
90+
short port = 99;
91+
int epollfd = epoll_create(1);
92+
exit_if(epollfd < 0, "epoll_create failed");
93+
int listenfd = socket(AF_INET, SOCK_STREAM, 0);
94+
exit_if(listenfd < 0, "socket failed");
95+
struct sockaddr_in addr;
96+
memset(&addr, 0, sizeof addr);
97+
addr.sin_family = AF_INET;
98+
addr.sin_port = htons(port);
99+
addr.sin_addr.s_addr = INADDR_ANY;
100+
int r = ::bind(listenfd,(struct sockaddr *)&addr, sizeof(struct sockaddr));
101+
exit_if(r, "bind to 0.0.0.0:%d failed %d %s", port, errno, strerror(errno));
102+
r = listen(listenfd, 20);
103+
exit_if(r, "listen failed %d %s", errno, strerror(errno));
104+
printf("fd %d listening at %d\n", listenfd, port);
105+
setNonBlock(listenfd);
106+
updateEvents(epollfd, listenfd, EPOLLIN, EPOLL_CTL_ADD);
107+
for (;;) { //实际应用应当注册信号处理函数,退出时清理资源
108+
loop_once(epollfd, listenfd, 10000);
109+
}
110+
return 0;
111+
}

28-kqueue/main.cpp

+131
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
// 使用 socket AF_XXX SOCK_XXX sockaddr 必备
2+
#include <sys/socket.h>
3+
// 使用 kqueue kevent EV_XXX EVYYY_XXX 必备
4+
#include <sys/event.h>
5+
// 使用 sockaddr_in 必备
6+
#include <netinet/in.h>
7+
// 使用 inet_ntoa 必备
8+
#include <arpa/inet.h>
9+
// 使用 fcntl F_XXX O_XXX 必备
10+
#include <fcntl.h>
11+
#include <unistd.h>
12+
#include <stdio.h>
13+
// 使用 errno 必备
14+
#include <errno.h>
15+
#include <string.h>
16+
#include <stdlib.h>
17+
18+
#define exit_if(r, ...) if(r) {printf(__VA_ARGS__); printf("error no: %d error msg %s\n", errno, strerror(errno)); exit(1);}
19+
20+
const int kReadEvent = 1;
21+
const int kWriteEvent = 2;
22+
23+
void setNonBlock(int fd) {
24+
int flags = fcntl(fd, F_GETFL, 0);
25+
exit_if(flags<0, "fcntl failed");
26+
int r = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
27+
exit_if(r<0, "fcntl failed");
28+
}
29+
30+
void updateEvents(int efd, int fd, int events, bool modify) {
31+
struct kevent ev[2];
32+
int n = 0;
33+
if (events & kReadEvent) {
34+
EV_SET(&ev[n++], fd, EVFILT_READ, EV_ADD|EV_ENABLE, 0, 0, (void*)(intptr_t)fd);
35+
} else if (modify){
36+
EV_SET(&ev[n++], fd, EVFILT_READ, EV_DELETE, 0, 0, (void*)(intptr_t)fd);
37+
}
38+
if (events & kWriteEvent) {
39+
EV_SET(&ev[n++], fd, EVFILT_WRITE, EV_ADD|EV_ENABLE, 0, 0, (void*)(intptr_t)fd);
40+
} else if (modify){
41+
EV_SET(&ev[n++], fd, EVFILT_WRITE, EV_DELETE, 0, 0, (void*)(intptr_t)fd);
42+
}
43+
printf("%s fd %d events read %d write %d\n",
44+
modify ? "mod" : "add", fd, events & kReadEvent, events & kWriteEvent);
45+
int r = kevent(efd, ev, n, NULL, 0, NULL);
46+
exit_if(r, "kevent failed ");
47+
}
48+
49+
void handleAccept(int efd, int fd) {
50+
struct sockaddr_in raddr;
51+
socklen_t rsz = sizeof(raddr);
52+
int cfd = accept(fd,(struct sockaddr *)&raddr,&rsz);
53+
exit_if(cfd<0, "accept failed");
54+
sockaddr_in peer, local;
55+
socklen_t alen = sizeof(peer);
56+
int r = getpeername(cfd, (sockaddr*)&peer, &alen);
57+
exit_if(r<0, "getpeername failed");
58+
printf("accept a connection from %s\n", inet_ntoa(raddr.sin_addr));
59+
setNonBlock(cfd);
60+
updateEvents(efd, cfd, kReadEvent|kWriteEvent, false);
61+
}
62+
63+
void handleRead(int efd, int fd) {
64+
char buf[4096];
65+
int n = 0;
66+
while ((n=::read(fd, buf, sizeof buf)) > 0) {
67+
printf("read %d bytes\n", n);
68+
int r = ::write(fd, buf, n); //写出读取的数据
69+
//实际应用中,写出数据可能会返回EAGAIN,此时应当监听可写事件,当可写时再把数据写出
70+
exit_if(r<=0, "write error");
71+
}
72+
if (n<0 && (errno == EAGAIN || errno == EWOULDBLOCK))
73+
return;
74+
exit_if(n<0, "read error"); //实际应用中,n<0应当检查各类错误,如EINTR
75+
printf("fd %d closed\n", fd);
76+
close(fd);
77+
}
78+
79+
void handleWrite(int efd, int fd) {
80+
//实际应用应当实现可写时写出数据,无数据可写才关闭可写事件
81+
updateEvents(efd, fd, kReadEvent, true);
82+
}
83+
84+
void loop_once(int efd, int lfd, int waitms) {
85+
struct timespec timeout;
86+
timeout.tv_sec = waitms / 1000;
87+
timeout.tv_nsec = (waitms % 1000) * 1000 * 1000;
88+
const int kMaxEvents = 20;
89+
struct kevent activeEvs[kMaxEvents];
90+
int n = kevent(efd, NULL, 0, activeEvs, kMaxEvents, &timeout);
91+
printf("epoll_wait return %d\n", n);
92+
for (int i = 0; i < n; i ++) {
93+
int fd = (int)(intptr_t)activeEvs[i].udata;
94+
int events = activeEvs[i].filter;
95+
if (events == EVFILT_READ) {
96+
if (fd == lfd) {
97+
handleAccept(efd, fd);
98+
} else {
99+
handleRead(efd, fd);
100+
}
101+
} else if (events == EVFILT_WRITE) {
102+
handleWrite(efd, fd);
103+
} else {
104+
exit_if(1, "unknown event");
105+
}
106+
}
107+
}
108+
109+
int main() {
110+
short port = 99;
111+
int epollfd = kqueue();
112+
exit_if(epollfd < 0, "epoll_create failed");
113+
int listenfd = socket(AF_INET, SOCK_STREAM, 0);
114+
exit_if(listenfd < 0, "socket failed");
115+
struct sockaddr_in addr;
116+
memset(&addr, 0, sizeof addr);
117+
addr.sin_family = AF_INET;
118+
addr.sin_port = htons(port);
119+
addr.sin_addr.s_addr = INADDR_ANY;
120+
int r = ::bind(listenfd,(struct sockaddr *)&addr, sizeof(struct sockaddr));
121+
exit_if(r, "bind to 0.0.0.0:%d failed %d %s", port, errno, strerror(errno));
122+
r = listen(listenfd, 20);
123+
exit_if(r, "listen failed %d %s", errno, strerror(errno));
124+
printf("fd %d listening at %d\n", listenfd, port);
125+
setNonBlock(listenfd);
126+
updateEvents(epollfd, listenfd, kReadEvent, false);
127+
for (;;) { //实际应用应当注册信号处理函数,退出时清理资源
128+
loop_once(epollfd, listenfd, 10000);
129+
}
130+
return 0;
131+
}

29-async/main.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#include <future>
2+
#include <iostream>
3+
4+
using namespace std;
5+
6+
int run(int number) { return number + 1; }
7+
8+
int main() {
9+
auto res = std::async(run, 5);
10+
auto response = std::async(std::launch::async, [](int n){ cout << "hello " << run(n) << endl; }, 9);
11+
cout << res.get() << endl;
12+
response.get();
13+
return 0;
14+
}

30-pointer/main

50.6 KB
Binary file not shown.

30-pointer/main.cpp

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#include <iostream>
2+
#include <memory>
3+
4+
using namespace std;
5+
6+
class Man {
7+
public:
8+
~Man() { cout << "goodbye" << endl; }
9+
};
10+
11+
int main() {
12+
shared_ptr<Man> man(new Man());
13+
shared_ptr<Man> mman = man;
14+
15+
// w 独占所有权
16+
unique_ptr<Man> w(new Man());
17+
// w 所有权交给 ww
18+
unique_ptr<Man> ww = move(w);
19+
return 0;
20+
}

6-class/exercise-17-类继承下的字节大小/main.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ class Computer {
44

55
private:
66
char id;
7-
7+
char pid;
88
// protected:
99
// int price;
1010

@@ -41,7 +41,9 @@ int main() {
4141
// 运行代码 make run c=6 e=17
4242

4343
// 运行代码
44-
// MacBook 1 bytes, id虽然是private的,但仍旧被MacBook继承,表明private只是强调访问权私有,而非继承权私有;
44+
// MacBook 2 bytes, id、pid虽然是private的,但仍旧被MacBook继承,表明private只是强调访问权私有,而非继承权私有;
45+
46+
// 注释掉第7行代码
4547

4648
// 打开第8、9行代码,运行代码
4749
// MacBook 8bytes

6-class/exercise-22-template类/main.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
template<typename T, typename S>
55
class Computer {
66

7-
public: using id_type=T;
7+
public: using id_type=S;
88

99
private:
1010
T id;
@@ -60,7 +60,7 @@ int main() {
6060

6161
// 运行代码 make run c=6 e=22
6262

63-
// 解释下第18行开始的模板定义
63+
// 解释下第20行开始的模板定义
6464
// 模板有3个泛型参数,其中 泛型 Purchase的类型又刚好是一个有2个参数的模板,
6565

6666
// 在第24行使用 泛型 Purchase, 因为它自身是一个模板,必须具体化才能使用,
@@ -78,9 +78,9 @@ int main() {
7878
// 请将第32~35行代码注释,打开29~30 39~41行的注释。
7979

8080

81-
// 第7行使用啦using定义啦一个类型 id_type;
81+
// 第7行使用using定义一个类型 id_type;
8282
// 在第45行 使用 typename T::id_type 使用了这个 id_type,
83-
// typename就是在强调使用 ::访问的是一个类型,不是类变量类函数;
83+
// typename就是在强调使用 ::访问的是一个类型,不是类变量类函数;
8484
// 值得注意的是,第7行给出了public限制符,否则第45行无法访问!
8585
//
8686
//

0 commit comments

Comments
 (0)