This commit is contained in:
qing committed 2026-07-20 11:12:29 +08:00
commit 70d467d052
97 files changed
+10386

No files matched your search

+38
View File
@@ -0,0 +1,38 @@
/*
* 利用条件变量进行等待
*
* FIXME: deepseek 认为有一个设计缺陷:它只能用于单次等待-唤醒的场景。
* FIXME: 可能导致永久堵塞,应使用带超时的等待
* FIXME: 使用标准库的 future/promise
*/
#include <thread>
#include <atomic> /* 也许将字段flag创建为原子变量 */
#include <mutex>
#include <condition_variable>
namespace qing {
class Cv_wait { /* 用于等待的条件变量类,对同一个对象进行操作能够阻塞当前线程,或者唤醒被阻塞的线程 */
private:
std::mutex mtx{}; /* 用于控制条件变量的锁 */
std::condition_variable cv{};
bool flag = false; /* 用于解锁条件变量的标志 */
public:
inline void Wait() /* 线程进入等待 */
{
auto lock = std::unique_lock<std::mutex>(mtx);
flag = false;
cv.wait(lock, [this] { return flag; });
}
inline void WakeCv() /* 唤醒线程 */
{
{
std::lock_guard<std::mutex> lcok(mtx);
flag = true;
}
cv.notify_all();
}
};
}
+75
View File
@@ -0,0 +1,75 @@
/*
* 有限状态机(Finite State Machine,FSM)
*/
#pragma once
#include <mutex> /*上锁 使得有限状态机线程安全*/
#include <condition_variable> /*条件变量,使得子类能够等待状态的设置*/
namespace qing {
/*
* FiniteStateMachine有限状态机
*
* 每个数字代表一个状态 使用static_cast<>()之类的函数去赋值
* FIXME: 之前用过一种使用回调函数处理的方式
*/
class Fsm {
public:
/* 状态枚举类 */
enum class Stat: int {
SHUT = -1, /* 关闭 */
STOP = 0, /* 静止 */
START = 1, /* 启动 */
RUNNING = 2 /* 运行 */
/* ... */
};/*Stat*/
/* 以STOP为初始状态 */
Fsm() { set(Stat::STOP); }
enum Stat check() { /* 检查当前的状态 */
std::lock_guard<std::mutex> lk(mtx);
return stat;
} /*check*/
/*
* 在不上锁的情况下设置一个状态
* 这里不能使用锁,因为我们还要在临界区里唤醒条件变量
*/
void set_without_lock(Stat stat) { this->stat = stat; }
/* 带锁的状态设置 但是该方法不唤醒条件变量 */
void set_without_notify(Stat stat) {
std::lock_guard<std::mutex> lk(mtx);
this->stat = stat;
}
/* 带锁和条件唤醒的状态设置 */
void set(Stat stat) {
{
std::lock_guard<std::mutex> lk(mtx);
set_without_lock(stat);
ready = true;
}
cv.notify_all();
}
//protected:
void suspend() { /* 阻塞线程,等待事件唤醒 */
std::unique_lock<std::mutex> lk(mtx);
ready = false;
cv.wait(lk, [this] { return ready; });
}/*suspend */
private:
std::mutex mtx; /* 线程安全 */
bool ready = false; /* 用于条件变量的阻塞唤醒 */
std::condition_variable cv; /* 条件变量 阻塞/唤醒线程 */
enum Stat stat; /* 状态机的状态变量 */
};//Fsm
}//qing
+9
View File
@@ -0,0 +1,9 @@
#pragma once
namespace qing{
class ITask { /* 单个任务通用接口 */
public:
virtual void start() = 0; /* 任务开始 */
virtual void stop() = 0; /* 任务结束 */
virtual bool isRunning() = 0; /* 是否在跑 */
};
}
+149
View File
@@ -0,0 +1,149 @@
/* 线程
*
*
* 包含一个简易的多线程控制机制,需要共享的变量和函数声明为成员。
*
* 线程主函数包括了流程控制,要使用需要实现其中的各个事件方法
*
* 20250621: 从派生改为持有
*
* NOTE: 在对象构造完之后应该激活
*/
#pragma once
#include <thread>
#include <memory> /* 内存管理 */
#include <chrono> /* 用于线程休息 */
#include <iostream>
#include <stdexcept>
#include <functional>
#include "us/Fsm.hpp" /* 有限状态机 */
namespace qing {
class Thread;
//using f_t = void(*)(Thread&);
using f_t = std::function<void(Thread&)>;
class Thread {
public:
/* 作为可变的函数,持有回调可能比继承更好
*
* FIXME: 可以改为链式传递参数 */
//Thread(f_t stop_callback, f_t wake_callback, f_t loop_callback, f_t clear_callback);
/* 使用默认初始化方法,然后用几个函数分别进行回调初始化 */
Thread() = default;
/*
* 删除复制构造函数。
*
* 因为持有线程类,不要轻举妄动。
*/
Thread(const Thread&) = delete;
/*
* 虚析构函数
*
* FIXME: 具体有什么用,忘了
*/
virtual ~Thread() {}
/* 设置停止回调函数 */
void set_stop(f_t callback);
/* 设置唤醒回调函数 */
void set_wake(f_t callback);
/* 设置循环体回调函数 */
void set_loop(f_t callback);
/* 设置清理回调函数 */
void set_clear(f_t callback);
/*-----------------------------------*/
/*-----------------------------------*/
/*
* 检查状态的方法
*
* NOTE: 做成虚函数,万一子类有特别要求呢
*
* FIXME: 将检查器和变异器做成一个简单的回调函数
*/
Fsm::Stat check();
/*-----------------------------------*/
/*-----------------------------------*/
/* 让线程能够阻塞直到新的状态被赋予的方法 */
void suspend();
/*-----------------------------------*/
/*-----------------------------------*/
/* 状态改变的方法 - 变异器 */
/* 进入唤醒状态
*
* 唤醒函数不可以进行该类中的锁操作,否则会造成死锁
*/
void wake();
/* 进入静止状态
*
* 上锁、唤醒阻塞的线程
*/
void stop();
/* 进入关闭状态 */
void shut();
/* 进入运行状态 */
void run();
/*-----------------------------------*/
/*-----------------------------------*/
/*
* 激活线程,申请线程对象
*
* 该函数不能放在构造函数内,因为需要确保对象已经被构造了
*/
void Activate();
/*
* 尝试唤醒线程并等待它开始 据说该函数有问题可能导致异常
*/
void WaitStart();
/* 等待线程关闭 */
void WaitClose();
/*-----------------------------------*/
/* 线程主函数 */
void main();
private:
qing::Fsm fsm{}; /* 持有状态机类型 */
std::unique_ptr<std::thread> th; /* 持有线程类型 */
std::mutex mtx_th; /* 持有锁类型 */
/*
* 这里持有一个条件变量,用于阻塞以等待线程的关闭
*
* 注意状态机中的cv是另一个变量
*/
std::condition_variable cv;
/* 辅助条件变量的逻辑型 */
bool ready;
/* 事件回调 */
std::unique_ptr<f_t> StopEvent;
std::unique_ptr<f_t> WakeEvent;
std::unique_ptr<f_t> LoopEvent;
std::unique_ptr<f_t> ClearEvent;
};
}