Skip to content

Commit

Permalink
“增加epoll相关的应用demo和注释说明
Browse files Browse the repository at this point in the history
  • Loading branch information
zc110747 committed Jul 3, 2020
1 parent affd7c6 commit 265cdb0
Show file tree
Hide file tree
Showing 14 changed files with 537 additions and 0 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,18 @@ int getopt (int ___argc, char *const *___argv, const char *__shortopts);
后续计划添加map, set, deque, tree等。
stl的具体接口说明在下级目录完善
# epoll/ 事件触发驱动实现
```cpp
//创建epoll事件句柄
int epoll_create (int __size);
//操作epoll事件的应用接口
int epoll_ctl (int __epfd, int __op, int __fd, struct epoll_event *__event
//等待epoll事件触发的接口
int epoll_wait (int __epfd, struct epoll_event *__events, int __maxevents, int __timeout);
//关闭epoll事件描述符,释放资源
int close (int __fd);
```

## fifo/ Linux命名先入先出管道通讯
用于Linux进程间通讯的命名先入先出管道
```cpp
Expand Down
5 changes: 5 additions & 0 deletions cplusplus/thread_pool/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"files.associations": {
"future": "cpp"
}
}
28 changes: 28 additions & 0 deletions cplusplus/thread_pool/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#编译工具和编译选项
CC = g++
CFLAGS := -O3 -std=c++11 -lpthread

#头文件路径
LOWERAPP_INC_ROOT = ../

OBJS = thread_pool.o
APP = thread_pool

LOWERAPP_INC= -I $(LOWERAPP_INC_ROOT)
INCLUDE_PATH = $(LOWERAPP_INC)

all : $(APP)

#生成.o文件
%.o : %.cpp
$(CC) $(CFLAGS) -c $< -o $@ $(INCLUDE_PATH)

#生成文件
$(APP): $(OBJS)
$(CC) -o $(APP) $(OBJS) $(LIB) $(CFLAGS)
rm -f $(OBJS)
tags :
ctags -R *

clean:
rm -f $(OBJS) $(APP)
Binary file added cplusplus/thread_pool/thread_pool
Binary file not shown.
105 changes: 105 additions & 0 deletions cplusplus/thread_pool/thread_pool.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/**********************************************************
* 说明: vector 向量容器
* 向量容器要求内部变量的类型一致,且与模板定义的一致
* 与数组的操作类似,较大的区别是vector对于空间的运用更加灵活
* vector常用方法
* size, push_back, pop_back, size, insert
* erase, clear 只清除变量,不释放空间
* capacity, resize,
* reserve
************************************************************/
#include "thread_pool.h"
#include <iostream>

void fun1(int slp)
{
printf(" hello, fun1 ! %d\n" ,std::this_thread::get_id());
if (slp>0) {
printf(" ======= fun1 sleep %d ========= %d\n",slp, std::this_thread::get_id());
std::this_thread::sleep_for(std::chrono::milliseconds(slp));
}
}

struct gfun {
int operator()(int n) {
printf("%d hello, gfun ! %d\n" ,n, std::this_thread::get_id() );
return 42;
}
};

class A {
public:
static int Afun(int n = 0) { //函数必须是 static 的才能直接使用线程池
std::cout << n << " hello, Afun ! " << std::this_thread::get_id() << std::endl;
return n;
}

static std::string Bfun(int n, std::string str, char c) {
std::cout << n << " hello, Bfun ! "<< str.c_str() <<" " << (int)c <<" " << std::this_thread::get_id() << std::endl;
return str;
}
};

int main()
{
try
{
std::threadpool executor{ 50 };
A a;
std::future<void> ff = executor.commit(fun1,0);
std::future<int> fg = executor.commit(gfun{},0);
//std::future<int> gg = executor.commit(a.Afun, 9999); //IDE提示错误,但可以编译运行
std::future<std::string> gh = executor.commit(A::Bfun, 9998,"mult args", 123);
std::future<std::string> fh = executor.commit([]()->std::string { std::cout << "hello, fh ! " << std::this_thread::get_id() << std::endl; return "hello,fh ret !"; });

std::cout << " ======= sleep ========= " << std::this_thread::get_id() << std::endl;
std::this_thread::sleep_for(std::chrono::microseconds(900));

for (int i = 0; i < 50; i++)
{
executor.commit(fun1,i*100 );
}
std::cout << " ======= commit all ========= " << std::this_thread::get_id()<< " idlsize="<<executor.idlCount() << std::endl;

std::cout << " ======= sleep ========= " << std::this_thread::get_id() << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(3));

ff.get(); //调用.get()获取返回值会等待线程执行完,获取返回值
std::cout << fg.get() << " " << fh.get().c_str()<< " " << std::this_thread::get_id() << std::endl;

std::cout << " ======= sleep ========= " << std::this_thread::get_id() << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(3));

std::cout << " ======= fun1,55 ========= " << std::this_thread::get_id() << std::endl;
executor.commit(fun1,55).get(); //调用.get()获取返回值会等待线程执行完

std::cout << "end... " << std::this_thread::get_id() << std::endl;


std::threadpool pool(4);
std::vector< std::future<int> > results;

for (int i = 0; i < 8; ++i) {
results.emplace_back(
pool.commit([i] {
std::cout << "hello " << i << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "world " << i << std::endl;
return i*i;
})
);
}
std::cout << " ======= commit all2 ========= " << std::this_thread::get_id() << std::endl;

for (auto && result : results)
{
std::cout << result.get() << ' ';
}
std::cout << std::endl;
return 0;
}
catch (std::exception& e)
{
std::cout << "some unhappy happened... " << std::this_thread::get_id() << e.what() << std::endl;
}
}
122 changes: 122 additions & 0 deletions cplusplus/thread_pool/thread_pool.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/**********************************************************
* 说明: vector 向量容器
* 向量容器要求内部变量的类型一致,且与模板定义的一致
* 与数组的操作类似,较大的区别是vector对于空间的运用更加灵活
************************************************************/
#ifndef THREAD_POOL_H
#define THREAD_POOL_H

#include <vector>
#include <queue>
#include <thread>
#include <atomic>
#include <condition_variable>
#include <future>
#include <functional>
#include <stdexcept>

namespace std
{
#define MAX_THREAD_NUM 256

//线程池,可以提交变参函数或拉姆达表达式的匿名函数执行,可以获取执行返回值
//不支持类成员函数, 支持类静态成员函数或全局函数,Opteron()函数等
class threadpool
{
using Task = std::function<void()>;
// 线程池
std::vector<std::thread> pool;
// 任务队列
std::queue<Task> tasks;
// 同步
std::mutex m_lock;
// 条件阻塞
std::condition_variable cv_task;
// 是否关闭提交
std::atomic<bool> stoped;
//空闲线程数量
std::atomic<int> idlThrNum;

public:
inline threadpool(unsigned short size = 4) :stoped{ false }
{
idlThrNum = size < 1 ? 1 : size;
for (size = 0; size < idlThrNum; ++size)
{ //初始化线程数量
pool.emplace_back(
[this]
{ // 工作线程函数
while(!this->stoped)
{
std::function<void()> task;
{ // 获取一个待执行的 task
std::unique_lock<std::mutex> lock{ this->m_lock };// unique_lock 相比 lock_guard 的好处是:可以随时 unlock() 和 lock()
this->cv_task.wait(lock,
[this] {
return this->stoped.load() || !this->tasks.empty();
}
); // wait 直到有 task
if (this->stoped && this->tasks.empty())
return;
task = std::move(this->tasks.front()); // 取一个 task
this->tasks.pop();
}
idlThrNum--;
task();
idlThrNum++;
}
}
);
}
}
inline ~threadpool()
{
stoped.store(true);
cv_task.notify_all(); // 唤醒所有线程执行
for (std::thread& thread : pool) {
//thread.detach(); // 让线程“自生自灭”
if(thread.joinable())
thread.join(); // 等待任务结束, 前提:线程一定会执行完
}
}

public:
// 提交一个任务
// 调用.get()获取返回值会等待任务执行完,获取返回值
// 有两种方法可以实现调用类成员,
// 一种是使用 bind: .commit(std::bind(&Dog::sayHello, &dog));
// 一种是用 mem_fn: .commit(std::mem_fn(&Dog::sayHello), &dog)
template<class F, class... Args>
auto commit(F&& f, Args&&... args) ->std::future<decltype(f(args...))>
{
if (stoped.load()) // stop == true ??
throw std::runtime_error("commit on ThreadPool is stopped.");

using RetType = decltype(f(args...)); // typename std::result_of<F(Args...)>::type, 函数 f 的返回值类型
auto task = std::make_shared<std::packaged_task<RetType()> >(
std::bind(std::forward<F>(f), std::forward<Args>(args)...)
); // wtf !
std::future<RetType> future = task->get_future();
{ // 添加任务到队列
std::lock_guard<std::mutex> lock{ m_lock };//对当前块的语句加锁 lock_guard 是 mutex 的 stack 封装类,构造的时候 lock(),析构的时候 unlock()
tasks.emplace(
[task]()
{ // push(Task{...})
(*task)();
}
);
}
cv_task.notify_one(); // 唤醒一个线程执行

return future;
}

//空闲线程数量
int idlCount() { return idlThrNum; }

};

}

#endif
1 change: 1 addition & 0 deletions cplusplus/vector/stl_vector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ int main(int argc, char* argv[])
return true;
return false;
});
sort(v0.begin(), v1.begin());
for_each(v1.begin(), v1.end(), [](int &value){
cout<<value<<" ";
});
Expand Down
36 changes: 36 additions & 0 deletions epoll/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#编译工具和编译选项
CC = g++
CFLAGS := -O3 -std=c++11 -lpthread

#头文件路径
LOWERAPP_INC_ROOT = ../

OBJS_1 = tcp_client.o
APP_1 = tcp_client
OBJS_2 = epoll_server.o
APP_2 = epoll_server
LIB =

LOWERAPP_INC= -I $(LOWERAPP_INC_ROOT)
INCLUDE_PATH = $(LOWERAPP_INC)

all : $(APP_1) $(APP_2)

#生成.o文件
%.o : %.cpp
$(CC) $(CFLAGS) -c $< -o $@ $(INCLUDE_PATH)

#生成文件
$(APP_1) : $(OBJS_1)
$(CC) -o $(APP_1) $(OBJS_1) $(LIB) $(CFLAGS)
rm -f $(OBJS_1)

$(APP_2) : $(OBJS_2)
$(CC) -o $(APP_2) $(OBJS_2) $(LIB) $(CFLAGS)
rm -f $(OBJS_2)

tags :
ctags -R *

clean:
rm -f $(OBJS_1) $(APP_1) $(OBJS_2) $(APP_2)
Binary file added epoll/epoll_server
Binary file not shown.
Loading

0 comments on commit 265cdb0

Please sign in to comment.