堆栈元素为一个无符字符数组(即字节数组)。堆栈中只存放该数组的地址。这个地址指向一个存储区域,该存储区的结构为:
_______________________________________________
|数组长度(4B)|数组内容(由前面的长度决定长度)|
---------------------------------------------------------------
这个堆栈支持多线程同步操作,对堆栈的元素改动时,有互斥锁mutex防止不同步。
工作环境:
linux 9.0
编译:
g++ BytesStack.cpp main.cpp -o main -lpthread
下面是代码部分:
俩个main.cpp函数,前一个为一般单线程应用。后一个为多线程应用。
/*
BytesStack.h
zhangggdlt
2004/11/15
to realize a stack storing bytes array.
*/
#ifndef _BYTES_STACK_H
#define _BYTES_STACK_H
#include <pthread.h>
#include <unistd.h>
#define OPERATION_OK 0
#define STACK_FULL -1
#define STACK_EMPTY -2
#define INCREASE_FAILED -3
#define NO_AREA -4
#define POINT_NULL -5
#define FAILED_LOCK -6
typedef int ERR_NUMBER;
typedef unsigned char uint_8;
/*
The class BytesStack is used to realize store an unsigned char array into the stack which
sustain mutiple thread and sycronization.
The size of the queue can be set when it is constructed and you
can also increas the size of the queue during the application.
*/
class BytesStack
{
private:
int _size;
int _top;
int _bottom;
uint_8 **_buffer;
pthread_mutex_t StaMutex;
public:
BytesStack(int size=512);
ERR_NUMBER increaseSize(int size=512);
ERR_NUMBER push(const uint_8 *data, int len);
ERR_NUMBER pop(uint_8 *data, int &len);
void destroy();
void errMessage(ERR_NUMBER err);
void showBytesStack(BytesStack& bs);
};
#endif //_BYTESSTACK_H
——————————————————————————————
/*
BytesStack.cpp
zhangggdlt
2004/11/15
to realize a stack storing bytes array which sustain the mutitread and sycronization.
*/
#include <stdio.h>
#include <string.h>
#include "BytesStack.h"
/*
The constructor.
This BytesStack can sustain sycronization among the mutiThread.
It means you can use this data structure under mutithread.
*/
BytesStack::BytesStack(int size) //size=10
{
this->_size = size;
this->_buffer = new (uint_8*)[this->_size];
this->_top = 0;
this->_bottom = 0;
pthread_mutex_init(&StaMutex, NULL);
}
/*
You can use this number fuction to increase the size of the stack.
The data will not be lost during the increasement.
*/
ERR_NUMBER BytesStack::increaseSize(int size)
{
uint_8 **temp;
int i;
this->_size += size;
if(!(temp = new (uint_8*)[this->_size]))
return INCREASE_FAILED;
for (i=0; i<this->_top; i++)
{
temp[i] = this->_buffer[i];
}
delete []this->_buffer;
this->_buffer = temp;
return OPERATION_OK;
}
/*
This function is use to accept one element into the stack.
You must remember the element is a unsigned char array.
Len is the length of the data.
*/
ERR_NUMBER BytesStack::push(const uint_8 *data, int len)
{
uint_8 *temp;
if (this->_top >= this->_size)
{
printf("The stack is full!\n");
return STACK_FULL;
}
if (!( temp= new uint_8[len + 4]))
return NO_AREA;
if (pthread_mutex_trylock(&StaMutex))
{
printf("Try lock failed!\n");
return FAILED_LOCK;
}
this->_buffer[this->_top] = temp;
memcpy(this->_buffer[this->_top], &len, 4);
memcpy(this->_buffer[this->_top]+4, data, len);
this->_top++;
pthread_mutex_unlock(&StaMutex);
return OPERATION_OK;
}
/*
This function is use to set free one element from the stack.
You must get a buffer big enough to store the data before you call the function.
At the same time you need a more int &len to get the data length.
*/
ERR_NUMBER BytesStack::pop(uint_8 *data, int &len)
{
if(!data)
return POINT_NULL;
if(this->_top <= this->_bottom)
{
printf("The stack is empty!\n");
return STACK_EMPTY;
}
if (pthread_mutex_trylock(&StaMutex))
{
printf("Try lock failed!\n");
return FAILED_LOCK;
}
this->_top--;
memcpy((void*)&len, this->_buffer[this->_top], 4);
memcpy((void*)data, this->_buffer[this->_top]+4, len);
pthread_mutex_unlock(&StaMutex);
return OPERATION_OK;
}
/*
This function is use to set free the data structure.
*/
void BytesStack::destroy()
{
while (this->_top > this->_bottom)
{
delete [](this->_buffer[--(this->_top)]);
}
delete [](this->_buffer);
this->_size = 0;
this->_buffer = NULL;
}
/*
This fuction is use to test.
Show the result of the call fuction.
*/
void BytesStack::errMessage(ERR_NUMBER err)
{
switch(err)
{
case OPERATION_OK:
printf(" push is ok!\n");
break;
case STACK_FULL:
printf(" push failed! The stack is full!!\n");
break;
case STACK_EMPTY:
printf(" pop failed! The stack is empty!!\n");
break;
case INCREASE_FAILED:
printf(" increase stack size failed! \n");
break;
default:
printf(" other things are wrong! \n");
break;
}
}
/*
This fuction is used to show the infomation of the current queue.
*/
void BytesStack::showBytesStack(BytesStack& bs)
{
printf(" %s\n", "The info of the BytesStack is :");
printf(" size : %d\n", bs._size);
printf(" top : %d\n", bs._top);
printf(" bottom : %d\n", bs._bottom);
printf(" buf addr: 0x%x\n", bs._buffer);
}
/*
using namespace NetworkProtocols;
//this is a good example to show how to use the data structure BytesQueue.
int main()
{
int len,i;
char ch;
ERR_NUMBER err;
uint_8 bufi[]={1,2,3,4,5,6,7,8,9,0};
uint_8 bufo[10];
BytesStack bs;
bs.showBytesStack(bs);
ch = getchar();
while(ch != 'q')
{
switch(ch)
{
case 'i':
err = bs.push(bufi, 10);
bs.errMessage(err);
bs.showBytesStack(bs);
ch = getchar();
break;
case 'o':
err = bs.pop(bufo, len);
bs.errMessage(err);
bs.showBytesStack(bs);
ch = getchar();
break;
case 'e':
err = bs.increaseSize();
bs.errMessage(err);
bs.showBytesStack(bs);
ch = getchar();
break;
case 'h':
printf("....................Help................\n");
printf(" i: push an array into stack.\n");
printf(" o: pop an array out of the satack.\n");
printf(" e: enlarge the size of the stack.\n");
printf(" h: help\n");
printf(" q: quit the system.\n");
ch = getchar();
break;
default:
if (ch != '\n')
printf("...........Your input is wrong! Again!..............\n");
ch = getchar();
break;
}
}
bs.destroy();
bs.showBytesStack(bs);
return 0;
}
*/
——————————————————————————————
//main.cpp
#include <stdio.h>
#include "BytesStack.h"
typedef struct
{
int id;
BytesStack *bs;
uint_8 *buf;
int len;
int delay;
}MyParameter;
pthread_t threads[5];
pthread_mutex_t QueMutex;
pthread_attr_t attr;
void *Push(void* pvar)
{
int i = 1;
MyParameter *para = (MyParameter*)pvar;
while( i )
{
printf("Thread inQue: %d is working! \n", para->id);
//para->bq->inQueue(para->buf, para->len);
//para->bq->showBytesQueue(*(para->bq));
para->bs->push(para->buf,para->len);
para->bs->showBytesStack(*(para->bs));
usleep(para->delay);
i ++;
}
pthread_exit(NULL);
}
void *Pop(void* pvar)
{
int i = 1;
MyParameter *para = (MyParameter*)pvar;
while( i )
{
printf("-------------Thread outQue: %d is working! \n", para->id);
//para->bq->outQueue(para->buf, para->len);
//para->bq->showBytesQueue(*(para->bq));
para->bs->pop(para->buf,para->len);
para->bs->showBytesStack(*(para->bs));
usleep(para->delay);
i ++;
}
pthread_exit(NULL);
}
int main()
{
//IpStack::IpStack(int size) //size=10
uint_8 mybuf1[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x50,
0x58, 0x0D, 0x0D, 0x0D, 0x08, 0x00, 0x45, 0x00,
0x00, 0x34, 0x00, 0xF2, 0x00, 0x00, 0x40, 0x11,
0xB6, 0x65, 0xC0, 0xA8, 0x21, 0x0F, 0xC0, 0xA8,
0x21, 0x02, 0x04, 0x01, 0x00, 0x05, 0x00, 0x20,
0x60, 0x4c, 0x73, 0x66, 0x61, 0x73, 0x64, 0x66,
0x73, 0x61, 0x64, 0x66, 0x61, 0x73, 0x64, 0x66,
0x73, 0x64, 0x61, 0x66, 0x61, 0x73, 0x66, 0x73,
0x64, 0x66
};
uint_8 mybuf2[100];
int len;
BytesStack bs(100);
MyParameter paras[4]={
{0,&bs,mybuf1,66,1000000},
{1,&bs,mybuf1,66,2000000},
{2,&bs,mybuf1,66,3000000},
{3,&bs,mybuf2,len,1000000}
};
//bq.showBytesQueue(bq);
pthread_attr_init(&attr);
pthread_create(&threads[0], &attr, Push, (void *)¶s[0]);
pthread_create(&threads[1], &attr, Push, (void *)¶s[1]);
pthread_create(&threads[2], &attr, Push, (void *)¶s[2]);
pthread_create(&threads[3], &attr, Pop, (void *)¶s[3]);
//pthread_create(&threads[4], &attr, Pop, (void *)¶s[3]);
for (int i=0; i<4; i++)
{
pthread_join(threads[i], NULL);
}
pthread_attr_destroy(&attr);
bs.destroy();
bs.showBytesStack(bs);
printf("ok!!\n");
pthread_exit (NULL);
return 0;
} //end of main
____________________________________________________________________________________
zhangggdlt
2004.12.10
(完)