编写智能指针实现对象托管(二)

四、侵入式的智能指针

  虽然侵入式智能指针会将部分数据记录到对象本身,但它可以实现一些非侵入式智能指针无法实现的功能,比如从this指针构造一个合法的智能指针对象。参照标准库的shared_ptr和weak_ptr,我设计出这样一个智能指针机制:
  同标准库的智能指针机制相比,该机制在对象基类中添加了计数指针和清除标记,将对象指针放到了计数对象中。该机制同样可以实现shared_ptr、weak_ptr的功能,而且,由于对象本身记录有计数指针,也可以从对象本身获取一个智能指针对象。其要求就是对象必须从一个基类派生,而且多继承时,还需要虚派生以保证基类部分的唯一性。
  如果目标对象没有清除标记,那么这个智能指针的使用方法就跟标准库的非常类似。但是,我们要设计的对象必须是可以托管的,当对象交给后台托管后,强引用计数将变为0,而这时候对象却不能被释放。这就需要对“被托管”和“未被托管”的对象进行区分。一种可行的方案是使用一个特定的函数模板来创建托管对象,从这个函数模板创建的对象都打上托管标记,并且加入后台托管集合中,那么当强引用计数变为0时就能区别对待了。考虑到同步问题,其中的托管标记需要放在计数对象上。

五、具体实现

  具体实现中包含:计数类、基类、强引用智能指针模板、弱引用智能指针模板、对象管理类。声明如下:
struct ReferenceCount;//计数类
struct ObjectBase;//基类
template<class T>struct sharedptr;//强引用智能指针模板
template<class T>struct weakptr;//弱引用智能指针模板
struct ObjectManager;//对象管理类

1.计数类

  计数类中至少要包含对象指针、弱引用计数和强引用计数三者,而且为了区分托管与非托管对象计数类中还需要一个成员,咱这里就用一个deleter来区分。具体代码如下:
#include<atomic>
struct ReferenceCount{//计数类
    ObjectBase* ptr_obj;//对象指针
    std::atomic<unsigned> cnt_strong;//强引用计数
    std::atomic<unsigned> cnt_weak;//弱引用计数
    void(*deleter)(ObjectBase*&);//强引用计数减至0时对象释放方法
};

2.基类

  基类中包含清除标记和一些基本方法。为了让其它类型从该类型派生,虚析构方法是必须的。然后就是获取托管智能指针成员的方法,也需要允许派生类重写。具体代码如下:
struct ObjectBase {
	unsigned use_count();//获取强引用计数
	ObjectBase();//默认构造函数
private:
	ReferenceCount* ptr_cnt;//计数对象指针
	unsigned t_cnt;//需要扫描成员数量
	unsigned char t_ver;//扫描版本号
	bool t_added;//是否已加入托管集合
	void setcnt(ReferenceCount*p);//设置计数指针
protected:
	virtual ~ObjectBase() ;//析构方法:不允许直接delete
	virtual unsigned GetScanObjects(weakptr
    
    
     
     **pout);//用以获取需要扫描的智能指针
	template
     
     
      
      friend struct weakptr;//友元
	template
      
      
       
       friend struct sharedptr;//友元
	friend struct ObjectManager;//友元
};
      
      
     
     
    
    

3.weakptr模板

  weakptr代码结构如下:
template
    
    
     
     struct weakptr{
	weakptr();//默认构造空引用
	weakptr(weakptr const&p);//复制构造增加弱引用计数
	weakptr& operator=(const weakptr&w);//赋值语句
	~weakptr();//析构
	weakptr& operator=(const sharedptr
     
     
      
      &w);//从sharedptr构造
      
      
       
       
	friend bool operator==(weakptr const&w1, weakptr const&w2);
	friend bool operator!=(weakptr const&w1, weakptr const&w2);//比较
	sharedptr
       
       
        
         lock();//获取一个sharedptr
private:
	ReferenceCount* ptr_cnt;//指向计数对象
};
       
       
      
      
     
     
    
    
  weakptr<T>主要提供赋值和比较操作,对于T并没有特殊要求,不论T是不是从ObjectBase派生。当weakptr<T>类型的对象指向一个托管的对象时,为了防止后台扫描线程扫描对象成员过程中,成员发生变化,必须在扫描过程中锁住赋值操作。因此weakptr<T>在T为可以托管的类型时,每次赋值都要经过锁。

4.sharedptr模板

  sharedptr代码结构如下:
template<class T>struct sharedptr {
	sharedptr();//默认构造空引用
	sharedptr(sharedptr const&p);//复制构造增加弱引用计数和强引用计数
	explicit sharedptr(T*p);//直接从对象指针构造
	void addref();//增加引用计数
	void release();//减少引用计数,并在强引用计数减为0时使用对象释放方法
	sharedptr& operator=(const sharedptr&w);//赋值语句
	friend bool operator==(sharedptr const&w1, sharedptr const&w2);//比较
	friend bool operator!=(sharedptr const&w1, sharedptr const&w2);
	friend bool operator==(sharedptr const&w1, std::nullptr_t);
	friend bool operator!=(sharedptr const&w1, std::nullptr_t);
	~sharedptr() { release(); }//析构
	T& operator*()const;
	T* get()const;
	T*operator->()const;
	unsigned use_count()const;
private:
	static T* castpointer(ObjectBase*p, ObjectBase*);//当第二个参数为ObjectBase派生类对象指针时使用
	static T* castpointer(ObjectBase*p, ...);
	void construct(T*,ObjectBase*p);//当第二个参数为ObjectBase派生类对象指针时使用
	void construct(T*p,...);
	static void deleter(ObjectBase*&p);
	ReferenceCount* ptr_cnt;//指向计数对象
	friend struct weakptr<T>;
	friend struct ObjectManager;
};
  sharedptr<T>中,T为int 跟T为ObjectBase派生类时会在构造计数对象、析构对象、指针转换时有所不同,因此使用两个函数重载来区别对待.sharedptr的赋值不需要经过锁,因为只要是存在sharedptr指向的可以托管的对象,都会在后台根集合中有记录。处理引用计数也是一个难题,因为对象完全托管时,其强引用计数将变为0,从weakptr使用lock构造sharedptr时,不能单纯地判断ReferenceCount中的cnt_strong是否为0来决定结果是不是空的sharedptr,而是要通过判断ptr_cnt是否是nullptr来决定。这里咱通过通过认定cnt_strong为1时处于对象释放处理阶段来进行多线程同步:当cnt_strong 减至1时,其它所有尝试增加强引用计数的线程都进入等待,等该线程将cnt_strong设置为0时,其它尝试增加强引用计数的线程再根据ptr_obj进行操作。这使得cnt_strong 总是比实际值多1.

5.ObjectManager类

  ObjectManager类中主要处理托管对象的扫描和释放,结构和成员如下:
struct ObjectManager {
	//根节点
	static ObjectManager& root(){ static ObjectManager r; return r; }
	//新增托管对象
	template<class T, class ...Args>static sharedptr<T>newobj(Args...a);
	//强引用计数为0时的删除方法:不做任何处理
	static void DeleteMethod(ObjectBase*&) {}
	//构造函数
	ObjectManager();
	//析构函数,释放所有管理对象
	~ObjectManager();
	//进入操作
	void EnterOperating();
	//退出操作
	void ExitOperating();
	//添加对象到对象表
	void AddObject(ObjectBase*p); 
	//添加对象到栈列表并返回栈引用
	sharedptr<ObjectBase> AddRootObject(ObjectBase*p);
	//移除所有对象
	void ReleaseAll();
	//立即发起一次扫描
	void ScanNow();
	//扫描线程
	void ScanThread();
	//扫描函数
	void Scan(std::vector<ObjectBase*>& robjs, unsigned d = 0);
	//递归更新版本号
	void UpdateVersion(unsigned char newversion, ObjectBase* p);
	//获取对象数
	size_t GetObjectCount()const { return objs.size(); }
	//获取托管根数量
	size_t GetRootCount()const { return rootobjs.size(); }
	//对象表,每个对象在其中至多只有一个记录
	std::vector<ObjectBase*>objs;
	std::mutex mtobjs;
	//根节点表,每个对象在其中最多只有一个记录
	std::vector<ObjectBase*>rootobjs;
	std::mutex mtstackobjs;
	//扫描次数统计
	size_t scancnt;
	//未扫描成员数
	size_t unscanMembers;
	//未扫描对象数量
	size_t unscanCount;
	//当前版本号
	unsigned char version;
	//状态变量,用以跟后台扫描线程同步
	size_t state;
	//扫描释放毫秒秒间隔(大概)
	size_t scanTime;
	//间隔计数
	size_t scanidx;
	//已进入的添加或删除节点的操作数量
	signed enterOperatingCount;
	//进入锁
	std::mutex mtEnter;
	//已退出的添加或删除节点的操作数量
	std::atomic<signed> exitOperatingCount;
};
  注意到其中的newobj函数即为创建托管对象的专用函数,该函数需要对新建的对象做标记:计算对象托管成员数量、记录对象到根节点集合、记录对象到对象集合。扫描原理上一部分讲过,认为所有通过newobj函数生成的对象都在根节点记录,然后先扫描根节点集合,再扫描对象集合来找出可释放对象。为防止循环引用导致无限扫描,扫描过程需要先判断该对象是否被扫描过(版本号是否是最新)。扫描过程虽然是递归的,但是并不能使用递归函数,因为对象数量一多就很容易爆栈。最后就是要处理好从托管智能指针weakptr<T>变量lock得到sharedptr的问题,这个sharedptr要根据对象是否托管来决定是否加入根节点集合。

六、具体代码和测试结果

  先看VS2015的测试结果,可以看到上一部分会导致内存耗尽的代码,在使用对象托管之后,进程内存占用呈锯齿状,已经可以由后台自动释放了。
   测试程序代码:
#include<iostream>
#include<atomic>
#include<thread>
#include<mutex>
#include<vector>
#include<Windows.h>
struct ReferenceCount;//计数类
struct ObjectBase;//基类
template<class T>struct sharedptr;//强引用智能指针模板
template<class T>struct weakptr;//弱引用智能指针模板
struct ObjectManager;//对象管理类
struct ReferenceCount {//计数类
	ObjectBase* ptr_obj;//对象指针
	std::atomic<unsigned> cnt_strong;//强引用计数
	std::atomic<unsigned> cnt_weak;//弱引用计数
	void(*deleter)(ObjectBase*&);//强引用计数减至0时对象释放方法
};

struct ObjectBase {
	unsigned use_count() { if (ptr_cnt) { unsigned cnt = ptr_cnt->cnt_strong; if (cnt > 1)return cnt - 1; }return 0; }//获取强引用计数
	ObjectBase() :ptr_cnt(nullptr), t_cnt(0), t_ver(0), t_added(false) {}//默认构造函数
private:
	ReferenceCount* ptr_cnt;//计数对象指针
	unsigned t_cnt;//需要扫描成员数量
	unsigned char t_ver;//扫描版本号
	bool t_added;//是否已加入托管集合
	void setcnt(ReferenceCount*p) {
		if (ptr_cnt != p) {
			if (ptr_cnt&&--ptr_cnt->cnt_weak == 0)
				delete ptr_cnt;
			ptr_cnt = p;
			if (ptr_cnt)
				++ptr_cnt->cnt_weak;
		}
	}
protected:
	virtual ~ObjectBase() { setcnt(nullptr); }//析构方法:不允许手动delete
	virtual unsigned GetScanObjects(weakptr<ObjectBase>**pout) {//用以获取需要扫描的智能指针
																//默认实现认为:1.类型从ObjectBase或ObjectBase的单继承派生类 单继承派生 2.成员只有sharedptr或者weakptr模板类对象
		*pout = reinterpret_cast<weakptr<ObjectBase>*>(const_cast<ObjectBase*>(this + 1));
		return t_cnt;
	}
	template<class T>friend struct weakptr;//友元
	template<class T>friend struct sharedptr;//友元
	friend struct ObjectManager;//友元
};
template<class T>struct weakptr {
	weakptr() :ptr_cnt(nullptr) {}//默认构造空引用
	weakptr(weakptr const&p) :ptr_cnt(p.ptr_cnt) { if (ptr_cnt)++ptr_cnt->cnt_weak; }//复制构造增加弱引用计数
	weakptr& operator=(const weakptr&w);
	~weakptr() {//析构
		if (ptr_cnt&&--ptr_cnt->cnt_weak == 0)
			delete ptr_cnt;
	}
	weakptr& operator=(const sharedptr<T>&w) {//因为sharedptr和weakptr结构一样,这里可以简单粗暴地调用operator=(weakptr)
		return *this = reinterpret_cast<weakptr const&>(w);
	}
	friend bool operator==(weakptr const&w1, weakptr const&w2) { return w1.ptr_cnt == w2.ptr_cnt; }
	friend bool operator!=(weakptr const&w1, weakptr const&w2) { return w1.ptr_cnt != w2.ptr_cnt; }
	sharedptr<T> lock();//该操作需要放到后面实现
private:
	ReferenceCount* ptr_cnt;//指向计数对象
};
template<class T>struct sharedptr {
	sharedptr() :ptr_cnt(nullptr) {}//默认构造空引用
	sharedptr(sharedptr const&p) :ptr_cnt(p.ptr_cnt) { addref(); }//复制构造增加弱引用计数和强引用计数
	explicit sharedptr(T*p) {
		construct(p, p);
	}
	void addref() {
		if (ptr_cnt) {
			++ptr_cnt->cnt_strong;
			++ptr_cnt->cnt_weak;
		}
	}
	void release() {
		if (ptr_cnt) {
			if (--ptr_cnt->cnt_strong == 1) {
				if (ptr_cnt->deleter) {
					ptr_cnt->deleter(ptr_cnt->ptr_obj);
					ptr_cnt->cnt_strong = 0;
				}
				else {
					ObjectBase* p = ptr_cnt->ptr_obj;
					ptr_cnt->ptr_obj = nullptr;
					ptr_cnt->cnt_strong = 0;
					delete p;
				}
			}
			if (--ptr_cnt->cnt_weak == 0) {
				delete ptr_cnt;
				ptr_cnt = 0;
			}
		}
	}
	sharedptr& operator=(const sharedptr&w) {
		if (ptr_cnt != w.ptr_cnt) {//两者所引用的计数对象不同时才需要赋值
			release();
			ptr_cnt = w.ptr_cnt;
			addref();
		}
		return *this;
	}
	friend bool operator==(sharedptr const&w1, sharedptr const&w2) { return w1.ptr_cnt == w2.ptr_cnt; }
	friend bool operator!=(sharedptr const&w1, sharedptr const&w2) { return w1.ptr_cnt != w2.ptr_cnt; }
	friend bool operator==(sharedptr const&w1, std::nullptr_t) { return w1.use_count() == 0; }
	friend bool operator!=(sharedptr const&w1, std::nullptr_t) { return w1.use_count() != 0; }
	~sharedptr() { release(); }//析构
	T& operator*()const { T *p = get(); if (p)return *p; throw std::runtime_error("空引用"); }
	T* get()const { return castpointer(ptr_cnt ? ptr_cnt->ptr_obj : nullptr, (T*)nullptr); }
	T*operator->()const { T *p = get(); if (p)return p; throw std::runtime_error("空引用"); }
	unsigned use_count()const { return ptr_cnt ? (unsigned)ptr_cnt->cnt_strong - 1 : 0; }
private:
	static T* castpointer(ObjectBase*p, ObjectBase*) { return dynamic_cast<T*>(p); }
	static T* castpointer(ObjectBase*p, ...) { return reinterpret_cast<T*>(p); }
	void construct(T*, ObjectBase*p) {
		if (p->ptr_cnt) {
			ptr_cnt = p->ptr_cnt;
			++ptr_cnt->cnt_weak;
			unsigned val = ptr_cnt->cnt_strong;
			while (val == 1) val = ptr_cnt->cnt_strong;
			while (!ptr_cnt->cnt_strong.compare_exchange_weak(val, val == 0 ? 2 : (val + 1))) {
				while (val == 1) val = ptr_cnt->cnt_strong;
			}
		}
		else {
			ptr_cnt = new ReferenceCount();
			ptr_cnt->cnt_weak = 1;
			ptr_cnt->cnt_strong = 2;
			p->setcnt(ptr_cnt);
			ptr_cnt->ptr_obj = p;
			ptr_cnt->deleter = nullptr;
		}
	}
	void construct(T*p, ...) {
		ptr_cnt = new ReferenceCount();
		ptr_cnt->ptr_obj = reinterpret_cast<ObjectBase*>(p);
		ptr_cnt->deleter = &sharedptr::deleter;
		ptr_cnt->cnt_weak = 1;
		ptr_cnt->cnt_strong = 2;
	}
	static void deleter(ObjectBase*&p) {
		delete reinterpret_cast<T*>(p);
		p = nullptr;
	}
	ReferenceCount* ptr_cnt;//指向计数对象
	friend struct weakptr<T>;
	friend struct ObjectManager;
};

struct ObjectManager {
	//根节点
	static ObjectManager& root() { static ObjectManager r; return r; }
	//新增托管对象
	template<class T, class ...Args>static sharedptr<T>newobj(Args...a) {
		T* p = new T(a...);
		sharedptr<T> sp(p);
		sp.ptr_cnt->deleter = &ObjectManager::DeleteMethod;
		p->t_cnt = (sizeof(T) - sizeof(ObjectBase)) / sizeof(weakptr<ObjectBase>);
		ObjectManager::root().AddRootObject(p);
		ObjectManager::root().AddObject(p);
		return sp;
	}
	//删除方法
	static void DeleteMethod(ObjectBase*&) {}
	//构造函数
	ObjectManager()
		:exitOperatingCount(0), enterOperatingCount(0),
		scanidx(0), scanTime(10),
		state(1), version(0), scancnt(0), unscanMembers(0) {
		std::thread(&ObjectManager::ScanThread, this).detach();//启动扫描线程
	}
	//析构函数
	~ObjectManager() {
		state &= ~1;
		while (state & 2)Sleep(1);
		ReleaseAll();
	}
	//进入操作
	void EnterOperating() {
		mtEnter.lock();
		enterOperatingCount++;
		mtEnter.unlock();
	}
	//退出操作
	void ExitOperating() {
		exitOperatingCount++;
	}
	//添加对象到对象表
	void AddObject(ObjectBase*p) {
		if (p) {
			EnterOperating();
			mtobjs.lock();
			objs.push_back(p);
			mtobjs.unlock();
			ExitOperating();
		}
	}
	//添加对象到栈列表并返回栈引用
	sharedptr<ObjectBase> AddRootObject(ObjectBase*p) {
		if (p) {
			if (unscanMembers > 1024 * 1024 * 8) {//当未扫描托管成员数量过多时,立即发起扫描
				ScanNow();
			}
			EnterOperating();
			if (p->t_added) {
				sharedptr<ObjectBase> t(p);
				ExitOperating();
				return t;
			}
			p->t_added = true;//标记为已经加入列表
			unscanCount++;
			unscanMembers += p->t_cnt;
			mtstackobjs.lock();
			rootobjs.push_back(p);
			mtstackobjs.unlock();
			sharedptr<ObjectBase> pt(p);
			ExitOperating();
			return pt;
		}
		return sharedptr<ObjectBase>();
	}
	//移除所有对象
	void ReleaseAll() {
		mtEnter.lock();
		while (enterOperatingCount != exitOperatingCount)Sleep(0);
		std::vector<ObjectBase*> robjs;
		std::vector<ObjectBase*> wobjs;
		std::swap(robjs, objs);
		std::swap(wobjs, rootobjs);
		mtEnter.unlock();
		for (size_t i = 0, j = robjs.size(); i != j; ++i)
			delete robjs[i];
		wobjs.resize(0);
	}
	//立即发起一次扫描
	void ScanNow() {
		unscanMembers = 0;
		unscanCount = 0;
		scanidx = 0;
		std::vector<ObjectBase*>robjs;
		mtEnter.lock();
		while (enterOperatingCount != exitOperatingCount)Sleep(0);
		Scan(robjs);
		for (size_t i = 0, j = robjs.size(); i != j; ++i)delete robjs[i];
		mtEnter.unlock();
	}
	//扫描线程
	void ScanThread() {//扫描线程
		state |= 2;
		try {
			std::vector<ObjectBase*> robjs;
			size_t i, j;
			while (state & 1) {
				if (scanidx++ < scanTime) { Sleep(1000); continue; }
				scanidx = 0;
				//扫描
				mtEnter.lock();
				while (enterOperatingCount != exitOperatingCount)Sleep(0);
				Scan(robjs);
				if (rootobjs.max_size() - rootobjs.size()>rootobjs.size() / 4)
					rootobjs.shrink_to_fit();
				if (objs.max_size() - objs.size()>objs.size() / 4)
					objs.shrink_to_fit();
				mtEnter.unlock();
				for (i = 0, j = robjs.size(); i != j; ++i)
					delete robjs[i];
				robjs.resize(0);
				robjs.shrink_to_fit();
			}
		}
		catch (...) {}
		state &= ~2;
	}
	//扫描函数
	void Scan(std::vector<ObjectBase*>& robjs, unsigned d = 0) {
		unscanMembers = 0;
		unscanCount = 0;
		size_t i, j;
		//更新版本号
		version++;
		//扫描栈对象表
		ObjectBase**proot = rootobjs.data();
		for (i = 0, j = rootobjs.size(); i != j; ++i) {
			if (proot[i]->use_count() == 0) {
				std::swap(rootobjs[i--], rootobjs[--j]);
				proot[j]->t_added = false;//标记为未加入列表
			}
			else UpdateVersion(version, proot[i]);
		}
		rootobjs.resize(j);
		//扫描对象表并记录要释放的对象以及
		for (i = 0, j = objs.size(); i != j; ++i) {
			if (objs.data()[i]->t_ver != version) {
				robjs.push_back(objs.data()[i]);
				objs.data()[i--] = objs.data()[--j];
			}
		}
		objs.resize(j);
	}
	//递归更新版本号
	void UpdateVersion(unsigned char newversion, ObjectBase* p) {
		const int idx_mov = (sizeof(weakptr<ObjectBase>*) + sizeof(ObjectBase*)) / sizeof(unsigned);
		std::vector<unsigned>stack(8192);
		int current = 0;
		(ObjectBase*&)stack[0] = p;
	START:;
		if (p) {
			if (p->t_ver == newversion) {
				goto SWITCH;//返回上一步
			}//该对象已更新过或者对象成员非托管
			p->t_cnt = p->GetScanObjects((weakptr<ObjectBase>**)(&stack[current + sizeof(ObjectBase*) / sizeof(unsigned)]));
			p->t_ver = newversion;
			for (stack[current + idx_mov] = 0;
				stack[current + idx_mov] <p->t_cnt;
				stack[current + idx_mov] ++) {
				ReferenceCount**pcnts = (ReferenceCount**)(stack[current + idx_mov] + (weakptr<ObjectBase>*&)stack[current + sizeof(ObjectBase*) / sizeof(unsigned)]);
				if (*pcnts == nullptr || (*pcnts)->deleter != &ObjectManager::DeleteMethod)continue;
				if ((current += idx_mov + 1) + idx_mov >= stack.size())
					stack.resize(current + idx_mov + 1);
				p = dynamic_cast<ObjectBase*>((*pcnts)->ptr_obj);
				(ObjectBase*&)stack[current] = p;
				//stack[current-1] = 1;//返回位置标1
				goto START;
			Next:;
			}
		}
	SWITCH:;
		if (current == 0)return;
		current -= idx_mov + 1;
		p = (ObjectBase*&)stack[current];
		goto Next;
	}
	//获取对象数
	size_t GetObjectCount()const { return objs.size(); }
	//获取托管根数量
	size_t GetRootCount()const { return rootobjs.size(); }
	//对象表,每个对象在其中至多只有一个记录
	std::vector<ObjectBase*>objs;
	std::mutex mtobjs;
	//根节点表,每个对象在其中最多只有一个记录
	std::vector<ObjectBase*>rootobjs;
	std::mutex mtstackobjs;
	//扫描次数统计
	size_t scancnt;
	//未扫描成员数
	size_t unscanMembers;
	//未扫描对象数量
	size_t unscanCount;
	//当前版本号
	unsigned char version;
	//状态,-1时退出线程
	size_t state;
	//扫描释放毫秒秒间隔(大概)
	size_t scanTime;
	//间隔计数
	size_t scanidx;
	//已进入的添加或删除节点的操作数量
	signed enterOperatingCount;
	//进入锁
	std::mutex mtEnter;
	//已退出的添加或删除节点的操作数量
	std::atomic<signed> exitOperatingCount;

};
template<class T> weakptr<T>& weakptr<T>::operator=(const weakptr<T>&w) {//后台扫描时要锁住赋值操作
	if (ptr_cnt != w.ptr_cnt) {//两者所引用的计数对象不同时才需要赋值
		ObjectManager::root().EnterOperating();
		if (ptr_cnt&&--ptr_cnt->cnt_weak == 0)
			delete ptr_cnt;
		ptr_cnt = w.ptr_cnt;
		if (ptr_cnt)
			++ptr_cnt->cnt_weak;
		ObjectManager::root().ExitOperating();
	}
	return *this;
}

template<class T>sharedptr<T> weakptr<T>::lock()
{
	if ((ptr_cnt&&ptr_cnt->deleter == &ObjectManager::DeleteMethod)) {
		sharedptr<ObjectBase> t = ObjectManager::root().AddRootObject(ptr_cnt->ptr_obj);
		return reinterpret_cast<sharedptr<T>&>(t);
	}
	else
	{
		sharedptr<T> t;
		if (ptr_cnt) {
			unsigned val = ptr_cnt->cnt_strong;
			while (val == 1) val = ptr_cnt->cnt_strong;
			if (ptr_cnt->ptr_obj == nullptr)return t;
			while (!ptr_cnt->cnt_strong.compare_exchange_weak(val, val == 0 ? 2 : (val + 1))) {
				while (val == 1) val = ptr_cnt->cnt_strong;
				if (ptr_cnt->ptr_obj == nullptr)return t;
			}
			t.ptr_cnt = ptr_cnt;
		}
		return t;
	}
}
struct Node:ObjectBase{
	weakptr<Node> head;
	weakptr<Node> next;
};
int main(){
	for (int i  = 1; i; ++i) {
		sharedptr<Node>root  = ObjectManager::newobj<Node>();
		root->next = ObjectManager::newobj<Node>();
		root->next.lock()->head = root;
	}
}

  实际上,代码中还有许多问题没有解决,比如多个线程从同一个ObjectBase*进行sharedptr构造会导致异常,但这代码已基本实现了上一部分的想法。
  另外咱建有个C++交流学习群(群号244953928),期待各位喜欢C++的伙伴加入O(∩_∩)O。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值