高并发服务器项目:内存管理实现逻辑

智能指针管理内存

项目中,使用智能指针shared_ptr,确保每个对象有一个共享所有权的计数器,当所有拥有指向该对象的shared_ptr全部销毁后,该对象的内存才会被自动释放,所以不会出现忘记释放该对象造成内存泄漏,以及过早释放对象,导致其他逻辑无法正常运行。同时使用weak_ptr,避免循环引用。以及类的内部使用了shared_from_this()获取自身的shared_ptr,确保对象在回调函数中,可以安全的调用该实例函数。最后通过function和智能指针结合,进一步保证了回调函数的使用安全。

**Connection类的管理:**使用shared_ptr管理连接对象的生命周期,在服务器逻辑中,当新连接到来后,生成一个shared_ptr<Connection>,然后存储在_conns容器中进行统一管理。(下面是连接类的内存管理逻辑,不重要的代码已经简略)

cpp 复制代码
using PtrConnection = std::shared_ptr<Connection>;

class Connection : public std::enable_shared_from_this<Connection> {
    ...
    // Connection 类的成员函数中使用 shared_from_this() 获取自身的 shared_ptr
    void HandleRead() {
        ...
        if (_in_buffer.ReadAbleSize() > 0) {
            return _message_callback(shared_from_this(), &_in_buffer);
        }
    }
    ...
};

class TcpServer {
    ...
    std::unordered_map<uint64_t, PtrConnection> _conns;
    ...
    void NewConnection(int fd) {
        _next_id++;
        PtrConnection conn(new Connection(_pool.NextLoop(), _next_id, fd));
        ...
        conn->Established();
        _conns.insert(std::make_pair(_next_id, conn));
    }
    ...
    void RemoveConnectionInLoop(const PtrConnection &conn) {
        int id = conn->Id();
        auto it = _conns.find(id);
        if (it != _conns.end()) {
            _conns.erase(it);
        }
    }
};

**TimerTask和TimerWheel类的管理:**使用shared_ptr管理定时器任务,同时借助weak_ptr避免循环引用,保证内存安全

cpp 复制代码
class TimerTask {
    private:
        uint64_t _id;
        bool _canceled;
        TaskFunc _task_cb;
        ReleaseFunc _release;
    public:
        TimerTask(uint64_t id, uint32_t delay, const TaskFunc &cb) 
            : _id(id), _timeout(delay), _task_cb(cb), _canceled(false) {}
        ...
        ~TimerTask() {
            if (!_canceled) _task_cb();
            _release();
        }
        ...
};

class TimerWheel {
    private:
        using WeakTask = std::weak_ptr<TimerTask>;
        using PtrTask = std::shared_ptr<TimerTask>;
        std::unordered_map<uint64_t, WeakTask> _timers;
        ...
        void TimerAddInLoop(uint64_t id, uint32_t delay, const TaskFunc &cb) {
            PtrTask pt(new TimerTask(id, delay, cb));
            pt->SetRelease(std::bind(&TimerWheel::RemoveTimer, this, id));
            _timers[id] = WeakTask(pt);
        }
        ...
        void TimerRefreshInLoop(uint64_t id) {
            auto it = _timers.find(id);
            if (it == _timers.end()) return;
            PtrTask pt = it->second.lock();
            ...
        }
        ...
};

RAII机制

项目中通过对象的生命周期,管理资源的获取和释放,从而保证内存安全,下面是项目中使用样例。

Socket类中析构函数中关闭套接字,确保套接字资源在对象销毁的时候自动释放

cpp 复制代码
class Socket {
private:
    int _sockfd;
public:
    Socket() : _sockfd(-1) {}
    Socket(int fd) : _sockfd(fd) {}
    ~Socket() { Close(); }
    //...
    void Close() {
        if (_sockfd != -1) {
            close(_sockfd);
            _sockfd = -1;
        }
    }
};

**Channel:**同样是在构造和析构函数管理事件的创建和注销,确保的创建的对象在生命周期内内存安全。

cpp 复制代码
class Channel {
private:
    int _fd;
    EventLoop* _loop;
    uint32_t _events;
    uint32_t _revents;
    using EventCallback = std::function<void()>;
    EventCallback _read_callback;
    EventCallback _write_callback;
    EventCallback _error_callback;
    EventCallback _close_callback;
    EventCallback _event_callback;

public:
    Channel(EventLoop* loop, int fd) : _fd(fd), _events(0), _revents(0), _loop(loop) {}
    ~Channel() { Remove(); }
    //...
    void Remove() { return _loop->RemoveEvent(this); }
    void Update() { return _loop->UpdateEvent(this); }
};

通过RAII方式,使用lock_gurad管理互斥锁,也就是在构造的时候给函数加锁,析构函数的时候解锁,保证锁的正确释放,避免死锁。

cpp 复制代码
#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx;

void process() {
    std::lock_guard<std::mutex> lock(mtx);
    // 共享资源操作
    // lock_guard超出作用域时会自动释放锁
}
相关推荐
秋名山小桃子几秒前
Kunlun 2280服务器(ARM)Raid卡磁盘盘符漂移问题解决
运维·服务器
与君共勉121381 分钟前
Nginx 负载均衡的实现
运维·服务器·nginx·负载均衡
努力学习的小廉8 分钟前
深入了解Linux —— make和makefile自动化构建工具
linux·服务器·自动化
MZWeiei11 分钟前
Zookeeper基本命令解析
大数据·linux·运维·服务器·zookeeper
Arenaschi30 分钟前
在Tomcat中部署应用时,如何通过域名访问而不加端口号
运维·服务器
小张认为的测试31 分钟前
Linux性能监控命令_nmon 安装与使用以及生成分析Excel图表
linux·服务器·测试工具·自动化·php·excel·压力测试
waicsdn_haha38 分钟前
Java/JDK下载、安装及环境配置超详细教程【Windows10、macOS和Linux图文详解】
java·运维·服务器·开发语言·windows·后端·jdk
良许Linux1 小时前
0.96寸OLED显示屏详解
linux·服务器·后端·互联网
蜜獾云1 小时前
docker 安装雷池WAF防火墙 守护Web服务器
linux·运维·服务器·网络·网络安全·docker·容器
小屁不止是运维1 小时前
麒麟操作系统服务架构保姆级教程(五)NGINX中间件详解
linux·运维·服务器·nginx·中间件·架构