Você está na página 1de 6

//author: Jiawei Gu

//email: jiawei.gu777@gmail.com
/*problem:
Only given 2048 bytes, implement queue operation including create/destro
y/enqueue/dequeue.
There are various number of queues with various size.
*/
#include <iostream> //for on_out_of_memory() and on_illegal_operation() to print
stuff
namespace Sample
{
unsigned char data[2048] = { };
//VERY IMPORTANT!!
//Initialize() must be called to setup the data layout before doing anyt
hing to the data.
/*
data layout
Size

|Accumulated Memory

|Use
----------------------------|-------------------|-------------------8 bytes
|8 bytes
|Head
64 * 4 bytes = 256 bytes
e Header
223 * 8 bytes = 1784 bytes
a Blocks
*/

|264 bytes

|64 Queu

|2048 bytes

|223 Dat

struct Head
{
//total 8 bytes
unsigned char freeBlockHead;

//the index to the first free bl

unsigned char freeQueueHead;

//the index to the first free qu

ock
eue
unsigned char queueNum;

//queue number is given

unsigned char blockNum;

//block number is calcul

64
ated 223
unsigned char unusedByte[4];
};
struct Q
{
//total 32 bits = 4 bytes
unsigned char next : 8;
64 queues and NULL need 7 bits; 8 bits for wrapping

//next free queue index;

unsigned char headOffset : 4; //head block data offset; each b


lock has 8 bytes, 3 bits to represent; 4 bits for wrapping
unsigned char tailOffset : 4; //tail block data offset
unsigned char headBlock : 8;
eeds 8 bits to represent
unsigned char tailBlock : 8;

//head block index; 223 blocks n


//tail block index

};
struct Block
{
//total 8 bytes
unsigned char next;
linked to this one
unsigned char data[7];
};

//the next block


//real data storage

//Function to get the head as a pointer


Head * GetHead()
{
return reinterpret_cast<Head *>(data);
}
//Function to get the queue header as a pointer
Q * GetQueue(unsigned char index)
{
return reinterpret_cast<Q *>(
data
//origin
memory address
+ 8
//head
+ sizeof(Q) * (index - 1));
//queue index starts at
1; 0 is reserved to represent NULL
}
//Function to get the block as a pointer
Block * GetBlock(unsigned char index)
{
return reinterpret_cast<Block *>(
data
//origin memory address
+ 8
//head
+ sizeof(Q) * 64
//queue
headers
+ sizeof(Block) * (index - 1)); //the block index starts
at 1; 0 is reserved to represent NULL
}
//error handle function provided
void on_out_of_memory()
{
printf("Out of memory!\n");
//Should do something else
system("pause");
}
//error handle function provided
void on_illegal_operation()
{
printf("Illegal operation!\n");
//Should do something else
system("pause");
}
//Initialize the 2048 data array
void Initialize()

{
Head * head = GetHead();
head->freeBlockHead = 1;
head->freeQueueHead = 1;
head->queueNum = 64;
head->blockNum = 223;

//free block start at 1


//free queue start at 1
//64 queues
//223 blocks, can be calculated

//Link the queue headers


for (unsigned char i = 1; i <= head->queueNum; ++i)
{
GetQueue(i)->next = i + 1;
}
GetQueue(head->queueNum)->next = 0; //last one to a NULL
//Link the blocks
for (unsigned char i = 1; i <= head->queueNum; ++i)
{
GetBlock(i)->next = i + 1;
}
GetBlock(head->queueNum)->next = 0; //last one to a NULL
}
//Return a free block index
unsigned char AllocateBlock()
{
Head * head = GetHead();
//Check if free block head is pointing to NULL, which means no m
ore free block
if (head->freeBlockHead == 0)
on_out_of_memory();
//Get the free block index
unsigned char blockIndex = head->freeBlockHead;
//Link the head to the next free block
head->freeBlockHead = GetBlock(head->freeBlockHead)->next;
//Detach the allocated block to the list
GetBlock(blockIndex)->next = 0;
return blockIndex;
}
//Free blocks from the start block to the end block
//The queue is designed to always have the start and the end linked thro
ugh a chain
//So we don't need to worry about the blocks in between
void FreeBlocks(unsigned char start, unsigned char end)
{
Head * head = GetHead();
//Get the next block from the head
unsigned char next = GetBlock(head->freeBlockHead)->next;
//insert the block chain at the head
head->freeBlockHead = start;
GetBlock(end)->next = next;
}

// Creates a FIFO byte queue, returning a handle to it.


Q * create_queue()
{
Head * head = GetHead();
//Check if free queue head is pointing to NULL, which means a 65
th queue is being created
if (head->freeQueueHead == 0)
on_illegal_operation();
//Take the first node off the free queue list
unsigned char queueIndex = head->freeQueueHead;
head->freeQueueHead = GetBlock(head->freeQueueHead)->next;
//Intialize the queue with a new block
Q * q = GetQueue(queueIndex);
unsigned char blockIndex = AllocateBlock();
q->headBlock = blockIndex;
q->headOffset = 0;
q->tailBlock = blockIndex;
q->tailOffset = 0;
return q;
}
// Destroy an earlier created byte queue.
void destroy_queue(Q * q)
{
Head * head = GetHead();
//Free the blocks into use
FreeBlocks(q->headBlock, q->tailBlock);
//Free the queue header into use; attach it to the free queue li
st
q->next = GetQueue(head->freeQueueHead)->next;
//The current q's index can be calculated through the address
head->freeQueueHead = ((reinterpret_cast<unsigned char *>(q) - (
data + 8)) / sizeof(Q));
}
// Adds a new byte to a queue.
void enqueue_byte(Q * q, unsigned char b)
{
//Store the byte
GetBlock(q->tailBlock)->data[q->tailOffset] = b;
//Increase the tail
++q->tailOffset;
//Checking out of index
//data is using 0-6 for indexing; if it's 7, a new block is requ
ired
if (q->tailOffset == 7)
{
unsigned char newBlock = AllocateBlock();
//Link this new block
GetBlock(q->tailBlock)->next = newBlock;
//Point to the new block
q->tailBlock = newBlock;
q->tailOffset = 0;

}
}
// Pops the next byte off the FIFO queue
unsigned char dequeue_byte(Q * q)
{
//if head and tail are pointing the same position, it means the
queue is empty
if (q->headBlock == q->tailBlock && q->headOffset == q->tailOffs
et)
on_illegal_operation();
//Get the byte
unsigned char r = GetBlock(q->headBlock)->data[q->headOffset];
//Increase the head
++q->headOffset;
//Checking out of index
//data is using 0-6 for indexing; if it's 7, the head block shou
ld be freed
if (q->headOffset == 7)
{
Head * head = GetHead();
unsigned char freeBlock = q->headBlock;
//Goes to the next block
q->headBlock = GetBlock(q->headBlock)->next;
q->headOffset = 0;
//Free the block
FreeBlocks(freeBlock, freeBlock);
}
return r;
}
}
//A simple drive, uncomment if needed
//using namespace Sample;
//void main()
//{
//
Initialize();
//
//
Q * q0 = create_queue();
//
enqueue_byte(q0, 0);
//
enqueue_byte(q0, 1);
//
Q * q1 = create_queue();
//
enqueue_byte(q1, 3);
//
enqueue_byte(q0, 2);
//
enqueue_byte(q1, 4);
//
printf("%d", dequeue_byte(q0));
//
printf("%d\n", dequeue_byte(q0));
//
enqueue_byte(q0, 5);
//
enqueue_byte(q1, 6);
//
printf("%d", dequeue_byte(q0));
//
printf("%d\n", dequeue_byte(q0));
//
destroy_queue(q0);
//
printf("%d", dequeue_byte(q1));
//
printf("%d", dequeue_byte(q1));
//
printf("%d\n", dequeue_byte(q1));
//
destroy_queue(q1);
//
//
system("pause");

//}

Você também pode gostar