#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
buddy system
最新推荐文章于 2018-12-17 18:57:39 发布