当前位置:   article > 正文

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

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

智能指针管理内存

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

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

  1. using PtrConnection = std::shared_ptr<Connection>;
  2. class Connection : public std::enable_shared_from_this<Connection> {
  3. ...
  4. // Connection 类的成员函数中使用 shared_from_this() 获取自身的 shared_ptr
  5. void HandleRead() {
  6. ...
  7. if (_in_buffer.ReadAbleSize() > 0) {
  8. return _message_callback(shared_from_this(), &_in_buffer);
  9. }
  10. }
  11. ...
  12. };
  13. class TcpServer {
  14. ...
  15. std::unordered_map<uint64_t, PtrConnection> _conns;
  16. ...
  17. void NewConnection(int fd) {
  18. _next_id++;
  19. PtrConnection conn(new Connection(_pool.NextLoop(), _next_id, fd));
  20. ...
  21. conn->Established();
  22. _conns.insert(std::make_pair(_next_id, conn));
  23. }
  24. ...
  25. void RemoveConnectionInLoop(const PtrConnection &conn) {
  26. int id = conn->Id();
  27. auto it = _conns.find(id);
  28. if (it != _conns.end()) {
  29. _conns.erase(it);
  30. }
  31. }
  32. };

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

  1. class TimerTask {
  2. private:
  3. uint64_t _id;
  4. bool _canceled;
  5. TaskFunc _task_cb;
  6. ReleaseFunc _release;
  7. public:
  8. TimerTask(uint64_t id, uint32_t delay, const TaskFunc &cb)
  9. : _id(id), _timeout(delay), _task_cb(cb), _canceled(false) {}
  10. ...
  11. ~TimerTask() {
  12. if (!_canceled) _task_cb();
  13. _release();
  14. }
  15. ...
  16. };
  17. class TimerWheel {
  18. private:
  19. using WeakTask = std::weak_ptr<TimerTask>;
  20. using PtrTask = std::shared_ptr<TimerTask>;
  21. std::unordered_map<uint64_t, WeakTask> _timers;
  22. ...
  23. void TimerAddInLoop(uint64_t id, uint32_t delay, const TaskFunc &cb) {
  24. PtrTask pt(new TimerTask(id, delay, cb));
  25. pt->SetRelease(std::bind(&TimerWheel::RemoveTimer, this, id));
  26. _timers[id] = WeakTask(pt);
  27. }
  28. ...
  29. void TimerRefreshInLoop(uint64_t id) {
  30. auto it = _timers.find(id);
  31. if (it == _timers.end()) return;
  32. PtrTask pt = it->second.lock();
  33. ...
  34. }
  35. ...
  36. };

RAII机制

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

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

  1. class Socket {
  2. private:
  3. int _sockfd;
  4. public:
  5. Socket() : _sockfd(-1) {}
  6. Socket(int fd) : _sockfd(fd) {}
  7. ~Socket() { Close(); }
  8. //...
  9. void Close() {
  10. if (_sockfd != -1) {
  11. close(_sockfd);
  12. _sockfd = -1;
  13. }
  14. }
  15. };

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

  1. class Channel {
  2. private:
  3. int _fd;
  4. EventLoop* _loop;
  5. uint32_t _events;
  6. uint32_t _revents;
  7. using EventCallback = std::function<void()>;
  8. EventCallback _read_callback;
  9. EventCallback _write_callback;
  10. EventCallback _error_callback;
  11. EventCallback _close_callback;
  12. EventCallback _event_callback;
  13. public:
  14. Channel(EventLoop* loop, int fd) : _fd(fd), _events(0), _revents(0), _loop(loop) {}
  15. ~Channel() { Remove(); }
  16. //...
  17. void Remove() { return _loop->RemoveEvent(this); }
  18. void Update() { return _loop->UpdateEvent(this); }
  19. };

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

 

  1. #include <iostream>
  2. #include <thread>
  3. #include <mutex>
  4. std::mutex mtx;
  5. void process() {
  6. std::lock_guard<std::mutex> lock(mtx);
  7. // 共享资源操作
  8. // lock_guard超出作用域时会自动释放锁
  9. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/在线问答5/article/detail/939569
推荐阅读
相关标签
  

闽ICP备14008679号