Browse Source

修改write-copy.h,使用外部原子变量保护共享指针在多线程中的失效

zzj 6 years ago
parent
commit
87847502a9
5 changed files with 73 additions and 20 deletions
  1. 2 2
      ant.cpp
  2. 1 2
      area.cpp
  3. 1 2
      card.cpp
  4. 2 2
      event.cpp
  5. 67 12
      write-copy.h

+ 2 - 2
ant.cpp

@@ -6,8 +6,8 @@
 #include "event.h"
 #include "tool_time.h"
 #include "area.h"
-template<> std::shared_ptr<sit_list> 
-single_base<sit_list, int, std::shared_ptr<site>>::m_instance=std::make_shared<sit_list>();
+//template<> std::shared_ptr<sit_list> single_base<sit_list, int, std::shared_ptr<site>>::m_instance=std::make_shared<sit_list>();
+
 int site::index()const
 {
 	return m_algo+(m_num_dims<<1);

+ 1 - 2
area.cpp

@@ -21,8 +21,7 @@
 #include "websocket/wsClientMgr.h"
 #include "ant.h"
 
-template<> std::shared_ptr<area_list> 
-single_base<area_list, int, std::shared_ptr<area>>::m_instance=std::make_shared<area_list>();
+//template<> std::shared_ptr<area_list> single_base<area_list, int, std::shared_ptr<area>>::m_instance=std::make_shared<area_list>();
 
 struct underground_area:area
 {

+ 1 - 2
card.cpp

@@ -427,6 +427,5 @@ bool card_list_visit::visit(std::shared_ptr<card_location_base> c)
 	return true;	
 }
 
-template<> std::shared_ptr<card_list> 
-single_base<card_list, uint64_t, std::shared_ptr<card_location_base>>::m_instance=std::make_shared<card_list>();
+//template<> std::shared_ptr<card_list> single_base<card_list, uint64_t, std::shared_ptr<card_location_base>>::m_instance=std::make_shared<card_list>();
 

+ 2 - 2
event.cpp

@@ -399,5 +399,5 @@ void event_list::_ev_to_node(std::shared_ptr<ya_event> ev_ptr,
 
     out_data.PushBack(ev, allocator);
 }
-template<> std::shared_ptr<event_list>
-single_base<event_list, uint64_t, std::shared_ptr<ya_event>>::m_instance=std::make_shared<event_list>();
+
+//template<> std::shared_ptr<event_list> single_base<event_list, uint64_t, std::shared_ptr<ya_event>>::m_instance=std::make_shared<event_list>();

+ 67 - 12
write-copy.h

@@ -1,6 +1,7 @@
 #ifndef _WRITE_COPY_HPP_
 #define  _WRITE_COPY_HPP_
 //add之前如果有数据,需要把运行中更改的数据进行保存。
+#include <assert.h>
 #include <unordered_map>
 #include <algorithm>
 #include <memory>
@@ -115,54 +116,108 @@ private:
 	}
 };
 
+template<typename T>
+struct safe_shared_ptr
+{
+	std::atomic<int> m_mutex;
+	std::shared_ptr<T> m_ptr;
+
+	safe_shared_ptr(std::shared_ptr<T> ptr)
+	{
+		m_mutex=0;
+		m_ptr=ptr;
+	}
+
+	safe_shared_ptr(safe_shared_ptr<T>&&ptr)
+	{
+		m_mutex.store(ptr.m_mutex.load());
+		m_ptr=std::move(ptr.get());
+	}
+
+
+	bool set(std::shared_ptr<T> ptr)
+	{
+		lock();
+		m_ptr=ptr;
+		unlock();
+
+		return true;
+	}
+
+	std::shared_ptr<T> get()
+	{
+		lock();
+		std::shared_ptr<T>  ret=m_ptr;
+		unlock();
+		return ret;
+	}
+
+private:
+	void lock()
+	{
+		int expected=0;
+		while(!m_mutex.compare_exchange_strong(expected,1))
+			expected=0;
+		assert(m_mutex.load()==1);
+	}
+
+	void unlock()
+	{
+		m_mutex.store(0);
+	}
+};
+
 template<typename T,typename K,typename V>
 struct single_base:write_copy_base<T,K,V>
 {
 	typedef write_copy_base<T,K,V> base;
-	static std::shared_ptr<T> m_instance;
+
+	static safe_shared_ptr<T> m_instance;
+	std::mutex         m_mutex;
+
 	static std::shared_ptr<T> instance()
 	{
-		return m_instance;
+		return m_instance.get();
 	}
 
-	std::mutex m_mutex;
-
 	void add(K k,V c)
 	{
 		std::lock_guard<std::mutex> lock(m_mutex);
-		m_instance=std::move(base::clone_add(k,c));
+		m_instance.set(base::clone_add(k,c));
 	}
 
 	void add(const std::unordered_map<K,V>&c)
 	{
 		std::lock_guard<std::mutex> lock(m_mutex);
-		m_instance=std::move(base::clone_add(c));
+		m_instance.set(base::clone_add(c));
 	}
 	void remove(K k,V c)
 	{
 		std::lock_guard<std::mutex> lock(m_mutex);
-		m_instance=std::move(base::clone_remove(k,c));
+		m_instance.set(base::clone_remove(k,c));
 	}
 
 	void remove(const std::unordered_map<K,V>&c)
 	{
 		std::lock_guard<std::mutex> lock(m_mutex);
-		m_instance=std::move(base::clone_remove(c));
+		m_instance.set(base::clone_remove(c));
 	}
 
     void remove(const std::vector<K>&list)
     {
-        std::lock_guard<std::mutex> lock(m_mutex);
-        m_instance=std::move(base::clone_remove(list));
+		std::lock_guard<std::mutex> lock(m_mutex);
+		m_instance.set(base::clone_remove(list));
     }
 
     void remove(K k)
     {
-        std::lock_guard<std::mutex> lock(m_mutex);
-        m_instance=std::move(base::clone_remove(k));
+		std::lock_guard<std::mutex> lock(m_mutex);
+		m_instance.set(base::clone_remove(k));
     }
 };
 
+template<typename T,typename K,typename V> safe_shared_ptr<T> single_base<T,K,V>::m_instance=std::make_shared<T>();
+
 #endif