赞
踩
项目中,使用智能指针shared_ptr,确保每个对象有一个共享所有权的计数器,当所有拥有指向该对象的shared_ptr全部销毁后,该对象的内存才会被自动释放,所以不会出现忘记释放该对象造成内存泄漏,以及过早释放对象,导致其他逻辑无法正常运行。同时使用weak_ptr,避免循环引用。以及类的内部使用了shared_from_this()获取自身的shared_ptr,确保对象在回调函数中,可以安全的调用该实例函数。最后通过function和智能指针结合,进一步保证了回调函数的使用安全。
Connection类的管理:使用shared_ptr管理连接对象的生命周期,在服务器逻辑中,当新连接到来后,生成一个shared_ptr<Connection>,然后存储在_conns容器中进行统一管理。(下面是连接类的内存管理逻辑,不重要的代码已经简略)
- 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避免循环引用,保证内存安全
- 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();
- ...
- }
- ...
- };
项目中通过对象的生命周期,管理资源的获取和释放,从而保证内存安全,下面是项目中使用样例。
Socket类中析构函数中关闭套接字,确保套接字资源在对象销毁的时候自动释放
- 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:同样是在构造和析构函数管理事件的创建和注销,确保的创建的对象在生命周期内内存安全。
- 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管理互斥锁,也就是在构造的时候给函数加锁,析构函数的时候解锁,保证锁的正确释放,避免死锁。
- #include <iostream>
- #include <thread>
- #include <mutex>
-
- std::mutex mtx;
-
- void process() {
- std::lock_guard<std::mutex> lock(mtx);
- // 共享资源操作
- // lock_guard超出作用域时会自动释放锁
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。