一個支持多線程同步的堆棧的實現

堆棧元素爲一個無符字符數組(即字節數組)。堆棧中只存放該數組的地址。這個地址指向一個存儲區域,該存儲區的結構爲:
                                    _______________________________________________
                                    |數組長度(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
                                                                                                                                         (完)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章