这是我改写的share_ptr的加锁版本,
问题一:不知道怎么验证是否线程安全
问题二:weak_ptr需不需要也加锁呢?如何验证线程安全呢?
share_ptr.cpp
#pragma once
#include <iostream>
#include <string>
#include <mutex>
using namespace std;
namespace heheda {
namespace utility {
template<class T>
class SharePtr {
template<class Y> friend class WeakPtr;
public:
SharePtr() : m_data(nullptr), m_count(nullptr),m_mutex(nullptr) {}
SharePtr(T* data) {
if(data != nullptr) {
m_data = data;
m_count = new int(1);
m_mutex = new mutex;
}
}
// 拷贝构造函数
SharePtr(const SharePtr<T>& other)
: m_data(other.m_data)
, m_count(other.m_count)
, m_mutex(other.m_mutex)
{
if(m_data != nullptr) addRefCount();// 增加引用计数
}
// 移动构造函数
SharePtr(SharePtr<T>&& other) noexcept
: m_data(other.m_data)
, m_count(other.m_count)
, m_mutex(other.m_mutex) { // move
other.m_data = nullptr;
other.m_count = nullptr;
other.m_mutex = nullptr;
}
// 析构函数
~SharePtr() {
if(m_data != nullptr) {
release();
}
}
void release() {
bool deleteflag = false;
m_mutex->lock();
if(--(*m_count) == 0) {
cout << "delete:" << m_data << endl;
// 释放资源
delete m_data;m_data = nullptr;
delete m_count;m_count = nullptr;
deleteflag = true;
}
m_mutex->unlock();
//表示m_ptr 和 m_pRefCount资源已经被释放,此时需要释放锁,否则产生资源泄漏
if(deleteflag) delete m_mutex;
}
T*get() const { return m_data; }
T*getCount() const { return m_count; }
void reset(T* data = nullptr) {
if(m_data == data) return;
if(m_data == nullptr) {
if(data!=nullptr) {
m_data = data;
m_mutex->lock();
m_count = new int(1);
m_mutex->unlock();
}
return;
}
m_mutex->lock();
(*m_count)--;
if(*m_count <= 0) {
delete m_data;
m_data = nullptr;
delete m_count;
m_count = nullptr;
}
m_data = data;
if(data != nullptr) {
m_count = new int(1);
}
m_mutex->unlock();
}
int use_count() const {
if(m_data == nullptr) return 0;
return *m_count;
}
bool unique() const {
if(m_data == nullptr) return false;
return *m_count == 1;
}
void swap(SharePtr<T>& other) {
auto data = other.m_data;
auto count = other.m_count;
auto m_mutex = other.m_mutex;
other.m_data = m_data;
other.m_count = m_count;
other.m_mutex = m_mutex;
m_data = data;
m_count = count;
other.m_mutex = m_mutex;
}
T* operator->() const { return m_data; }
T& operator*() const { return *m_data; }
explicit operator bool() const noexcept { return m_data != nullptr; }
SharePtr& operator=(const SharePtr<T>& other) {
if(this == &other) return *this;
m_data = other.m_data;
m_count = other.m_count;
m_mutex = other.m_mutex;
addRefCount();// 增加引用计数
return *this;
}
// 移动赋值
SharePtr& operator=(SharePtr<T>&& other) noexcept {
if(this == &other) return *this;
m_data = other.m_data;
m_count = other.m_count;
m_mutex = other.m_mutex;
other.m_data = nullptr;
other.m_count = nullptr;
other.m_mutex = nullptr;
return *this;
}
// 增加引用计数
void addRefCount() {
m_mutex->lock();
++(*m_count);
m_mutex->unlock();
}
private:
T* m_data; // 指向管理资源的指针
int* m_count; // 指向引用计数的指针
mutex *m_mutex; // 互斥锁,处理线程安全
};
}
}
weak_ptr.cpp
#pragma once
#include "shared_ptr.h"
// #include "thread_shared_ptr.h"
namespace heheda{
// weak_ptr和shared_ptr最大的区别:
// shared_ptr是一个共享智能指针,每多一个智能指针,它的引用计数就加1
// 多个weak_ptr可以指向同一个对象,但是它并不增加引用计数
// shared_ptr会管理它的生命周期,但每多一个引用,它的引用计数就会加1
// 当某一个shared_ptr销毁的时候,引用计数就会减1,如果说减到0的话,
// 那这个对象就会被释放掉.
// weak_ptr它不会释放对象,它也不会增加这个引用计数
namespace utility {
template<class T>
class WeakPtr{
public:
WeakPtr():m_data(nullptr),m_count(nullptr){}
// WeakPtr(const SharePtr<T>& sp):m_data(sp.get()),m_count(sp.getCount()){}
WeakPtr(const SharePtr<T>& sp):m_data(sp.m_data),m_count(sp.m_count){}
// 拷贝构造函数
WeakPtr(const WeakPtr<T>& other):m_data(other.m_data),m_count(other.m_count){}
// 移动构造函数
WeakPtr(WeakPtr<T> && other):m_data(other.m_data),m_count(other.m_count){
other.m_data = nullptr;
other.m_count = nullptr;
}
~WeakPtr(){
m_data = nullptr;
m_count = nullptr;
}
void reset(){
m_data = nullptr;
m_count = nullptr;
}
bool expired() const{
return !m_count || (*m_count)<=0;
}
SharePtr<T> lock() const{
if(expired()) {
return SharePtr<T>();
}
SharePtr<T> sp;// 临时对象,被析构就会--
sp.m_data = m_data;
sp.m_count = m_count;
if(m_count != nullptr) {
(*m_count)++;
}
return sp;
}
void swap(WeakPtr<T>& other) {
auto data = other.m_data;
auto count = other.m_count;
other.m_data = m_data;
other.m_count = m_count;
m_data = data;
m_count = count;
}
int use_count() const{
if(m_data == nullptr) return 0;
return *m_count;
}
WeakPtr& operator=(const SharePtr<T>& sp) {
m_data = sp.m_data;
m_count = sp.m_count;
return *this;
}
WeakPtr& operator=(const WeakPtr<T>& other) {
if(this == &other) return *this;
m_data = other.m_data;
m_count = other.m_count;
return *this;
}
// 移动赋值
WeakPtr & operator=(WeakPtr<T> && other) {
if(this == &other) return *this;
m_data = other.m_data;
m_count = other.m_count;
other.m_data = nullptr;
other.m_count = nullptr;
return *this;
}
private:
T* m_data;
int* m_count;
};
}
}