Files
RCS-3000/include/dispatch/resource_manager.h
2026-01-12 10:02:16 +08:00

254 lines
6.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef RESOURCE_MANAGER_H
#define RESOURCE_MANAGER_H
#include "graph_map.h"
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <thread>
#include <atomic>
/**
* @brief 资源请求状态
*/
enum class ResourceRequestStatus {
GRANTED, // 已授予
PENDING, // 等待中
TIMEOUT, // 超时
CANCELLED // 已取消
};
/**
* @brief 资源请求
*/
struct ResourceRequest {
int id;
AGV* agv;
Path* path;
uint64_t timestamp;
ResourceRequestStatus status;
std::condition_variable* condition; // 用于通知
ResourceRequest(int id_, AGV* agv_, Path* path_)
: id(id_), agv(agv_), path(path_), timestamp(getCurrentTimestamp()),
status(ResourceRequestStatus::PENDING), condition(nullptr) {}
bool operator<(const ResourceRequest& other) const {
// 可以根据优先级或其他规则排序
return timestamp < other.timestamp; // FIFO
}
private:
static uint64_t getCurrentTimestamp() {
return std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now().time_since_epoch()).count();
}
};
/**
* @brief 资源管理器
* 负责管理路径和节点的占用
*/
class ResourceManager {
private:
// 资源占用状态
std::unordered_map<Path*, AGV*> path_occupancy_;
std::unordered_map<Point*, AGV*> point_occupancy_;
// 等待队列(路径和节点)
std::unordered_map<Path*, std::queue<ResourceRequest*>> path_wait_queue_;
std::unordered_map<Point*, std::queue<ResourceRequest*>> point_wait_queue_;
// 互斥锁
mutable std::mutex resource_mutex_;
// 请求ID生成器
std::atomic<int> next_request_id_{1};
// 统计信息
std::atomic<uint64_t> total_requests_{0};
std::atomic<uint64_t> granted_requests_{0};
std::atomic<uint64_t> wait_count_{0};
public:
ResourceManager() = default;
~ResourceManager() = default;
/**
* @brief 请求占用路径
* @param agv 请求的AGV
* @param path 要占用的路径
* @param timeout_ms 超时时间毫秒0表示无限等待
* @return 请求状态
*/
ResourceRequestStatus requestPath(AGV* agv, Path* path, int timeout_ms = 0);
/**
* @brief 释放路径资源
* @param agv 释放的AGV
* @param path 释放的路径
*/
void releasePath(AGV* agv, Path* path);
/**
* @brief 检查路径是否可用
* @param path 要检查的路径
* @param requester 请求的AGV如果是自己占用也算可用
* @return 是否可用
*/
bool isPathAvailable(Path* path, AGV* requester = nullptr);
/**
* @brief 请求占用节点
* @param agv 请求的AGV
* @param point 要占用的节点
* @param timeout_ms 超时时间
* @return 请求状态
*/
ResourceRequestStatus requestPoint(AGV* agv, Point* point, int timeout_ms = 0);
/**
* @brief 释放节点资源
* @param agv 释放的AGV
* @param point 释放的节点
*/
void releasePoint(AGV* agv, Point* point);
/**
* @brief 检查节点是否可用
* @param point 要检查的节点
* @param requester 请求的AGV
* @return 是否可用
*/
bool isPointAvailable(Point* point, AGV* requester = nullptr);
/**
* @brief 获取占用路径的AGV
* @param path 路径
* @return 占用的AGV如果没有则返回nullptr
*/
AGV* getPathOccupant(Path* path) const;
/**
* @brief 获取占用节点的AGV
* @param point 节点
* @return 占用的AGV如果没有则返回nullptr
*/
AGV* getPointOccupant(Point* point) const;
/**
* @brief 强制释放AGV占用的所有资源用于错误处理
* @param agv 要释放资源的AGV
*/
void releaseAllResources(AGV* agv);
/**
* @brief 获取统计信息
*/
void getStatistics(uint64_t& total_requests, uint64_t& granted_requests,
uint64_t& wait_count) const;
/**
* @brief 打印资源占用状态
*/
void printResourceStatus() const;
/**
* @brief 检测死锁
* @return 发现的死锁数量
*/
int detectDeadlocks();
private:
/**
* @brief 处理等待队列
* 当资源释放时,检查等待队列并分配给下一个请求
*/
void processWaitQueue(Path* path);
void processWaitQueue(Point* point);
/**
* @brief 取消请求
*/
void cancelRequest(ResourceRequest* request);
/**
* @brief 检查循环等待(死锁检测)
*/
bool hasCircularWait(AGV* agv, std::unordered_set<AGV*>& visited,
std::unordered_set<Path*>& path_set);
/**
* @brief 记录统计信息
*/
void recordRequest(bool granted);
};
/**
* @brief 资源自动管理器
* 使用RAII模式自动管理资源
*/
class ScopedPathResource {
private:
ResourceManager* manager_;
AGV* agv_;
Path* path_;
bool acquired_;
public:
ScopedPathResource(ResourceManager* manager, AGV* agv, Path* path)
: manager_(manager), agv_(agv), path_(path), acquired_(false) {
if (manager_ && agv_ && path_) {
auto status = manager_->requestPath(agv_, path_);
acquired_ = (status == ResourceRequestStatus::GRANTED);
}
}
~ScopedPathResource() {
if (acquired_ && manager_ && agv_ && path_) {
manager_->releasePath(agv_, path_);
}
}
bool isAcquired() const { return acquired_; }
// 禁止拷贝
ScopedPathResource(const ScopedPathResource&) = delete;
ScopedPathResource& operator=(const ScopedPathResource&) = delete;
};
/**
* @brief 节点资源自动管理器
*/
class ScopedPointResource {
private:
ResourceManager* manager_;
AGV* agv_;
Point* point_;
bool acquired_;
public:
ScopedPointResource(ResourceManager* manager, AGV* agv, Point* point)
: manager_(manager), agv_(agv), point_(point), acquired_(false) {
if (manager_ && agv_ && point_) {
auto status = manager_->requestPoint(agv_, point_);
acquired_ = (status == ResourceRequestStatus::GRANTED);
}
}
~ScopedPointResource() {
if (acquired_ && manager_ && agv_ && point_) {
manager_->releasePoint(agv_, point_);
}
}
bool isAcquired() const { return acquired_; }
// 禁止拷贝
ScopedPointResource(const ScopedPointResource&) = delete;
ScopedPointResource& operator=(const ScopedPointResource&) = delete;
};
#endif // RESOURCE_MANAGER_H