List.h
#include<iostream>
#include<assert.h>
#include<string>
#include"Alloc.h"
#include"Iterator.h"
using namespace std;
//带头结点的双向循环链表--结构的优势->>>>操作都统一
template<class T>
struct __ListNode
{
T _data;
struct __ListNode<T>* _prev;
struct __ListNode<T>* _next;
__ListNode(const T& x)
:_data(x)
,_prev(NULL)
,_next(NULL)
{}
~__ListNode()
{}
};
//T T& T*
//T const T& const T*
template<class T,class Ref,class Ptr>
struct __ListIterator
{
typedef __ListNode<T> Node;
typedef __ListIterator<T, Ref, Ptr> Self;
//
Node* _node;
//
typedef BidirectionalIteratorTag IteratorCategory;
typedef T ValueType;//内置类型
typedef Ptr Pointer;//指针
typedef Ref Reference;//引用
typedef size_t DifferenceType;//距离
__ListIterator(Node* node)
:_node(node)
{}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &(operator*());
}
bool operator==(const Self& s)
{
return _node == s._node;
}
bool operator!=(const Self& s)
{
return _node != s._node;
}
Self operator++()
{
_node = _node->_next;
return *this;
}
Self operator++(int)//后置
{
Self tmp = _node;
_node = _node->_next;
return tmp;
}
Self operator--()
{
_node = _node->_prev;
return *this;
}
Self operator--(int)
{
Self tmp = _node;
_node = _node->_prev;
return tmp;
}
};
template<class T,class Alloc = alloc>
class List
{
typedef struct __ListNode<T> Node;
public:
typedef __ListIterator<T, T&, T*> Iterator;
typedef __ListIterator<T, const T&, const T*> ConstIterator;
typedef ReverseIterator<ConstIterator> ConstReverseIterator;
typedef ReverseIterator<Iterator> ReverseIterator;
typedef SimpleAlloc<Node, Alloc> ListNodeAlloc;
Iterator Begin()
{
return _head->_next;
}
//小心
Iterator End()
{
return _head;
}
ReverseIterator RBegin()
{
return ReverseIterator(End());
}
ReverseIterator REnd()
{
return ReverseIterator(Begin());
}
// const List<int>* this
ConstIterator Begin() const
{
return _head->_next;
}
ConstIterator End() const
{
return _head;
}
//构造 先申请空间 然后赋值
Node* BuyNode(const T& x)
{
Node* node = ListNodeAlloc::Allocate();//分配空间
try
{
new (node) Node(x);// new Node(x);??
}
catch (...)
{
//进来这里说明构造失败
ListNodeAlloc::Deallocate(node);
throw;
}
return node;
}
//析构 先析构 然后回收空间
void DestoryNode(Node* p)
{
p->~Node();
ListNodeAlloc::Deallocate(p);
}
List()
{
_head = BuyNode(T());
_head->_next = _head;
_head->_prev = _head;
}
List(const List<T>& l)//这个只会在初始化的时候用到
{
//_head = new Node(T());
_head = BuyNode(T());
_head->_next = _head;
_head->_prev = _head;
/*
Node* cur = l._head->_next;
while (cur != l._head)
{
PushBack(cur->_data);
cur = cur->_next;
}*/
ConstIterator it = l.Begin();
while (it != l.End())
{
PushBack(*it);
++it;
}
}
~List()
{
Clear();
//delete _head;
DestoryNode(_head);
_head = NULL;
}
void Clear()
{
Iterator it = Begin();
while (it != End())
{
Node* del = it._node;
++it;
//delete del;
DestoryNode(del);
}
_head->_next = _head;
_head->_prev = _head;
}
//好好思考下
List& operator=(List<T> l)
{
if (this != &l)
{
swap(_head, l._head);
}
return *this;
}
void PushBack(const T&x)
{
//Insert(_head,x);
Insert(End(), x);
}
void PushFront(const T&x)
{
//Insert(_head->_next, x);
Insert(Begin(), x);
}
void PopBack()
{
//Erase(_head->_prev);
Erase(--End());
}
void PopFront()
{
//Erase(_head->_next);
Erase(Begin());
}
//void Insert(Node* pos, const T& x)
void Insert(Iterator pos, const T& x)
{
//assert(pos);
在pos 的前面插入
//Node* prev = pos->_prev;
//Node* tmp = new Node(x);
//tmp->_next = pos;
//tmp->_prev = prev;
//prev->_next = tmp;
//pos->_prev = tmp;
Node* cur = pos._node;
Node* prev = cur->_prev;
Node* tmp = BuyNode(x);
prev->_next = tmp;
tmp->_next = cur;
tmp->_prev = prev;
cur->_prev = tmp;
}
//void Erase(Node* pos)
//{
// assert(pos&&pos!=_head);
// Node* prev = pos->_prev;
// Node* next = pos->_next;
// delete pos;
// next->_prev = prev;
// prev->_next = next;
//}
// 防御式 assert + const & -- 保守
// 扩展 -> 即删即用
Iterator Erase(Iterator& pos)
{
assert(pos != End());
Node* prev = (pos._node)->_prev;
Node* next = (pos._node)->_next;
prev->_next = next;
next->_prev = prev;
//delete pos._node;
DestoryNode(pos._node);
pos._node = prev;
//return next;
return Iterator(next);
}
private:
Node* _head;
};
void PrintList(const List<int>& l)
{
List<int>::ConstIterator it = l.Begin(); //const List<int>*
while (it != l.End())
{
cout << *it << " ";
++it;
}
cout << endl;
}
void TestList()
{
List<int> l;
l.PushBack(1);
l.PushBack(2);
l.PushBack(3);
l.PushBack(4);
PrintList(l);
cout << Distance(l.Begin(), l.End()) << endl;
List<int>::ReverseIterator rIt = l.RBegin();
while (rIt != l.REnd())
{
cout << *rIt << " ";
++rIt;
}
cout << endl;
}
int main()
{
TestList();
system("pause");
return 0;
}
Alloc.h
#pragma once
#include<iostream>
#include <stdarg.h>
using namespace std;
#define __DEBUG__
static string GetFileName(const string& path)
{
char ch = '/';
#ifdef _WIN32
ch = '\\';
#endif
size_t pos = path.rfind(ch);
if (pos == string::npos)
return path;
else
return path.substr(pos + 1);
}
// 用于调试追溯的trace log
inline static void __trace_debug(const char* function,
const char * filename, int line, char* format, ...)
{
// 读取配置文件
#ifdef __DEBUG__
// 输出调用函数的信息
fprintf(stdout, "【 %s:%d】%s ", GetFileName(filename).c_str(), line, function);
// 输出用户打的trace信息
va_list args;
va_start(args, format);
vfprintf(stdout, format, args);
va_end(args);
#endif
}
#define __TRACE_DEBUG(...) \
__trace_debug(__FUNCTION__ , __FILE__, __LINE__, __VA_ARGS__);
typedef void(*HANDLE_FUNC)();
template<int inst>
class __MallocAllocTemplate
{
private:
static void* OOM_Malloc(size_t n)
{
void* ret;
while (1)
{
if (__mallocAllocOomHandler == 0)
{
throw bad_alloc();
}
__mallocAllocOomHandler();//期望释放内存
ret = malloc(n);
if (ret)
break;
}
return ret;
}
static HANDLE_FUNC __mallocAllocOomHandler;//句柄函数指针
public:
static void* Allocate(size_t n)
{
__TRACE_DEBUG("到一级空间配置器申请内存.%d\n", n);
void* result = malloc(n);
if (0 == result)
result = OOM_Malloc(n);
return result;
}
static void Deallocate(void* p, size_t /*n*/)
{
free(p);
}
static HANDLE_FUNC SetMallocHandler(HANDLE_FUNC f)
{
HANDLE_FUNC old = __mallocAllocOomHandler;
__mallocAllocOomHandler = f;
return old;
}
};
template<int inst>
HANDLE_FUNC __MallocAllocTemplate<inst>::__mallocAllocOomHandler = 0;
/
template<bool threads, int inst>
class __DefaultAllocTemplate {
public:
static size_t FREELIST_INDEX(size_t bytes)//求出对应下标
{
return (((bytes)+__ALIGN-1)/ __ALIGN - 1);
//(X +7)/8 -1;
}
static size_t ROUND_UP(size_t bytes)//非8倍数的整数上调到8的倍数
{
return (((bytes)+__ALIGN - 1)&~(__ALIGN - 1));
}
static char* ChunkAlloc(size_t n, size_t& nobjs)//想内存池去要
{
size_t totalBytes = n*nobjs;
size_t leftBytes = _endFree - _startFree;
__TRACE_DEBUG("需要%d bytes, 狭义内存池有多少%dbytes\n", totalBytes, leftBytes);
if (leftBytes >= totalBytes)
{
char* ret = _startFree;
_startFree += totalBytes;
return ret;
}
else if (leftBytes > n)//够至少一个
{
nobjs = leftBytes / n;
totalBytes = nobjs*n;
char* ret = _startFree;
_startFree += totalBytes;
return ret;
}
else
{
//处理剩余内存
if (leftBytes > 0)
{
size_t index = FREELIST_INDEX(leftBytes);
//头插
((Obj*)_startFree)->_freeListLink = _freeList[index];
_freeList[index] = (Obj*)_startFree;
}
size_t bytesToGet = totalBytes * 2 + ROUND_UP(_heapSize);
_startFree = (char*)malloc(bytesToGet);
__TRACE_DEBUG("向系统申请%dbytes\n", bytesToGet);
if (_startFree == NULL)
{
//尝试去更大的自由链表中去找
for (size_t i = FREELIST_INDEX(n); i < __NFREELISTS; i++)
{
if (_freeList[i])
{
Obj* obj = _freeList[i];
_freeList[i] = obj->_freeListLink;
_startFree = (char*)obj;
_endFree = _startFree + (i + 1)*__ALIGN;
//回调自己,为了修正nobjs
return ChunkAlloc(n, nobjs);
}
}
_endFree = 0;//出现意外,到处都没内存可用了
//调用第一级配置器,看看out-of-memory机制能否尽力
_startFree = (char*)__MallocAllocTemplate<0>::Allocate(bytesToGet);
//结果是抛出异常或者内存不足情况得到改善
}
_heapSize += bytesToGet;
_endFree = _startFree + bytesToGet;
return ChunkAlloc(n, nobjs);
}
}
static void* Refill(size_t n)//扩充某个链表中节点下的空间
{
size_t nobjs = 20;
char* chunk = ChunkAlloc(n, nobjs);
__TRACE_DEBUG("在狭义内存池申请到%d个对象,返回一个,挂%d个到自由链表\n", nobjs, nobjs - 1);
if (nobjs == 1)
return chunk;
size_t index = FREELIST_INDEX(n);
Obj* cur = (Obj*)(chunk + n);
_freeList[index] = cur;
for (size_t i = 0; i < nobjs - 2; i++)
{
Obj* next = (Obj*)((char*)cur + n);
cur->_freeListLink = next;
cur = next;
}
cur->_freeListLink = NULL;
return chunk;
}
static void* Allocate(size_t n)
{
if (n > __MAX_BYTES)
{
return __MallocAllocTemplate<0>::Allocate(n);
}
size_t index = FREELIST_INDEX(n);
Obj* first = _freeList[index];
if (first == NULL)
{
__TRACE_DEBUG("freeList[%d]下面没有挂对象,到狭义内存池进行申请\n", index);
return Refill(ROUND_UP(n));
}
else
{
__TRACE_DEBUG("freeList[%d]下面有对象,取一个内存对象返回\n", index);
_freeList[index] = first->_freeListLink;
return first;
}
}
static void Deallocate(void* p,size_t n)
{
if (n > __MAX_BYTES)
{
__MallocAllocTemplate<0>::Deallocate(p, n);
return;
}
size_t index = FREELIST_INDEX(n);
//头插
Obj* obj = (Obj*)p; //*************/ Node*------->Obj* 还有_freeListLink存下一个 注意这个size 也就是8 16 24 是个突破点
obj->_freeListLink = _freeList[index];
_freeList[index] = obj;
}
private:
enum { __ALIGN = 8 };
enum { __MAX_BYTES = 128 };
enum { __NFREELISTS = __MAX_BYTES / __ALIGN };
union Obj
{
union Obj* _freeListLink;
char client_data[1]; /* The client sees this. */
};
// 自由链表--管理内存块
static Obj* _freeList[__NFREELISTS];
// 内存池--狭义
static char* _startFree;
static char* _endFree;
static size_t _heapSize; // 反馈调节 -- 内存池已经向系统省内请的内存大小
};
template<bool threads, int inst>
typename __DefaultAllocTemplate<threads, inst>::Obj*
__DefaultAllocTemplate<threads, inst>::_freeList[] = { 0 };
template<bool threads, int inst>
char* __DefaultAllocTemplate<threads, inst>::_startFree = 0;
template<bool threads, int inst>
char* __DefaultAllocTemplate<threads, inst>::_endFree = 0;
template<bool threads, int inst>
size_t __DefaultAllocTemplate<threads, inst>::_heapSize = 0;
# ifdef __USE_MALLOC
typedef __MallocAllocTemplate<0> alloc;
#else
typedef __DefaultAllocTemplate<false, 0> alloc;
#endif
template<class T, class Alloc>
class SimpleAlloc
{
public:
static T* Allocate(size_t n)
{
return 0 == n ? 0 : (T*)Alloc::Allocate(n * sizeof(T));
}
static T* Allocate(void)
{
return (T*)Alloc::Allocate(sizeof(T));
}
static void Deallocate(T *p, size_t n)
{
if (0 != n)
Alloc::Deallocate(p, n * sizeof(T));
}
static void Deallocate(T *p)
{
Alloc::Deallocate(p, sizeof(T));
}
};
Iterator.h
#pragma once
//
// 迭代器的型别
//
struct InputIteratorTag {};
struct OutputIteratorTag {};
struct ForwardIteratorTag : public InputIteratorTag {};
struct BidirectionalIteratorTag : public ForwardIteratorTag {};
struct RandomAccessIteratorTag : public BidirectionalIteratorTag {};
//
// Traits 就像一台“特性萃取机”,榨取各个迭代器的特性(对应的型别)
//
template <class Iterator>
struct IteratorTraits
{
typedef typename Iterator::IteratorCategory IteratorCategory;
typedef typename Iterator::ValueType ValueType;
typedef typename Iterator::DifferenceType DifferenceType;
typedef typename Iterator::Pointer Pointer;
typedef typename Iterator::Reference Reference;
};
//特化版本
template <class T>
struct IteratorTraits<T*>
{
typedef RandomAccessIteratorTag IteratorCategory;
typedef T ValueType;
typedef size_t DifferenceType;
typedef T* Pointer;
typedef T& Reference;
};
template <class T>
struct IteratorTraits<const T*>
{
typedef RandomAccessIteratorTag IteratorCategory;
typedef T ValueType;
typedef size_t DifferenceType;
typedef const T* Pointer;
typedef const T& Reference;
};
// O(N)
template<class Iterator>
size_t __Distance(Iterator first, Iterator last, InputIteratorTag)
{
size_t n = 0;
while (first != last)
{
++first;
++n;
}
return n;
}
// O(1)
template<class Iterator>
size_t __Distance(Iterator first, Iterator last, RandomAccessIteratorTag)
{
return last - first;
}
template<class Iterator>
size_t Distance(Iterator first, Iterator last)
{
//return __Distance(first, last, Iterator::IteratorCategory());
//萃取器
return __Distance(first, last, IteratorTraits<Iterator>::IteratorCategory());
}
// 适配器
template<class Iterator>
struct ReverseIterator
{
typedef ReverseIterator<Iterator> Self;
Iterator _it;
explicit ReverseIterator(Iterator it)
:_it(it)
{}
//通过萃取器 取出对应的型别 在迭代器内部本身也有声明 (所以都用typename)
typename IteratorTraits<Iterator>::Reference operator*()
{
//return *_it;
Iterator tmp = _it;
return *(--tmp);
}
typename IteratorTraits<Iterator>::Pointer operator->()
{
return &(operator*());
}
Self& operator++()
{
--_it;
return *this;
}
Self& operator--()
{
++_it;
return *this;
}
bool operator==(const Self& s)
{
return _it == s._it;
}
bool operator!=(const Self& s)
{
return _it != s._it;
}
};
关于空间配置器十个问题
一、一二级配置器开放准则是什么?
整个设计究竟只开放第一级配置器,或是同时开放第二级配置器,取决于__USE_MALLOC是否被定义
二、什么是内碎片和外碎片?
操作系统频繁分配内存和回收内存的时候。这些6M,4M的小内存无法利用造成了外部碎片。
自由链表所挂区块都是8的整数倍,因此当我们需要非8倍数的区块,往往会导致浪费,比如我只要1字节的大小,但是自由链表最低分配8块,也就是浪费了7字节,这7字节就是内碎片
三、为什么引入复杂的两级空间配置器?
1. 频繁使用malloc,free开辟释放小块内存带来的性能效率的低下
2. 内存碎片问题,导致不连续内存不可用的浪费
四、为什么所有成员函数都是静态的?
是为了在外面通过作用域就可以调用,而不需要构造对象
五、typename有什么作用?
这个关键字用于指出模板声明(或定义)中的非独立名称(dependent names)是类型名,而非变量名。
六、ROUNT_UP的实现原理是什么?
static
size_t ROUND_UP(size_t bytes)//作用是将非8倍数的整数上调到8的倍数。
{
{
return
(((bytes)+__ALIGN - 1) &~(__ALIGN - 1));
}
round_up实现原理:
以 bytes = 30为例:
a. (30 + 7) = 37, 可以知道30的round_up为32, 给32加(8-1)的目的是让其(一定)大于32
b. 这样的话,以十进制形式,37肯定可以表达为如下的形式:(x*8 + y), 并且可以肯定这个y的值小于8,上述37表达形式为:(32 + 5)
c. 根据上述b步骤的形式,我们很自然的明白, 只要将 ((bytes) + 8-1) 转换为(x*8 + y)的形式后,然后再将y的值减去就达到目的了
d. 总结上述思路,我们要做事情有两个,一是将 ((bytes) + 8-1) 转换为 (x*8 + y)的形式; 二是将(x*8 + y)中的y值清零
e. 在十进制下,要完成上述任务,比较困难,而在二进制下,就非常好办
f. 首先,将 ((bytes) + 8-1) 转换为(x*8 + y), 只要将 ((bytes) + 8-1)的值转为二进制,如以37为例,其二进制为: 00100101,这样写你可能看得还不是很直观,这样写 (00100) (101), 这样就可以发现,第一个小括号里面的值就为(x*8), 第二个小括号里面的值就为(y);
接下来,我们的目的就很简单的, 将第二个小括号里面的所有位置为0即可, 参考上述网页中的规则“非运算和与运算结合,可以确保将指定位 清0, 故 & ~(__ALIGN - 1)的目的就是将第二个小括号中的位清0.
至此, 问题圆满解决。
七、引入两层配置器带来什么问题?
1.内存碎片
2.我们发现似乎没有释放自由链表所挂区块的函数?确实是的,由于配置器的所有方法,成员都是静态的,那么他们就是存放在静态区。释放时机就是程序结束,这样子会导致自由链表一直占用内存,自己进程可以用,其他进程却用不了