一个支持多线程同步的堆栈的实现

堆栈元素为一个无符字符数组(即字节数组)。堆栈中只存放该数组的地址。这个地址指向一个存储区域,该存储区的结构为:
                                    _______________________________________________
                                    |数组长度(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 (pthread_mutex_trylock(&StaMutex))
 {
   printf("Try lock failed!/n");
   return FAILED_LOCK;
 }
 if (this->_top >= this->_size)
 {
  printf("The stack is full!/n");
  pthread_mutex_unlock(&StaMutex);
  return STACK_FULL;
 }
 if (!( temp= new uint_8[len + 4]))
 {
  pthread_mutex_unlock(&StaMutex);
  return NO_AREA;
 }
 
 
 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 (pthread_mutex_trylock(&StaMutex))
 {
   printf("Try lock failed!/n");
   return FAILED_LOCK;
 }
 if(!data)
 {
  pthread_mutex_unlock(&StaMutex);
  return POINT_NULL;
 }
 if(this->_top <= this->_bottom)
 {
  printf("The stack is empty!/n");
  pthread_mutex_unlock(&StaMutex);
  return STACK_EMPTY;
 }
 
 
 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 *)&paras[0]);
 pthread_create(&threads[1], &attr, Push, (void *)&paras[1]);
 pthread_create(&threads[2], &attr, Push, (void *)&paras[2]);
 pthread_create(&threads[3], &attr, Pop, (void *)&paras[3]);
 //pthread_create(&threads[4], &attr, Pop, (void *)&paras[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
                                                                                                                                         (完)

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值