254 lines
6.8 KiB
C++
254 lines
6.8 KiB
C++
#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
|