0% found this document useful (0 votes)
185 views6 pages

Sample

The document implements queue operations including create, destroy, enqueue, and dequeue using a fixed-size 2048 byte data array. It defines data structures for the queue header, blocks, and overall header to manage the available memory. Functions are provided to initialize the memory, allocate and free blocks, create and destroy queues, and perform enqueue and dequeue operations on the queues.

Uploaded by

api-316663272
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
185 views6 pages

Sample

The document implements queue operations including create, destroy, enqueue, and dequeue using a fixed-size 2048 byte data array. It defines data structures for the queue header, blocks, and overall header to manage the available memory. Functions are provided to initialize the memory, allocate and free blocks, create and destroy queues, and perform enqueue and dequeue operations on the queues.

Uploaded by

api-316663272
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 6

//author: Jiawei Gu

//email: [email protected]
/*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");

//}

You might also like