首页 > 学院 > 开发设计 > 正文

buddy system

2019-11-08 01:47:24
字体:
来源:转载
供稿:网友
#ifndef PUBLIC_UTILITY#define PUBLIC_UTILITY#include <stdio.h>#include <sys/sysinfo.h>#include <vector>#include <algorithm>namespace publicutility{using namespace std;class PublicUtility{public:	/*	 * @brief adjust odd elements to locate before even elements	 * */	static void Odd_before_Even(vector<int>&);	/*	 * @brief judge wheter a number is odd	 * */	inline static bool IsOdd(int num) 	{		return num & 1;	}	/*	 * @brief judge whether the num is to pwoer like 2 4 8 16 ...	 * */	inline static bool ToPower(size_t num)	{		return 0 == (num & (num -1));	}	/*	 * @brief get the free random	 * @return K free memory 	 * */	inline static unsigned long GetFreeRam() 	{		struct sysinfo s_info;		if(sysinfo(&s_info)) return 0;				return s_info.freeram;	}	/*	 * @brief fix the number to the minimal to power number such as num = 3 then return 4 num = 67 return 128	 * */	inline static unsigned FixToPower(unsigned num)	{		if(ToPower(num)) return num;		num |= (num >> 1);					// make top 2 bit to be 1 11xx xxxx xxxx xxxx xxxx xxxx xxxx xxxx		num |= (num >> 2);					// make top 4 bit to be 1 1111 xxxx xxxx xxxx xxxx xxxx xxxx xxxx		num |= (num >> 4);					// make top 8 bit to be 1 1111 1111 xxxx xxxx xxxx xxxx xxxx xxxx		num |= (num >> 8);					// make top 16 bit to be 1 1111 1111 1111 1111 xxxx xxxx xxxx xxxx		num |= (num >> 16);					// make top 32 bit to be 1 1111 1111 1111 1111 1111 1111 1111 1111		return num + 1;	}};}#endif#include "PublicUtility.h"namespace publicutility{/* * @brief adjust odd elements to locate before even elements * */void PublicUtility::Odd_before_Even(vector<int>&v){	int nlow = 0;	int nhigh = v.size() - 1;	bool blow_is_odd = false;	bool bhigh_is_odd = false;	bool blow_is_change = true;	bool bhigh_is_change = true;	while(nlow < nhigh)	{		if(blow_is_change)		{			blow_is_odd = IsOdd(v[nlow]);			blow_is_change = false;		}		if(bhigh_is_change)		{			bhigh_is_odd = IsOdd(v[nhigh]);			bhigh_is_change = false;		}		if(!blow_is_odd && bhigh_is_odd)		{			swap(v[nlow++], v[nhigh--]);			blow_is_change = true;			bhigh_is_change = true;		}		else		if(!blow_is_odd && !bhigh_is_odd)		{			nhigh--;			bhigh_is_change = true;		}		else		if(blow_is_odd && bhigh_is_odd)		{			nlow++;			blow_is_change = true;		}		else		{			nlow++;			nhigh--;			blow_is_change = true;			bhigh_is_change = true;		}	}}}/****************************************************************************@File Name: buddysystem.h@Author: wangzhicheng@mail: 2363702560@QQ.com@Created Time: Wed 15 Feb 2017 01:54:36 PM CST			   2017-02-20****************************************************************************/#ifndef BUDDY_SYSTEM_H#define BUDDY_SYSTEM_H#include <stdio.h>#include <string.h>#include <iostream>#include <vector>#include <mutex>#include <algorithm>#include "PublicUtility.h"namespace buddysystem{using namespace publicutility;class FreeException{public:	FreeException()	{		fPRintf(stderr, "free exception...!/n");	}};class BuddySystem{private:	unsigned m_nCapacity;				// total memory 	vector<unsigned>m_vecTree;			// full binary tree for storing each memory block	void *m_pBasePtr;					// pointer to a memory zone	mutex m_gmutex;private:	/*	 * @brief get the current node of parent	 * */	inline int Parent(int current)	{		return (current - 1) >> 1;	}	/*	 * @brief get the current index of lchild	 * */	inline int Lchild(int current)	{		return (current << 1) + 1;	}	/*	 * @brief get the current index of rchild	 * */	inline int Rchild(int current)	{		return (current << 1) + 2;	}public:	BuddySystem():m_pBasePtr(0)	{	}	~BuddySystem()	{		if(m_pBasePtr)		{			free(m_pBasePtr);	//		m_pBasePtr = 0;		}	}	/*	 * @brief initialize the buddy system	 * @cap the memory capacity unit:Byte	 * @return true if init ok	 * */	bool Init(unsigned cap);	/*	 * @brief cout the tree sequently	 * */	void ShowTree() const;	/*	 * @brief allocate the memory	 * @size memory size(uint:byte)	 * @return the starting allocated memory address	 * */	void *Alloc(unsigned size);	/*	 * @brief free the memory	 * @ptr pointer to the starting memory address 	 * */	void Free(void *ptr);};}#endif/****************************************************************************@File Name: buddysystem.cpp@Author: wangzhicheng@mail: 2363702560@qq.com@Created Time: Wed 15 Feb 2017 01:54:36 PM CST			   2017-02-17****************************************************************************/#include "buddysystem.h"namespace buddysystem{/* * @brief initialize the buddy system * @cap the memory capacity unit:Byte * @return true if init ok * */bool BuddySystem::Init(unsigned cap){	// check the cap	if(!PublicUtility::ToPower(cap)) 	{		cap = PublicUtility::FixToPower(cap);	}	if(cap >= PublicUtility::GetFreeRam()) return false;	m_nCapacity = cap;	m_pBasePtr = malloc(m_nCapacity);	if(!m_pBasePtr) return false;	unsigned n = (m_nCapacity << 1) - 1;		// n is the count of nodes in the full tree	int parent;	m_vecTree.resize(n);	// fill the tree	m_vecTree[0] = m_nCapacity;	for(int i = 1;i < n;i++)	{		parent = Parent(i);		m_vecTree[i] = m_vecTree[parent] >> 1;	}	return true;}/* * @brief cout the tree sequently * */void BuddySystem::ShowTree() const{	for_each(begin(m_vecTree), end(m_vecTree), [](unsigned size)	{		cout << size << endl;	});}/* * @brief allocate the memory * @size memory size(uint:byte) * @return the starting allocated memory address * */void *BuddySystem::Alloc(unsigned size){	if(!m_pBasePtr) return 0;	int index = 0;	unsigned node_size;	unsigned offset;	size = PublicUtility::FixToPower(size);	// lock lockguard	lock_guard<mutex>lockguard(m_gmutex); 	// search the fit memory block	if(m_vecTree[0] < size) return 0;	for(node_size = m_nCapacity;node_size != size;node_size >>= 1)	{		if(m_vecTree[Lchild(index)] >= size) 		{			index = Lchild(index);		}		else		{			index = Rchild(index);		}	}	m_vecTree[index] = 0;	offset = (index + 1) * node_size - m_nCapacity;	// adjust the tree	while(index)	{		index = Parent(index);		m_vecTree[index] = max(m_vecTree[Lchild(index)], m_vecTree[Rchild(index)]);	}	return (void *)((char *)m_pBasePtr + offset);}/* * @brief free the memory * @ptr pointer to the starting memory address  * */void BuddySystem::Free(void *ptr){	int index;	unsigned node_size = 1;	unsigned offset;	unsigned lsize;	unsigned rsize;	if(!m_pBasePtr) return;	offset = (char *)ptr - (char *)m_pBasePtr;			// get the offset	pointer to the memory buffer position	if(offset >= m_nCapacity) throw FreeException();	// check the offset	index = offset + m_nCapacity - 1;					// get the index pointer to the tree position	// lock	lock_guard<mutex>lockguard(m_gmutex); 	for(;m_vecTree[index];index = Parent(index)) 	{		node_size <<= 1;		if(!index) return;	}	m_vecTree[index] = node_size;	// update parent nodes	while(index) 	{		index = Parent(index);		node_size <<= 1;		lsize = m_vecTree[Lchild(index)];		rsize = m_vecTree[Rchild(index)];		if(lsize + rsize == node_size) 		{ 			m_vecTree[index] = node_size;		}		else		{ 			m_vecTree[index] = max(lsize, rsize);		}	}}}/****************************************************************************@File Name: test.cpp@Author: wangzhicheng@mail: 2363702560@qq.com@Created Time: Sat 28 Jan 2017 09:25:55 PM CST@Revision Time:2017-02-17****************************************************************************/#include "buddysystem.h"#include <thread>using namespace buddysystem;void fun0(BuddySystem &bs){	int *p = (int *)bs.Alloc(sizeof(int));	if(p) 	{		*p = 18;		cout << *p << endl;		bs.Free(p);	}}void fun1(BuddySystem &bs){	char *ptr = (char *)bs.Alloc(256);	if(ptr)	{		strcpy(ptr, "hello world...!/n");		cout << ptr << endl;		bs.Free(ptr);	}}int main(){	BuddySystem bs;	cout << bs.Init(1024) << endl;	/*	int *p = (int *)bs.Alloc(sizeof(int));	if(p) 	{		*p = 18;		cout << *p << endl;	}	char *ptr = (char *)bs.Alloc(256);	if(ptr)	{		strcpy(ptr, "hello world...!/n");		cout << ptr << endl;	}*/	thread t0(fun0, ref(bs));	thread t1(fun1, ref(bs));	t0.join();	t1.join();	return 0;}CC=g++all:	$(CC) -std=c++11 -g -o test test.cpp PublicUtility.h PublicUtility.cpp buddysystem.cpp buddysystem.h
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表