Pārlūkot izejas kodu

将之前写的stl合并到这个库中

Gogs 4 mēneši atpakaļ
vecāks
revīzija
18b85aa9fd

+ 81 - 0
lib/backward/nanxing_auto_ptr.h

@@ -0,0 +1,81 @@
+//auto_ptr在C++11中被unique_ptr替代,在GNU_STL中现在放在backward/auto_ptr中,可以访问但是不建议使用
+
+#include<new>
+#ifndef _NANXING_AUTO_PTR_H_
+#define _NANXING_AUTO_PTR_H_
+
+namespace nanxing
+{
+    template<typename _Ptr>
+    struct auto_ptr_ref                       //作为一个中继
+    {
+        _Ptr* point;
+        explicit auto_ptr_ref(_Ptr* _p):point(_p){}
+    };
+    template<typename _Ptr>
+    class auto_ptr
+    {
+    private:
+        _Ptr * point;               //auto_ptr中保留的原始指针
+    public:
+    //这里的_Ptr实际上都不是很需要,C++11之后能进行模板类型推导
+        explicit auto_ptr(_Ptr* _p=0)throw():point(_p){}                  
+        auto_ptr(auto_ptr<_Ptr>& _p)throw():point(_p.release()){}
+
+        auto_ptr(auto_ptr<_Ptr>&& _p)throw(){}                     //移动构造函数
+
+        //当然这里的this也是没必要的,只是为了明确一下到底是谁的release
+        auto_ptr<_Ptr>& operator=(auto_ptr<_Ptr>& _p){                  //返回对应的引用是为了能够链式赋值
+            if(_p!=this)
+            {
+                delete this->point;         //释放当前的指针指向的空间
+            }
+            this->point=_p.release();
+            return *this;
+        }
+
+        _Ptr* release()
+        {
+            _Ptr* tmp=point;
+            point=nullptr;
+            return tmp;
+        }
+#ifdef _ES_UNSAFE_
+        _Ptr* get() const
+        {
+            return point;
+        }
+#endif
+        void reset(_Ptr* _p=nullptr)throw()
+        {
+            if(_p!=point)
+            {
+                delete point;
+            }
+            point=_p;
+        }
+
+        //在GNU_STL中还有两个类型转换运算符的定义
+        operator auto_ptr_ref<_Ptr>()             //从auto_ptr->auto_ptr_ref 的定义
+        {
+            return auto_ptr_ref<_Ptr>(this->release());
+        }
+
+        operator auto_ptr<_Ptr>()                       //类型转换运算符
+        {
+            return auto_ptr<_Ptr>(this->release());
+        }
+
+        ~auto_ptr()
+        {
+            if(point!=nullptr)
+            {
+                delete point;
+            }
+        }
+
+
+    };
+}
+
+#endif

+ 3 - 0
lib/backward/nanxing_concept_check.h

@@ -0,0 +1,3 @@
+//这个文件中是的对约束的检来自于SGI-STL 1999年加入的模板类型检查,在GNU-STL(libstdc++)中完全参考了SGI-STL的实现
+//当然这种检查在C++11之后被编译器支持的concept,以及静态断言系统取代了,但是还是对于参数宏,模板的检查与模板类型的检查等学习有很大的参考价值
+

+ 0 - 0
lib/basic/nanxing_STL_queue.h


+ 0 - 0
lib/basic/nanxing_basic_shared_ptr.h


+ 112 - 0
lib/basic/nanxing_basic_signal_linklist.h

@@ -0,0 +1,112 @@
+#ifndef NANXING_BASIC_SIGNAL_LINKLIST_
+#define NANXING_BASIC_SIGNAL_LINKLIST_
+#include"nanxing_defalloc.h"
+#include<mutex>
+#include<deque>
+
+namespace nanxing{
+    template<typename T>
+    struct link_node
+    {
+        T* data;
+        link_node<T>* next;
+
+        link_node(T _data):data(_data),next(nullptr){}
+
+        link_node<T>& operator=(link_node<T>& _data)
+        {
+            data=std::move(_data.data);
+            return *this;
+        }
+
+        link_node(T&& _data):data(_data){}
+    };
+
+
+    template<typename T,typename Alloc=nanxing::allocator<link_node<T>>>
+    class basic_signal_linklist                           //注意这个和list的区别,链表会返回值而不是引用,在某些地方我们需要std::move而不是仅仅获得一个引用
+    {
+    private:
+        std::mutex t;
+        using pointer=link_node<T>*;
+        int size=0;
+        pointer head=nullptr;     //头节点指针
+        pointer end =nullptr;        //这个相当于钻规则的空子,end是晚于head初始化的
+        Alloc Creator;
+    public:
+        explicit basic_signal_linklist(){}
+
+        int push(T&& data)
+        {
+            
+            pointer ptr=Creator.allocate(sizeof(link_node<T>));
+            if(ptr==nullptr)
+            {
+                return -1;
+            }
+            //Creator.construct(ptr,std::move(data));
+            ptr->data=new std::packaged_task<void()>(std::move(data));
+            //(ptr->data)();
+            ptr->next=nullptr;
+            if(head==nullptr)
+            {
+                head=ptr;
+                end=ptr;
+            }
+            else
+            {  
+                end->next=ptr;
+                end=end->next;
+            }
+            size++;
+            ptr=nullptr;
+
+            return 0;
+        }
+
+        int list_size()
+        {
+            return size;
+        }
+
+        pointer pop()
+        {
+            std::unique_lock<std::mutex> lk(t);
+            if(size==0)
+            {
+                return nullptr;
+            }
+            pointer ptr=head;
+
+            head=head->next;
+            size--;
+            if(size==0)
+            {
+                end=nullptr;
+            }
+            return ptr;
+        }
+
+        ~basic_signal_linklist()
+        {
+            while(head!=end)
+            {
+                pointer ptr=head;
+                head=head->next;
+                Creator.destory(ptr);
+            }
+            if(head==end&&head!=nullptr)
+            {
+                Creator.destory(head);
+            }
+        }
+
+
+
+
+    };
+
+
+
+}
+#endif

+ 241 - 0
lib/basic/nanxing_basic_sort.h

@@ -0,0 +1,241 @@
+#ifndef _NANXING_SORT_BASIC_H_
+#define _NANXING_SORT_BASIC_H_
+#include"nanxing_operator_check.h"
+#include"../nanxing_type_trait.h"
+#include<type_traits>
+#include<iostream>
+#include<climits>
+namespace nanxing{
+
+    template<typename T>
+    class sort           //这里的T类型必须是一个指针类型否则会报错
+    {
+    public:
+        
+        static_assert(NANXING_BASIC_OPERATOR_(T,index),"It cannot be indexed");      //检查T类型能否下标访问
+        static_assert(NANXING_BASIC_OPERATOR_(T,compare_ptr),"The data pointed cannot compared");  //检查指向的数据能否比较大小
+        static_assert(NANXING_BASIC_OPERATOR_(T,equal_ptr),"The data pointed cannot assign value");   //检查指向的数据能否相互赋值
+
+        void operator()(T data,size_t size)       //默认的sort用快速排序
+        {
+            fast_sort(data,0,size-1);
+        }
+
+        static void  fast_sort(T data,size_t left,size_t right)           //快速排序
+        {
+            if(right<=left)
+            {
+                return;
+            }
+            using ptr_type=nanxing::remove_pointer<T>::type;
+            ptr_type middle;
+            //选取最后一个数字作为枢纽元(如果不是最后一个就将枢纽元和right元素交换)
+            int i=left;
+            int j=right-1;
+            middle;             
+            if((right-left)<=3)            //当划分的长度小于3的时候用直接插入排序
+            { 
+                for(int i=left+1;i<=right;i++)
+                {
+                    for(int j=i;j>left;j--)
+                    {
+                        if(data[j]<data[j-1])
+                        {
+                            middle=data[j];
+                            data[j]=data[j-1];
+                            data[j-1]=middle;
+                        }
+                    }
+                }
+                return;
+            }
+            for(;;)
+            {
+                while(data[i]<=data[right]&&i<right){i++;}
+                while(data[j]>data[right]&&j>left){j--;}                 //注意书上的例程没有考虑一种非常特殊的情况即在ij同时等于枢纽元
+                if(i<j)
+                {                
+                    middle=data[i];
+                    data[i]=data[j];
+                    data[j]=middle;
+                }
+                
+                else{
+                    break;
+                }
+            }
+            middle=data[i];
+            data[i]=data[right];
+            data[right]=middle;
+            fast_sort(data,left,i-1);
+            fast_sort(data,i+1,right);
+            
+        }
+
+        static void bubble_sort(T data,size_t size)          //冒泡排序
+        {
+
+            using ptr_type=nanxing::remove_pointer<T>::type;
+            ptr_type middle;
+            
+            for(int i=0;i<size;size--)
+            {
+                for(int j=i;j<size-1;j++)
+                {
+                    if(data[j]>data[j+1])
+                    {
+                       middle =data[j+1];
+                       data[j+1]=data[j];
+                       data[j]=middle;
+                    }
+                }
+            }
+        }
+
+        static void  strait_insert_sort(T data, size_t size)     //直接插入排序
+        {
+            using ptr_type=nanxing::remove_pointer<T>::type;
+            ptr_type middle;
+            for(size_t i=1;i<size;i++)
+            {
+                for(int j=i;j>0;j--)
+                {
+                    if(data[j]<data[j-1])
+                    {
+                        middle=data[j];
+                        data[j]=data[j-1];
+                        data[j-1]=middle;
+                    }
+                    else{
+                        break;
+                    }
+                }
+            }
+        }
+
+
+        static void select_sort(T data,size_t size)        //选择排序
+        {
+            using ptr_type=nanxing::remove_pointer<T>::type;
+            ptr_type min;
+            ptr_type middle;
+            int n=0;        
+            for(int i=0;i<size;i++)
+            {
+                min=data[i];
+                n=i;
+                for(int j=i;j<size;j++)
+                {
+                    if(data[j]<min)
+                    {
+                        n=j;
+                        min=data[j];
+                    }
+                }
+                data[n]=data[i];
+                data[i]=min;   
+            }
+        }
+
+
+
+
+        static void heap_sort(T data,size_t size)         //堆排序
+        {
+            using ptr_type=nanxing::remove_pointer<T>::type;
+            ptr_type middle;    
+            size_t middle_size=size;
+            for(int i=static_cast<int>(middle_size/2-1);i>=0;i--)          //构建堆
+            {
+                build_heap(data,i,size);
+            }
+
+
+            for(size_t i=size-1;i>0;i--)
+            {
+                middle=data[0];
+                data[0]=data[i];
+                data[i]=middle;
+                build_heap(data,0,i);
+            }
+
+        }
+
+
+        static void  Hill_sort(T data,size_t jump,size_t size)        //希尔排序
+        {
+            using ptr_type=nanxing::remove_pointer<T>::type;
+            ptr_type middle;    
+            if(jump*2>=size-1)                    //如果跳跃的间隔过大就直接用直接插入排序
+            {
+                strait_insert_sort(data,size);  
+                return;
+            }
+            for(int i=0;i<jump;i++)                    //分组做直接插入排序
+            {
+                for(int j=i+jump;j<size;j+=jump)
+                {
+
+                    for(int k=j;k>=jump;k-=jump)
+                    {
+                        if(data[k]<data[k-jump])
+                        {
+                            middle=data[k-jump];
+                            data[k-jump]=data[k];
+                            data[k]=middle;
+                        }
+                        
+                        else{
+                            break;
+                        }
+                    }         
+                    
+                }
+            }
+            strait_insert_sort(data,size);
+        }
+
+
+        static void Print(T data,size_t size)
+        {
+            for(int i=0;i<size-1;i++)
+            {
+                std::cout<<data[i]<<" "<<","<<" ";
+            }
+            std::cout<<data[size-1]<<std::endl;
+        }
+
+    private:
+
+        static void build_heap(T data ,size_t S,size_t size)    //除了S之外的所有点都满足大顶堆的定义
+        {
+            using ptr_type=typename nanxing::remove_pointer<T>::type;
+            ptr_type middle=data[S];
+            int middle_s=S;
+            for(int j=2*middle_s+1;j<=(size-1);j=j*2+1)    //这个是左孩子
+            {
+                if(j<size-1&&data[j]<data[j+1])          //注意这里的范围j<size-1,size是其中点的数量,但是下标从0开始的
+                {
+                    j++;
+                }
+                if(middle>data[j]){
+        
+                    break;
+                }
+                else{
+                    data[middle_s]=data[j];
+                    middle_s=j;
+                }
+            }
+            data[middle_s]=middle;
+        }
+
+    private:
+        unsigned int amount;
+        //T* sort_data_ptr;         //指向需要排序的数据(一个数组或者一个vector之类的指针)
+        //T& sort_data_ptr;         //原始数据的引用
+
+    };
+
+}
+#endif

+ 117 - 0
lib/basic/nanxing_defalloc.h

@@ -0,0 +1,117 @@
+#ifndef _DEF_ALLOC_
+#define _DEF_ALLOC_ 1
+#include<iostream>
+#include<cstddef>
+#include<new>
+#include<climits>
+namespace nanxing
+{
+	template<typename T>
+	constexpr
+	inline T* _allocate(ptrdiff_t size, T*) noexcept                  //这个是STL标准的要求,第二个传入的T*没啥用(在实际调用的时候会传入一个空指针)
+	{
+		T* temp;
+		try
+		{
+			temp = (T*)(::operator new((size_t)(size * (sizeof(T)))));
+		}
+		catch(...)
+		{
+			return nullptr;                                        //如果出现失败会直接返回nullptr
+		}
+		return temp;
+	}
+
+
+	//template<typename T1,typename T2>
+	// inline void _construct(T1* p, const T2& x)
+	// {
+	// 	::new(p) T1(x);   //在p指向空间上调用构造函数
+	// }
+
+	template<typename _Up, typename... _Args>
+	inline void _construct(_Up* __p, _Args&&... __args) noexcept(std::is_nothrow_constructible<_Up, _Args...>::value)
+	{ 
+		::new((void *)__p) _Up(std::forward<_Args>(__args)...); 
+	}	
+	
+
+	template<typename T>
+	constexpr
+	inline void _deallocate(T* buffer)
+	{
+		::operator delete(buffer);                   //释放空间(注意和delete的区别)
+	}
+
+	template<typename T>
+	constexpr
+	inline void _destory(T* ptr)
+	{
+		ptr->~T();                     //调用析构函数
+	}
+
+	template<typename T>
+	class allocator
+	{
+	public:
+		using value_type = T;
+		using pointer = T*;
+		using const_pointer = const T*;
+		using reference = T&;
+		using size_type = size_t;
+		using difference_type = ptrdiff_t;
+		using const_reference = const T&;
+		
+		constexpr  allocator() noexcept
+		{
+			//std::cout<<"hello"<<std::endl;
+		}
+		template<typename U> struct rebind
+		{
+			using other = allocator<U>;
+		};
+		constexpr pointer allocate(size_type n, const void* hint = 0)           //注意这个函数是会抛出一个std::bad_alloc异常
+		{
+			return _allocate((difference_type)n, (pointer)0);
+		}
+
+		
+		template<typename... _Args>
+		void construct(pointer __p, _Args&&... __args) noexcept
+		{ 
+			_construct(__p,std::forward<_Args>(__args)...);
+			//::new((void *)__p) _Up(std::forward<_Args>(__args)...); 
+		}	
+
+		// template<pointer,typename T2>
+		// void construct(pointer p,const T2& data )noexcept         //唯一参数版本
+		// {
+		// 	_construct(p,data);
+		// }
+		constexpr void deallocate(pointer p, size_type n=0)
+		{
+			_deallocate(p);
+		}
+
+		constexpr void destory(pointer p)
+		{
+			_destory(p);
+		}
+
+		constexpr pointer address(reference x)
+		{
+			return (pointer)&x;
+		}
+		constexpr const_pointer address(const_reference x)
+		{
+			return (const_pointer)&x;
+		}
+		
+		constexpr size_type max_size()const
+		{
+			return size_type(UINT_MAX / sizeof(T));
+		}
+	};
+}
+
+#endif

+ 96 - 0
lib/basic/nanxing_operator_check.h

@@ -0,0 +1,96 @@
+#ifndef _NANXING_CHECK_OPERATOR_H_
+#define _NANXING_CHECK_OPERATOR_H_
+#include<type_traits>
+//这个文件的目的是为了做一些匹配性检查,检查一些泛型的实例化是否能满足一定的要求
+//使用SFINAE
+//这个头文件的操作需要编译器至少支持C++11才能用,但是在C++20中引入的约束模板类型已经成功的将这些抽象的操作加入语法中
+//由于到目前(2024年10月还有部分编译器的默认支持不是C++20,因此还是保留这个文件)
+//当然目前libstdc++中模板的判断还是用类似的方法
+
+#define NANXING_TYPETRAIT_TEMPLATE_T_V_ template<typename T ,typename V =void >
+#define NANXING_TYPETRAIT_TEMPLATE_T_ template<typename T > 
+#define NANXING_BASIC_OPERATOR_(Type, Op) nanxing::Op##_admit<Type>::value   //注意要写成这样才行
+namespace nanxing{
+    template<typename...>         //这里用泛型的作用在于为了后面做模板参数匹配
+    using void_t=void;
+
+    NANXING_TYPETRAIT_TEMPLATE_T_V_
+    struct add_admit:std::false_type{static void p(){std::cout<<"false"<<std::endl;}};                //基础模板类型
+
+
+    //关于这里需要使用void_t修饰,这个是这样的
+    //这里实际上是做了一个偏特化,将V进行特化,特化为void_t<decltype(std::declval<T>()+std::declval<T>())>
+    //当我们使用的时候我们实际上是只传入了一个参数,第二个参数使用默认值void,当且仅当偏特化的特化值为void的时候才能成功匹配
+    //看下面这个例子即可
+
+    // template<typename T,typename V=void>
+    // struct test{static const int value=0;};
+    // template<typename T>
+    // struct test<T,void>{static const int value=1;};
+
+    //T能否进行加法运算
+    NANXING_TYPETRAIT_TEMPLATE_T_
+    struct add_admit<T,void_t<decltype(std::declval<T>()+std::declval<T>())>>:std::true_type{static void p(){std::cout<<"true"<<std::endl;}};
+
+    //T能否进行减法运算
+    NANXING_TYPETRAIT_TEMPLATE_T_V_
+    struct mut_admit:std::false_type{};
+
+    NANXING_TYPETRAIT_TEMPLATE_T_
+    struct mut_admit<T,void_t<decltype(std::declval<T>()-std::declval<T>())>>:std::true_type{};
+
+    //T能否进行比较
+    NANXING_TYPETRAIT_TEMPLATE_T_V_
+    struct compare_admit:std::false_type{};
+
+    NANXING_TYPETRAIT_TEMPLATE_T_
+    struct compare_admit<T,void_t<decltype(std::declval<T>()<std::declval<T>())>>:std::true_type{};
+
+    //T能否相互赋值
+    NANXING_TYPETRAIT_TEMPLATE_T_V_
+    struct equal_admit:std::false_type{};
+
+    NANXING_TYPETRAIT_TEMPLATE_T_
+    struct equal_admit<T,void_t<decltype(std::declval<T>()=std::declval<T>())>>:std::true_type{};
+
+    //T能否下标运算
+    NANXING_TYPETRAIT_TEMPLATE_T_V_
+    struct index_admit:std::false_type{};
+
+    NANXING_TYPETRAIT_TEMPLATE_T_
+    struct index_admit<T,void_t<decltype(std::declval<T>()[0])>>:std::true_type{};    
+
+    //T指向的数据能否进行比较运算
+    NANXING_TYPETRAIT_TEMPLATE_T_V_
+    struct compare_ptr_admit:std::false_type{};
+
+    NANXING_TYPETRAIT_TEMPLATE_T_
+    struct compare_ptr_admit<T,void_t<decltype(std::declval<T>()[0]==std::declval<T>()[0])>>:std::true_type{};
+
+    //T指向的数据能否相互赋值
+    NANXING_TYPETRAIT_TEMPLATE_T_V_
+    struct equal_ptr_admit:std::false_type{};
+
+    NANXING_TYPETRAIT_TEMPLATE_T_
+    struct equal_ptr_admit<T,void_t<decltype(std::declval<T>()[0]=std::declval<T>()[0])>>:std::true_type{};
+
+    //T类型可以作为可调用对象进行调用
+    NANXING_TYPETRAIT_TEMPLATE_T_V_
+    struct fun_admit:std::false_type{};
+
+    NANXING_TYPETRAIT_TEMPLATE_T_
+    struct fun_admit<T,void_t<decltype(std::declval<T>()())>>:std::true_type{};
+    
+
+    //T类型允许从一个T类型的实例构造(即拷贝构造)
+    NANXING_TYPETRAIT_TEMPLATE_T_V_
+    struct copy_construct_admit:std::false_type{};
+
+    NANXING_TYPETRAIT_TEMPLATE_T_
+    struct copy_construct_admit<T,void_t<decltype(T(std::declval<T>(T)))>>:std::true_type{};      
+    //接下去用另一种技术实现函数存在性的判定
+    //用函数的模板匹配
+
+
+}
+#endif

+ 21 - 0
lib/basic/nanxing_share_ptr.h

@@ -0,0 +1,21 @@
+#ifndef _NANXING_SHARE_PTR_
+#define _NANXING_SHARE_PTR_
+#include<iosfwd>        //这个是GNU-STL的库(目前还没有确定过stl-STL里到底有没有)
+
+
+namespace nanxing
+{
+
+    
+}
+
+
+
+
+
+
+
+
+
+
+#endif

STL/basical/type_checking.h → lib/basical/type_checking.h


STL/extend/filter.h → lib/extend/filter.h


+ 1 - 1
STL/extend/skiplist.h

@@ -28,6 +28,7 @@ namespace nanxing_extend
             return "malloc new node error";
         }
     };
+
     class random_error:std::exception             //申请预设随机数空间的时候
     {
         const char* what() const noexcept
@@ -227,7 +228,6 @@ namespace nanxing_extend
             return sk;
         }
 
-        
         auto Delete_node(K _key) noexcept ->std::variant<Skip_result,V>            //由于使用侵入式数据结构,因此当节点空间析构的时候对应的数据也会完全析构
         {
             std::variant<Skip_result,V> sk;

+ 81 - 0
lib/future/nanxing_static_reflect.h

@@ -0,0 +1,81 @@
+#ifndef _STATIC_H_
+#define _STATIC_H_
+//静态反射库(C++26提案中出现C++静态反射)
+//但是C++能通过一些现有的手段实现静态反射,这里尝试一下写一个C++的静态反射
+
+//验证宏的参数个数
+
+//这个也很有意思,用了64个占位符号,
+
+#define EMPTY_MACRO_CHECK(...) __VA_ARGS__ EMPTY_MACRO_CHECK_1     //用于实现判断参数个数是不是零个,如果是0个将返回一个全空的字符串
+#define EMPTY_MACRO_CHECK_1(...) #__VA_ARGS__  
+
+
+#define GET_NTR_AGR(   \
+    _1,_2,_3,_4,_5,_6,_7,_8,_9,_10, \
+    _11,_12,_13,_14,_15,_16,_17,_18, \
+    _19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,\
+    _31,_32,_33,_34,_35,_36,_37,_38,_39,\
+    _40,_41,_42,_43,_44,_45,_46,_47,_48,_49,\
+    _50,_51,_52,_53,_54,_55,_56,_57,_58,_59, \
+    _60,_61,_62,_63,_64,n,...)n
+
+#define GET_ARG_COUNT(...)  GET_NTR_AGR(__VA_ARGS__,                    \
+            64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, \
+            48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, \
+            32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, \
+            16, 15, 14, 13, 12, 11, 10, 9,  8,  7,  6,  5,  4,  3,  2,  1,0 ) \
+
+
+
+//接下来一个计算结构体的参数类型的泛型
+
+
+struct Any_type
+{
+    template<typename T>
+    operator T();                      //即代表在模板中Any_type结构体可以转换为任意类型(当然,这个只能在编译期的模板中使用)
+                                        //这是C++模板的一个很重要的特性,即C++在模板中不会关注这个类型能否这样进行转换,也不关注是怎么进行转换的
+                                        //(这也是为什么这个函数连函数体都可以没有)
+                                        //C++模板推导过程中只关注这个函数的转换的类型结果是什么
+                                        //同时也可以引出另一个特性,即C++模板推导中使用一个函数的返回值作为推导依据时,同样C++也只关注返回值类型是什么
+                                        //同时C++的特化是做惰性特化,在运行期不调用的函数根本不会进行特化
+                                        //这也就是为什么这个函数可以存在且运行期不会报错的原因,因为C++根本没有生成这个模板函数的实例
+                                        //下面就是一个例子
+};
+
+
+
+/******************************************
+ * 加上第二个前置的知识SFINAE(Substitution failure is not an error)
+ * 首先一言以蔽之,这实际上可以理解为模板的重载
+ * 这几个词确实很抽象
+ * 一个一个解释Substitution指的是模板匹配的过程
+ * failure失败,歧义主要出现在这里
+ * 在计算机程序中的失败和现实中不太一样
+ * 看一个例子(if语句)
+ *int a=0;
+ *if(a==1)
+ * a++;
+ *if(a==0)
+ * a--;
+ * 首先在if(a==1)中会匹配失败(failure)
+ * 但是会继续去匹配if(a==0)即failure is not error
+ * 
+ *  
+ * ******************************************/
+// template <typename T,typename ... Args>
+// consteval int CountMember(Args&&... args)       等价写法
+template <typename T>
+consteval int CountMember(auto&&... Args)
+{
+    if constexpr(!requires{T{Args...};})
+    {
+        return sizeof...(Args)-1;
+    }
+    else{
+        return CountMember<T>(Args... , Any_type{});           //递归添加一个额外的参数
+    }
+}
+
+#endif

+ 0 - 0
lib/nanxing_algorithm.h


+ 6 - 0
lib/nanxing_future.h

@@ -0,0 +1,6 @@
+#ifndef _NANXING_FUTURE_H_
+#define _NANXING_FUTURE_H_
+#include"future/nanxing_static_reflect.h"
+
+
+#endif

+ 10 - 0
lib/nanxing_memory.h

@@ -0,0 +1,10 @@
+#ifndef NANXING_MEMORY_
+#define NANXING_MEMORY_
+
+#include<new.h>                    //访问系统提供的new函数
+#include"backward/nanxing_auto_ptr.h"        //auto_ptr指针
+#include"basic/nanxing_defalloc.h"              //空间分配函数
+#include"others/nanxing_memory_pool.h"         //线程池
+
+
+#endif

+ 35 - 0
lib/nanxing_new.h

@@ -0,0 +1,35 @@
+#ifndef NANXING_NEW_H_
+#define NANXING_NEW_H_ 1
+#include<iostream>
+//这是一个基础类,GNU-STL中的new头文件里对new的各种重载的只有声明没有定义,
+//定义在C++运行时以及编译器中,这里只能定义一些可能需要的operator new的重载
+//这里主要是为了提供一些用于方便自定义operator的基础函数
+//只需要在外面封装上薄薄的一层operator外壳就即可
+
+namespace nanxing{
+    //这一对函数来之于effective C++,同时参考了static的对初始化的判定(static使用额外的一个int来判定数据已经被成功初始化)
+    //同样的这个new函数也会在前面附加一个char长度的空间,这个空间中将会用于判定是否已经被释放
+    void*  safe_new(size_t size)
+    {
+        char* data=(char*)malloc(size+1);          //加上一个1位的额外空间作为标识符
+        *data='{';
+        data+=1;
+        return static_cast<void*>(data);
+    }
+
+
+    void safe_delete(void* data,size_t) 
+    {
+        char * middle=static_cast<char*>(data);
+        middle-=1;
+        if(*middle=='{')
+        {
+            *middle='\n';
+            free(static_cast<void*>(middle));
+        }
+        else{
+            std::cerr<<"The space has not been free"<<std::endl;
+        }
+    }
+}
+#endif

+ 6 - 0
lib/nanxing_other.h

@@ -0,0 +1,6 @@
+#ifndef OTHERS_H_
+#define OTHERS_H_
+#include"others/skiplist.h"
+
+
+#endif

+ 0 - 0
lib/nanxing_queue.h


+ 5 - 0
lib/nanxing_sort.h

@@ -0,0 +1,5 @@
+#ifndef _NANXING_SORT_H_
+#define _NANXING_SORT_H_
+#include"basic/nanxing_basic_sort.h"
+
+#endif

+ 22 - 0
lib/nanxing_type_trait.h

@@ -0,0 +1,22 @@
+#ifndef NANXING_TYPE_TRAIT_
+#define NANXING_TYPE_TRAIT_
+
+namespace nanxing
+{
+    template<typename T>
+    struct remove_pointer{
+        using type=T;
+    };
+
+
+    template<typename T>
+    struct remove_pointer<T*>           //如果是指针就会匹配这个
+    {
+        using type=typename remove_pointer<T>::type;         //递归一直到匹配到非指针类型
+    };
+
+    template<typename T>
+    using remove_pointer_t=typename remove_pointer<T>::type;
+}
+
+#endif

+ 0 - 0
lib/others/Astar.h


+ 1 - 0
lib/others/data_structure_of_nanxing/data_structure.md

@@ -0,0 +1 @@
+<p> 这里的数据结构算是一个练习吧,没有太考虑完备性什么的,当然,在后面可能会有一部分会加入到正式的lib中 </p>

+ 34 - 0
lib/others/data_structure_of_nanxing/nanxing_link_list_test.h

@@ -0,0 +1,34 @@
+#ifndef _nanxing_test_link_list_
+#define _nanxing_test_link_list_
+#include"../../basic/nanxing_operator_check.h"
+#include"../../basic/nanxing_defalloc.h"
+#include<iostream>
+#include<assert.h>
+
+template<typename T>
+struct SLinkNode
+{
+    static_assert(NANXING_BASIC_OPERATOR_(T,equal),"This type has no operator equal");
+    T data;
+    SLinkNode<T>* next;
+
+    SLinkNode():next()nullptr{}
+    ~SLinkNode(){}
+}
+
+
+template<typename T,typename Alloc=nanxing::allocator>
+class Slist
+{
+    
+    SLinkNode<T>* head;
+
+    Slist():head(nullptr){};
+
+    int insert() noexcept
+    {
+        
+    }
+}
+
+#endif

+ 10 - 0
lib/others/nanxing_memory_pool.h

@@ -0,0 +1,10 @@
+#ifndef NANXING_MEMORY_POOL_
+#define NANXING_NEMORY_POOL_
+
+namespace nanxing
+{
+    
+}
+
+
+#endif

+ 371 - 0
lib/others/skiplist.h

@@ -0,0 +1,371 @@
+//stl之外的东西
+
+#ifndef _SKIPLISTS_H_
+#define _SKIPLISTS_H_
+#include<ostream>
+#include<cstdlib>
+#include<type_traits>
+#include<shared_mutex>
+#include<mutex>
+#include<cstring>
+#include<random>
+#include<chrono>
+#include<optional>
+#include"../nanxing_memory.h"
+
+namespace nanxing
+{
+    template<typename K,typename V=int>           
+    struct SkiplistNode
+    {
+
+    
+    private:
+        K key;            
+        V Value;
+
+    public:
+     using deep_point=SkiplistNode**;
+        explicit SkiplistNode(){}
+        SkiplistNode(K _k,V _v,int _deep):key(_k),Value(_v),deep_level(_deep)      //这里有个问题,即V只能是一个可复制或者可移动的类型
+        {
+            forward=  new SkiplistNode*[deep_level+1];   //构造一个存储对应的数据的指针(分配空间就好了没必要调用构造函数)
+            std::memset(forward,0,sizeof(SkiplistNode*)*(deep_level+1));      //全部初始化为0
+        }
+        ~SkiplistNode()
+        {
+   
+            delete[] forward;     
+        }
+
+        [[nodiscard]]
+        V get_value()const{return Value;};
+
+        [[nodiscard]]       //没事不要乱取值,否则会影响性能,返回值不用取来干嘛
+        K get_key()const{return key;}
+
+        void set_value(V _v){Value=_v;}
+
+        [[nodiscard]]
+        V reset_value(V _v){Value=_v;}
+        
+        deep_point forward;                //指向下一层数据的指针数组的指针
+        int deep_level;
+
+    };
+
+    template<typename K,typename V,typename alloc=nanxing::allocator<SkiplistNode<K,V>>>      //使用自定义构造器
+    class Skiplists
+    {
+    public:
+    using Node=SkiplistNode<K,V>;
+        Skiplists(int _max_level):Creater(),max_level(_max_level){ 
+            current_level=0;
+            Node_count=0;
+            K key;
+            V value;
+            head=(this->Creater.allocate(sizeof(SkiplistNode<K,V>)));
+            Creater.construct(head,key,value,_max_level);
+
+            for(int i=0;i<10000;i++)
+            {
+                random_map[i]=get_random();
+            }
+        }
+
+        [[nodiscard]]
+        SkiplistNode<K,V>* creat_node(K key,V value,int level)             //如果返回值被忽略会发生内存泄露
+        {
+            SkiplistNode<K,V>* tmp=static_cast<SkiplistNode<K,V>*>(Creater.allocate(sizeof(SkiplistNode<K,V>(key,value,level)))) ;          
+            Creater.construct(tmp,key,value,level);                                   //进行内存分配
+            return tmp;
+        }
+
+        int List_size(){return {Node_count};}
+
+        [[nodiscard]]
+        int insert_Node(K key,V value)             //插入节点
+        {
+        #ifdef _THREAD_                             //考虑到很多时候是用单线程异步所以用锁反而会拖累速度,所以条件编译单线程不加锁
+            std::unique_lock<std::shared_mutex>lk{RWmutex};                        //这里用的是写锁
+        #endif
+            Node* tmp=this->head;
+            Node* updata[max_level]={0};                     //用于记录每一层的路径(首先初始化为全nullptr)
+            
+            for(int i= current_level;i>=0;i--)                          //从最顶层开始向下查找                    
+            {
+                while(tmp->forward[i]!=nullptr&&tmp->forward[i]->get_key()<key)        //寻找插入点(这里的i代表在同一层)
+                {                                                                       //head节点是一个没有值的全空节点,用于标识头部,因此插入的所有节点都在head之后
+                                                                                        //因此查找的起始点是head->forward
+                    tmp=tmp->forward[i];                                     //这里需要参考skiplist的论文
+                                                                            //这里递归向下的愿意是一个在i层出现的节点一定会出现在n层(n<i)
+                                                                            //即只需要从这个节点开始先后查找即可
+                }
+                updata[i]=tmp;             //用于记录每一层插入的位置
+            }
+
+            tmp=tmp->forward[0];          //查看最底层
+            if(tmp!=nullptr&&tmp->get_key()==key)
+            {
+
+                return 2;                  //代表点已经存在
+            }
+            else      //{tmp==nullptr|| tmp->get_key()!=key}
+            {
+                int _node_level=random_map[random_point%10000];     //打表,但是最离谱的是rand()比这边打表还快
+
+                random_point++;      //这个如果没有就退化为单链表
+
+
+                
+
+                if(_node_level>current_level)
+                {
+                    for(int i=_node_level+1;i>=current_level+1;i--)
+                    {
+                        updata[i]=head;
+                    }
+                    current_level=_node_level;
+                }
+
+                Node* _insert=creat_node(key,value,_node_level);
+
+                for(int i=0;i<=_node_level;i++)
+                {
+                    _insert->forward[i]=updata[i]->forward[i];
+                    updata[i]->forward[i]=_insert;
+                }
+                Node_count++;
+
+                return 1;                     //插入成功
+            }
+            
+        
+            return -1;                      //插入失败
+        }
+
+        int insert_Node(SkiplistNode<K,V>* _insert)
+        {
+        #ifdef _THREAD_                             //考虑到很多时候是用单线程异步所以用锁反而会拖累速度,所以条件编译单线程不加锁
+            RWmutex.lock();                        //这里用的是写锁
+        #endif
+            K key=_insert->get_key();
+            Node* tmp=this->head;
+            Node* updata[max_level]={0};                     //用于记录每一层的路径(首先初始化为全nullptr)
+            
+            for(int i= current_level;i>=0;i--)                          //从最顶层开始向下查找                    
+            {
+                while(tmp->forward[i]!=nullptr&&tmp->forward[i]->get_key()<key)        //寻找插入点(这里的i代表在同一层)
+                {
+                    tmp=tmp->forward[i];                                     //这里需要参考skiplist的论文
+                }
+                updata[i]=tmp;             //用于记录每一层插入的位置
+            }
+
+            tmp=tmp->forward[0];          //查看最底层
+            if(tmp!=nullptr&&tmp->get_key()==key)             //这里做一个截断判定,如果是空指针不会判定第二个条件
+            {
+        #ifdef _THREAD_
+            RWmutex.unlock();
+        #endif
+                return 2;                  //代表点已经存在
+            }
+            else      //{tmp==nullptr|| tmp->get_key()!=key}
+            {
+                int _node_level=_insert->deep_level;
+
+                if(_node_level>current_level)
+                {
+                    for(int i=_node_level+1;i>current_level+1;i--)
+                    {
+                        updata[i]=head;
+                    }
+                }
+
+                for(int i=0;i<=_node_level;i++)
+                {
+                    _insert->forward[i]=updata[i]->forward[i];
+                    updata[i]->forward[i]=_insert;
+                }
+                Node_count++;
+        #ifdef _THREAD_
+            RWmutex.unlock();
+        #endif
+                return 1;                     //插入成功
+            }
+        #ifdef _THREAD_
+            RWmutex.unlock();
+        #endif
+            return -1;                      //插入失败
+
+        #ifdef _THREAD_
+            RWmutex.unlock();
+        #endif
+        }
+
+        bool search_Node(K key)                   //查找值是否存在
+        {
+        #ifdef _THREAD_                             //考虑到很多时候是用单线程异步所以用锁反而会拖累速度,所以条件编译单线程不加锁
+            RWmutex.lock_shared();                        //这里用的是读锁
+        #endif
+            using Node=SkiplistNode<K,V>;
+            Node* tmp=head;
+            for(int i=current_level;i>=0;i--)             //逐层查找
+            {
+                while(tmp->forward[i]!=nullptr&&tmp->forward[i]->get_key()<key)
+                {
+                    tmp=tmp->forward[i];
+                }
+            }
+            tmp=tmp->forward[0];
+            if(tmp!=nullptr&&tmp->get_key()==key)
+            {
+                return true;
+            }
+            else
+            {
+                return false;
+            }
+
+        #ifdef _THREAD_                             //考虑到很多时候是用单线程异步所以用锁反而会拖累速度,所以条件编译单线程不加锁
+            RWmutex.unlock_shared();                        //这里用的是读锁
+        #endif
+        }
+
+        std::optional<V> get_value_from_key(K key)       //通过键返回值
+        {
+        #ifdef _THREAD_                             //考虑到很多时候是用单线程异步所以用锁反而会拖累速度,所以条件编译单线程不加锁
+            RWmutex.lock_shared();                        //这里用的是读锁
+        #endif
+            using Node=SkiplistNode<K,V>;
+            std::optional<V> opt;
+            Node* tmp=head;
+            for(int i=current_level;i>=0;i--)             //逐层查找
+            {
+                while(tmp->forward[i]!=nullptr&&tmp->forward[i]->get_key()<key)
+                {
+                    tmp=tmp->forward[i];
+                }
+            }
+            tmp=tmp->forward[0];
+            if(tmp!=nullptr&&tmp->get_key()==key)
+            {
+                opt=tmp->get_value();
+            }
+            else
+            {
+                opt = std::nullopt; 
+            }
+            return opt; 
+        #ifdef _THREAD_                             //考虑到很多时候是用单线程异步所以用锁反而会拖累速度,所以条件编译单线程不加锁
+            RWmutex.unlock_shared();                        //这里用的是读(共享)锁
+        #endif
+        }
+
+        int delete_Node(K key)
+        {
+        #ifdef _THREAD_                             //考虑到很多时候是用单线程异步所以用锁反而会拖累速度,所以条件编译单线程不加锁
+            RWmutex.lock();                        //这里用的是写锁
+        #endif
+
+            using Node=SkiplistNode<K,V>;
+            Node* updata[current_level]={nullptr};           //由于是删除,用current_level就好了
+            
+            Node* tmp=head;
+            for(int i=current_level;i>=0;i++)
+            {
+                while(tmp->forward[i]!=nullptr&&tmp->forward[i]->get_key()<key)
+                {
+                    tmp=tmp->forward[i];
+                }
+                updata[i]=tmp;
+            }
+
+            tmp=tmp->forward[0];
+            if(tmp!=nullptr&&tmp->get_key()==key)            //判断第一层的这个点是否为需要删除的点
+            {
+                Node* deletes=tmp;
+                for(int i=0;i<current_level;i++)                   //从下往上修改对应的指针
+                {
+                    if(updata[i]->forward[i]!=key)                 //到某一层这个指针指向的不是需要删除的节点的时候停止(跳表中任意的节点只会出现在第0-k层)
+                    {
+                        break;
+                    }
+                    updata->forward[i]=tmp->forward[i];
+                }
+                Creater.destory(deletes);                   //调用析构函数
+                Creater.deallocate(deletes);                //释放空间
+
+                return 1;                                 //删除成功
+            }
+            else
+            {
+                return 0;                                 //没有需要删除的节点
+            }
+            return -1;                                     //删除失败
+   
+        #ifdef _THREAD_
+            RWmutex.unlock();
+        #endif
+        }
+
+        void Print_basic()
+        {
+            using Node=SkiplistNode<K,V>;
+            Node* tmp=head;
+            if(tmp->forward[0]!=nullptr)
+            {
+                tmp =tmp ->forward[0];
+                std::cout<<"("<<tmp->get_key()<<","<<tmp->get_value()<<")";
+            }
+            while(tmp->forward[0]!=nullptr)
+            {
+                tmp=tmp->forward[0];
+                std::cout<<"->"<<"("<<tmp->get_key()<<","<<tmp->get_value()<<")";
+                
+            }
+            std::cout<<std::endl;
+
+        }
+private:
+        int get_random()                           //生成随机数,用于创建对应的数据的层数
+        {
+            // 通过<chrono>库获取当前的高精度时间点  
+            auto now = std::chrono::system_clock::now();  
+            // 将时间点转换为自纪元(通常是1970年1月1日)以来的纳秒数  
+            auto duration_since_epoch = now.time_since_epoch();  
+            // 将纳秒数转换为无符号长整型,用作随机数生成的种子  
+            unsigned long seed = std::chrono::duration_cast<std::chrono::nanoseconds>(duration_since_epoch).count();  
+        
+            // 创建一个随机数引擎,这里使用的是Mersenne Twister引擎  
+            std::mt19937 rng(seed);  
+        
+            // 定义一个均匀分布的整数范围
+            std::uniform_int_distribution<int> dist(0, max_level);  
+        
+            //生成一个随机数  
+            return dist(rng); 
+            //return (rand()%max_level);
+             
+        }
+    private:
+        int max_level;
+
+        int current_level;                        //当前的深度
+
+    #ifdef _THREAD_                               //不是多线程没有必要 
+        std::shared_mutex RWmutex;                      //读写锁
+    #endif
+        alloc Creater;                                 //构造器实例
+
+        SkiplistNode<K,V>* head;                               //跳表的起点
+
+        int Node_count;                                   //总结点数  
+
+        int random_map[10000]={0};                       //随机数表
+
+        int random_point=0;                              //指示当前访问的随机数的位置
+    };
+}
+
+#endif

+ 226 - 0
lib/others/thread_pool.h

@@ -0,0 +1,226 @@
+#ifndef thread_poll_
+#define thread_poll_
+
+#include<thread>
+#include<mutex>
+#include<shared_mutex>
+#include<vector>      
+#include<tuple>    
+#include<chrono>
+#include<condition_variable>
+#include<future>
+#include"../basic/nanxing_operator_check.h"
+#include"../basic/nanxing_basic_signal_linklist.h"          //任务链表
+
+namespace nanxing
+{
+    template<typename T>                     //一个不带有任务窃取的简单可伸缩队列(明天实现伸缩)
+    class basic_thread_pool
+    {
+
+    static_assert(NANXING_BASIC_OPERATOR_(T,fun),"The type is illigel");     //验证T是否是一个可调用对象
+
+    private:
+        std::condition_variable task_empty;
+        std::mutex queue_mutex;                 //任务队列锁
+        nanxing::basic_signal_linklist<T> tasks;         //任务队列
+        int Max_size=1;       //线程的最多数量,默认由硬件数量决定
+        std::vector<std::thread> thread_group;                    //线程池中的线程
+        std::vector<std::tuple<bool,bool>> control_thread;        //控制线程的开闭,true的时候对应的线程处于开启状态
+        
+
+    private:
+        void thread_function(bool& done,bool& situation)             //线程工作函数,done从外部传入用于控制线程数量,状态用于指示线程是否完结
+        {
+            T*  task;
+
+            while(!done)
+            {
+                {
+                    //std::cout<<"a"<<std::endl;
+                    std::unique_lock<std::mutex> ulk(queue_mutex);
+                    task_empty.wait(ulk,[&]{return (bool(tasks.list_size()));});         //如果任务队列为空则阻塞
+                    if(done)
+                    {
+                        break;
+                    }
+                    task=(tasks.pop()->data);                  //从队列中获取函数 
+                    ulk.unlock();
+                }
+                (*task)();
+
+                
+            }
+        }
+
+    public:
+
+        //不允许移动和复制因为受到同步原语的限制,同步原语是不允许移动和复制的
+        basic_thread_pool(basic_thread_pool&)=delete;
+        basic_thread_pool(basic_thread_pool&& others)=delete;
+        basic_thread_pool& operator=(basic_thread_pool others)=delete;
+        basic_thread_pool& operator=(const basic_thread_pool& others)=delete;
+
+    public:
+        basic_thread_pool()
+        {
+            Max_size=std::thread::hardware_concurrency()*2;
+        }
+
+        int init_pool() noexcept
+        {
+            int count;
+            for(int i=0;i<Max_size;i++)
+            {
+                count=0;
+                control_thread.push_back(std::make_tuple(false,true));
+                bool& data_tm_0=std::get<0>(control_thread[0]);
+                bool&data_tm_1=std::get<1>(control_thread[0]);
+                std::thread fun;
+            Loop:
+                
+                try{
+                    fun=std::thread(&basic_thread_pool<T>::thread_function,this,std::ref(data_tm_0),std::ref(data_tm_1));
+                    
+                }
+                catch(...)
+                {
+                    if(count<=5)
+                    {
+                        count++;
+                        goto Loop;
+                    }
+                    else
+                    {
+                        std::cerr<<"thread_build_error"<<std::endl;
+                        control_thread.pop_back();
+                        
+                        return -1;
+                    }
+                }
+                thread_group.push_back(std::move(fun));  
+            }
+            return 1;
+        }
+        int get_size()
+        {
+            return Max_size;
+        }
+        int get_task_size()
+        {
+            return tasks.list_size();
+        }
+        int insert(T&& data)
+        {
+            int flag=0;
+            int mid;
+            {
+                std::unique_lock<std::mutex> lk(queue_mutex);
+                mid=tasks.push(std::move(data));
+
+                if(tasks.list_size()==1)
+                {
+                    flag=1;
+                    
+                }
+            }
+            if(flag==1)
+            {
+                task_empty.notify_all();  
+            }                                       //如果任务队列非空就随机启动一个阻塞线程
+            return  mid;         
+        }
+        void close()
+        {
+            for(int i=0;i<control_thread.size();i++)
+            {
+                std::get<0>(control_thread[i])=true;
+            }
+        }
+
+        int build_more_thread(size_t more=1)         //如果不给出具体参数就赋值为1
+        {
+            Max_size+=more;
+            int count;
+            for(int i=0;i<more;i++)
+            {
+                count=0;
+                control_thread.push_back(std::make_tuple(false,true));
+                bool& data_tm_0=std::get<0>(control_thread[0]);
+                bool&data_tm_1=std::get<1>(control_thread[0]);
+                std::thread fun;
+            Loop:       
+                try{
+                    fun=std::thread(&basic_thread_pool<T>::thread_function,this,std::ref(data_tm_0),std::ref(data_tm_1));
+                    
+                }
+                catch(...)
+                {
+                    if(count<=5)
+                    {
+                        count++;
+                        goto Loop;
+                    }
+                    else
+                    {
+                        std::cerr<<"thread_build_error"<<std::endl;
+                        control_thread.pop_back();                       //如果连续插入失败直接将没有绑定线程的标志位弹出
+                        return -1;
+                    }
+                }
+                thread_group.push_back(std::move(fun));
+            }
+            return 1;
+        }
+
+        void kill_thread(int count=1)
+        {
+            int size=control_thread.size();
+            
+            for(int i=0;i<count;i++)
+            {
+                std::get<0>(control_thread[size-1-i])=false;              //线程,一种惰性关闭,如果线程处于阻塞的状态的时候会在下一轮运行完成后关闭
+                control_thread.pop_back();                                  //从尾部把线程管理弹出
+                thread_group.pop_back();
+
+            }
+        }
+
+
+        ~basic_thread_pool()
+        {
+            int i=thread_group.size();
+            if(i!=0)
+            {
+                for(i-1;i>=0;i--)
+                {
+                    if(thread_group[i].joinable())
+                    {
+                        std::cout<<i<<std::endl;
+                        thread_group[i].join();
+                        
+                    }
+                }
+
+            }
+        }
+    };
+
+
+    template<typename T>
+    struct thread_group          //构建线程组,每个线程组有自己的任务队列,任务使用双向链表的形式,当有需要的时候直接将整个链表全部移走
+    {
+
+    };
+
+
+    template<typename T>
+    class middle_pool                //一个带有任务窃取的线程池
+    {
+    private:
+
+    };
+}
+
+
+#endif

tests/skiplist_test → lib/tests/skiplist_test


tests/skiplist_test.cpp → lib/tests/skiplist_test.cpp


tests/time.h → lib/tests/time.h


BIN
论文/skiplists.pdf