这是一个同学写的关于共享内存的东西,封装了一些常用的数据结构,
在Redhat 9下编译通过,并且已经有了商业化的应用,目前还是比较稳
定的。下面是源代码:
lcli.cpp
#include "shmobjlink.h"
#include <unistd.h>
#include "mylog.h"
#include "obj.h"
int main()
{
shmobjlink<testObj> charPoolIns(100,2000);
int i;
for(i=1;i<2001;i++)
{
testObj j;
int ret;
j.index = i;
ret = charPoolIns.put(&j);
sleep(1);
if(ret == false)
{
mylog("no obj available");
sleep(1);
}
mylog("ret = %d",j.index);
}
return 0;
}
lser.cpp
#include "shmobjlink.h"
#include <unistd.h>
#include "mylog.h"
#include <signal.h>
#include "obj.h"
shmobjlink<testObj> charPoolIns(100,2000);
void catchSignal(int sig)
{
mylog("catch signal %d",sig);
testObj i;
testObj j;
i.index = 2;
while(charPoolIns.get(&j,&i)==true)
{
mylog("get obj= %d",j.index);
}
mylog("ok");
return;
}
int main()
{
signal(SIGUSR1, catchSignal);
while(1)
{
sleep(1);
}
}
mylog.cpp
/*
* this file provide log functionality
* composed by antony
* 2003-1-1
* copyright reserved
*/
/*
*if PERFORMANCE is define check performance of program
*this file provide performanc check global var
*/
#ifndef __MYLOG__H_
#define __MYLOG__H_
#include "mylog.h"
#ifdef PERFORMANCE
struct timeval timeTTStart; //记录时间
struct timeval timeTTNow;
#endif
#endif
mylog.h
/*
* this file provide log functionality
* composed by antony
* 2003-1-1
* copyright reserved
*/
/*
*if PERFORMANCE is define check performance of program
*define MACRO for log
*/
#ifndef __MYLOG__H_
#define __MYLOG__H_
#define LOG_MAX_LEN 512
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <iostream>
#include <fstream>
using namespace std;
#ifdef PERFORMANCE
extern struct timeval timeTTStart; //记录时间
extern struct timeval timeTTNow;
inline int my_check_start()
{
return gettimeofday(&timeTTStart, NULL);
}
int my_check_start();
#define my_check_point(fmt,arg...) { \
char mylogTmpString[LOG_MAX_LEN], tmpTime[20]; \
gettimeofday(&timeTTNow,NULL); \
sprintf(mylogTmpString,fmt,##arg); \
sprintf(tmpTime,"sec[%02d]m_sec[%06d]", \
(timeTTNow.tv_usec - timeTTStart.tv_usec)>0? \
(timeTTNow.tv_sec - timeTTStart.tv_sec):(timeTTNow.tv_sec - timeTTStart.tv_sec-1), \
(timeTTNow.tv_usec - timeTTStart.tv_usec)>0?\
(timeTTNow.tv_usec - timeTTStart.tv_usec):(1000000+(timeTTNow.tv_usec - timeTTStart.tv_usec)) ); \
cout<<tmpTime<<"F["<<__FILE__<<"]["<<__FUNCTION__<<"]L["<<__LINE__<<"]" \
<<":["<<mylogTmpString<<"]"<<endl; \
}
#define mylog(fmt,arg...)
#define get_now_time(fmt,arg...)
#else
#define my_check_start()
#define my_check_point(fmt,arg...)
#define mylog(fmt,arg...) { \
char mylogTmpString[LOG_MAX_LEN], tmpTime[20];\
get_now_time(tmpTime ,sizeof(tmpTime)); \
sprintf(mylogTmpString,fmt,##arg);\
cout<<tmpTime<<"F["<<__FILE__<<"]["<<__FUNCTION__<<"]L["<<__LINE__<<"]"\
<<":["<<mylogTmpString<<"]"<<endl;\
}
inline int get_now_time( char *str, int len)
{
struct tm * lt;
time_t tick;
char str_time[20];
tick=time(NULL);
lt=localtime(&tick);
int len_time;
sprintf(str_time,"[%02d:%02d:%02d:%02d]",lt->tm_mday,lt->tm_hour,lt->tm_min,lt->tm_sec);
if(len <(len_time=strlen(str_time)))
{
str[0] = 0;
return 0;
}
else
{
strcpy(str,str_time);
return len_time;
}
}
#endif
#endif
obj.cpp
#include "obj.h"
testObj::testObj()
{
}
testObj::~testObj()
{
}
bool testObj::operator==(testObj &another)
{
return (this->index == another.index);
}
testObj& testObj::operator=(testObj &another)
{
this->index = another.index;
return *this;
}
obj.h
#ifndef _OBJ_H_
#define _OBJ_H_
#include <stdlib.h>
#include <errno.h>
class testObj
{
public:
int index;
testObj();
~testObj();
void setIndex(int in)
{
index = in;
}
bool operator==( testObj &another);
testObj &operator=(testObj &another);
};
#endif
qcli.cpp
#include "shmobjqueue.h"
#include <unistd.h>
#include "mylog.h"
int main()
{
int i;
for(i=0;i<4000;i++)
{
shmobjqueue<int> charPoolIns(100,2000);
i = charPoolIns.getSize();
mylog("pool size %d",i);
int j;
int ret;
j = i;
ret = charPoolIns.put(&j);
/*
sleep(1);
if(ret == false)
{
mylog("no space available");
sleep(1);
}
mylog("ret = %d",j);
*/
ret = charPoolIns.get(&j);
}
return 0;
}
qser.cpp
#include "shmobjqueue.h"
#include <unistd.h>
#include "mylog.h"
#include <signal.h>
shmobjqueue<int> charPoolIns(100,2000);
void catchSignal(int sig)
{
mylog("catch signal %d",sig);
int j;
while(charPoolIns.get(&j)==true)
{
mylog("get obj= %d",j);
}
mylog("ok");
return;
}
int main()
{
signal(SIGUSR1, catchSignal);
while(1)
{
sleep(1);
}
}
rmipcs.cpp
//antony for rm ipcs utlity
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include "../include/mylog.h"
int main(int argc, char **argv)
{
int shmid;
int semid;
key_t shmkey;
key_t semkey;
if(argc != 4)
{
mylog("useage: rmipcs shmfile semfile project_id");
exit(0);
}
char *pShmfile = argv[1];
char *pSemfile = argv[2];
int proj_id = atoi(argv[3]);
shmkey = ftok(pShmfile, proj_id);
shmid = shmget(shmkey, 0, 0640);
printf("shmid=%d\n", shmid);
semkey = ftok(pSemfile, proj_id);
semid = semget(semkey, 0, 0640);
printf("semid=%d\n",semid);
}
shmobjlink.cpp
/*
* this file provide obj pool realization
* composed by antony
* 2003-3-17
* copyright reserved
*/
/*
*last modified 2003-3-25
*still need to add code to realize search function
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include "shmobjlink.h"
#include "mylog.h"
template <class st > shmobjlink<st>::shmobjlink(int ipckey,unsigned int count)
{
m_pShm = this->shmcreate(ipckey, count);
if(m_pShm == NULL)
{
mylog("shm init error");
assert(0);
}
this->m_pShmHead = (shmHead *)this->m_pShm;
if(m_pShmHead->maxPoolSize != count)
{
mylog("max num %d,req count %d",m_pShmHead->maxPoolSize, count);
assert(0);
}
this->asynInit(ipckey);
}
template <class st > shmobjlink<st>::~shmobjlink()
{
this->detach();
}
template <class st > char* shmobjlink<st>::shmcreate(int ipckey, unsigned int count)
{
int shmid = 0;
char *l_pShm = NULL;
key_t shmkey;
unsigned int size = sizeof(shmHead)+count*sizeof(container);
shmkey = ipckey;
mylog("shmkey:%d",shmkey);
shmid = shmget( shmkey, size, 0660 );
if( shmid < 0 ) {
shmid = shmget( shmkey, size, IPC_CREAT | 0660);
if( shmid < 0 )
return NULL;
l_pShm = (char *) shmat( shmid, NULL, 0 );
if( l_pShm == (void *)-1 )
return NULL;
((shmHead *)l_pShm)->maxPoolSize = count;
/* m_pShm 未赋值 */
m_pShm = l_pShm;
this->clearup();
} else {
mylog("attaching shm");
l_pShm = (char *) shmat( shmid, NULL, 0 );
if( l_pShm == (char *)-1 )
return NULL;
}
return l_pShm;
}
template <class st > bool shmobjlink<st>::get(st *p_st)
{
bool ret = false;
container *l_pCurContainer;
this->asynStart();
l_pCurContainer = m_pShmHead->first;
if( m_pShmHead->actPoolSize> 0)
{
ret = true;
memcpy(p_st, &l_pCurContainer->obj,sizeof(st));
l_pCurContainer->status = false;
m_pShmHead->first = l_pCurContainer->next;
m_pShmHead->last->next = m_pShmHead->first;
m_pShmHead->actPoolSize--;
}
else
{
mylog("error,pool size %d", m_pShmHead->actPoolSize);
}
this->asynEnd();
return ret;
}
template <class st > bool shmobjlink<st>::get(st *p_st, st *p_stIndext)
{
unsigned int loop;
bool ret = false;
container *l_pFirstContainer;
this->asynStart();
l_pFirstContainer = m_pShmHead->first;
for(loop=0;loop<m_pShmHead->actPoolSize;loop++)
{
if((m_pShmHead->first->obj) == *p_stIndext)
{
ret = true;
memcpy(p_st, &(m_pShmHead->first->obj),sizeof(st));
m_pShmHead->first->status = false;
m_pShmHead->first = m_pShmHead->first->next;
m_pShmHead->last->next = m_pShmHead->first;
m_pShmHead->actPoolSize--;
break;
}
this->moveNext();
}
this->asynEnd();
return ret;
}
template <class st > bool shmobjlink<st>::search(st *p_stIndext)
{
unsigned int loop;
bool ret = false;
container *l_pFirstContainer;
this->asynStart();
l_pFirstContainer = m_pShmHead->first;
for(loop=0;loop<m_pShmHead->actPoolSize;loop++)
{
if((m_pShmHead->first->obj) == *p_stIndext)
{
ret = true;
break;
}
this->moveNext();
}
this->asynEnd();
return ret;
}
template <class st > bool shmobjlink<st>::put(st *p_st)
{
bool ret = false;
container *l_pCrusingContainer = m_pShmHead->first;
this->asynStart();
if(m_pShmHead->actPoolSize< m_pShmHead->maxPoolSize)
{
while(l_pCrusingContainer != m_pShmHead->shmEnd )
{
if(l_pCrusingContainer->status == false)
break;
l_pCrusingContainer = l_pCrusingContainer ++;
}
if(l_pCrusingContainer != m_pShmHead->shmEnd)
{
ret = true;
l_pCrusingContainer->status = true;
memcpy(&(l_pCrusingContainer->obj), p_st, sizeof(st));
l_pCrusingContainer->next = m_pShmHead->first;
m_pShmHead->first = l_pCrusingContainer;
m_pShmHead->last->next = m_pShmHead->first;
m_pShmHead->actPoolSize ++;
mylog("after put,size %d", m_pShmHead->actPoolSize);
}
else
{
mylog("reach no space found");
}
}
else
{
mylog("pool is full");
}
this->asynEnd();
return ret;
}
template <class st > void shmobjlink<st>::clearup()
{
shmHead *l_pShmHead = (shmHead *)this->m_pShm;
container *l_pCrusingContainer = (container *)(this->m_pShm+sizeof(shmHead));
this->asynStart();
l_pShmHead->actPoolSize = 0;
l_pShmHead->shmStart = (container *)(this->m_pShm+sizeof(shmHead));
l_pShmHead->first = l_pShmHead->shmStart;
l_pShmHead->last = l_pShmHead->shmStart;
l_pShmHead->shmEnd = l_pShmHead->shmStart+l_pShmHead->maxPoolSize;
while(l_pCrusingContainer != l_pShmHead->shmEnd)
{
l_pCrusingContainer->status = false;
l_pCrusingContainer->next = NULL;
l_pCrusingContainer = l_pCrusingContainer++;
}
this->asynEnd();
}
template <class st > bool shmobjlink<st>::moveNext()
{
bool ret = false;
shmHead *l_pShmHead = (shmHead *)m_pShm;
//this->asynStart();
if(l_pShmHead->first->next != NULL)
{
ret = true;
l_pShmHead->last = l_pShmHead->first;
l_pShmHead->first = l_pShmHead->last->next;
}
//this->asynEnd();
return ret;
}
template <class st > void shmobjlink<st>::delCur()
{
}
template <class st > void shmobjlink<st>::asynInit(int ipckey)
{
key_t semkey;
int value;
semkey = ipckey;
mylog("semkey=%d",semkey);
m_iSemid = semget(semkey, 0, 0640);
if(m_iSemid <0)
{
m_iSemid = semget(semkey, 1, IPC_CREAT|0640);
if(m_iSemid<0)
{
mylog("error:%s",strerror( errno ));
}
arg.val = 1;
value = semctl(m_iSemid,0, SETVAL, arg);
value = semctl(m_iSemid,0, GETVAL, arg);
mylog("create sem value=%d",value);
return;
}
else
{
value = semctl(m_iSemid,0, GETVAL, arg);
mylog("sem exist,value=%d",value);
return;
}
}
template <class st > void shmobjlink<st>::asynStart()
{
struct sembuf sops;
int value;
sops.sem_num=0;
sops.sem_op=-1;
sops.sem_flg=0;
value=semctl(m_iSemid,sops.sem_num,GETVAL,0);
mylog("before AsyStart %d", value);
value = semop(m_iSemid,&sops,1);
mylog("after AsyStart %d", value);
return;
}
template <class st > void shmobjlink<st>::asynEnd()
{
struct sembuf sops;
int value;
sops.sem_num=0;
sops.sem_op=1;
sops.sem_flg=0;
value=semctl(m_iSemid,sops.sem_num,GETVAL,0);
mylog("before AsyEnd %d", value);
value = semop(m_iSemid,&sops,1);
value=semctl(m_iSemid,sops.sem_num,GETVAL,0);
mylog("after AsyEnd %d", value);
return;
}
template <class st > void shmobjlink<st>::detach()
{
if(m_pShm > (void *)0)
shmdt(m_pShm);
}
template <class st > bool shmobjlink<st>::isEmpty()
{
if(m_pShmHead->actPoolSize == 0)
return true;
else
return false;
}
shmobjlink.h
/*
* this file provide obj pool realization
* composed by antony
* 2003-3-24
* copyright reserved
*/
/*
* last modified 2003-3-25
*/
#ifndef __SHMBOJLINK_H_
#define __SHMBOJLINK_H_
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include "obj.h"
template <class st> class shmobjlink
{
private:
union semun {
int val;
struct semid_ds *buf;
ushort *array;
} arg;
typedef struct container
{
bool status;
st obj;
container *next;
};
typedef struct
{
unsigned int maxPoolSize;
unsigned int actPoolSize;
container *shmStart;
container *shmEnd;
container *last;
container *first;
}shmHead;
char *m_pShm;
shmHead *m_pShmHead;
int m_iSemid;
char *shmcreate(int ipckey, unsigned int count);
void asynInit(int ipckey);
void asynStart();
void asynEnd();
/* move to next node */
bool moveNext();
void delCur();
public:
//create memory to contain num st obj
shmobjlink(int ipckey, unsigned int count );
~shmobjlink();
//get first obj from pool
bool get(st *) ;
//search obj from pool
bool search(st *) ;
//get a obj by index
bool get(st *out, st *in);
//put a obj to pool
bool put(st *);
//clear up all objs in pool
void clearup();
//detach from shm
void detach();
//return true if empty
bool isEmpty();
};
/*
* just realize the following class
*/
template class shmobjlink<char>;
template class shmobjlink<int>;
template class shmobjlink<testObj>;
#endif
shmobjlinkeq.cpp
/*
* this file provide obj pool realization
* composed by antony
* 2003-3-17
* copyright reserved
*/
/*
*last modified 2003-3-25
*still need to add code to realize search function
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include "shmobjlinkeq.h"
#include "mylog.h"
template <class st, class eq> shmobjlinkeq<st, eq>::shmobjlinkeq(int ipckey,unsigned int count)
{
m_pShm = this->shmcreate(ipckey, count);
if(m_pShm == NULL)
{
mylog("shm init error");
assert(0);
}
this->m_pShmHead = (shmHead *)this->m_pShm;
if(m_pShmHead->maxPoolSize != count)
{
mylog("max num %d,req count %d",m_pShmHead->maxPoolSize, count);
assert(0);
}
this->asynInit(ipckey);
}
template <class st, class eq> shmobjlinkeq<st, eq>::~shmobjlinkeq()
{
this->detach();
}
template <class st, class eq> char* shmobjlinkeq<st, eq>::shmcreate(int ipckey, unsigned int count)
{
int shmid = 0;
char *l_pShm = NULL;
key_t shmkey;
unsigned int size = sizeof(shmHead)+count*sizeof(container);
shmkey = ipckey;
mylog("shmkey:%d",shmkey);
shmid = shmget( shmkey, size, 0660 );
if( shmid < 0 ) {
shmid = shmget( shmkey, size, IPC_CREAT | 0660);
if( shmid < 0 )
return NULL;
l_pShm = (char *) shmat( shmid, NULL, 0 );
if( l_pShm == (void *)-1 )
return NULL;
((shmHead *)l_pShm)->maxPoolSize = count;
/* m_pShm 未赋值 */
m_pShm = l_pShm;
this->clearup();
} else {
mylog("attaching shm");
l_pShm = (char *) shmat( shmid, NULL, 0 );
if( l_pShm == (char *)-1 )
return NULL;
}
return l_pShm;
}
template <class st, class eq> bool shmobjlinkeq<st, eq>::get(st *p_st)
{
bool ret = false;
container *l_pCurContainer;
this->asynStart();
l_pCurContainer = m_pShmHead->first;
if( m_pShmHead->actPoolSize> 0)
{
ret = true;
memcpy(p_st, &l_pCurContainer->obj,sizeof(st));
l_pCurContainer->status = false;
m_pShmHead->first = l_pCurContainer->next;
m_pShmHead->last->next = m_pShmHead->first;
m_pShmHead->actPoolSize--;
}
else
{
mylog("error,pool size %d", m_pShmHead->actPoolSize);
}
this->asynEnd();
return ret;
}
template <class st, class eq> bool shmobjlinkeq<st, eq>::get(st *p_st, st *p_stIndext)
{
unsigned int loop;
bool ret = false;
container *l_pFirstContainer;
this->asynStart();
l_pFirstContainer = m_pShmHead->first;
for(loop=0;loop<m_pShmHead->actPoolSize;loop++)
{
if((m_pShmHead->first->obj) == *p_stIndext)
{
ret = true;
memcpy(p_st, &(m_pShmHead->first->obj),sizeof(st));
m_pShmHead->first->status = false;
m_pShmHead->first = m_pShmHead->first->next;
m_pShmHead->last->next = m_pShmHead->first;
m_pShmHead->actPoolSize--;
break;
}
this->moveNext();
}
this->asynEnd();
return ret;
}
template <class st, class eq> bool shmobjlinkeq<st, eq>::search(st *p_stIndext)
{
unsigned int loop;
bool ret = false;
container *l_pFirstContainer;
this->asynStart();
l_pFirstContainer = m_pShmHead->first;
for(loop=0;loop<m_pShmHead->actPoolSize;loop++)
{
if((m_pShmHead->first->obj) == *p_stIndext)
{
ret = true;
break;
}
this->moveNext();
}
this->asynEnd();
return ret;
}
template <class st, class eq> bool shmobjlinkeq<st, eq>::put(st *p_st)
{
bool ret = false;
container *l_pCrusingContainer = m_pShmHead->first;
this->asynStart();
if(m_pShmHead->actPoolSize< m_pShmHead->maxPoolSize)
{
while(l_pCrusingContainer != m_pShmHead->shmEnd )
{
if(l_pCrusingContainer->status == false)
break;
l_pCrusingContainer = l_pCrusingContainer ++;
}
if(l_pCrusingContainer != m_pShmHead->shmEnd)
{
ret = true;
l_pCrusingContainer->status = true;
memcpy(&(l_pCrusingContainer->obj), p_st, sizeof(st));
l_pCrusingContainer->next = m_pShmHead->first;
m_pShmHead->first = l_pCrusingContainer;
m_pShmHead->last->next = m_pShmHead->first;
m_pShmHead->actPoolSize ++;
mylog("after put,size %d", m_pShmHead->actPoolSize);
}
else
{
mylog("reach no space found");
}
}
else
{
mylog("pool is full");
}
this->asynEnd();
return ret;
}
template <class st, class eq> void shmobjlinkeq<st, eq>::clearup()
{
shmHead *l_pShmHead = (shmHead *)this->m_pShm;
container *l_pCrusingContainer = (container *)(this->m_pShm+sizeof(shmHead));
this->asynStart();
l_pShmHead->actPoolSize = 0;
l_pShmHead->shmStart = (container *)(this->m_pShm+sizeof(shmHead));
l_pShmHead->first = l_pShmHead->shmStart;
l_pShmHead->last = l_pShmHead->shmStart;
l_pShmHead->shmEnd = l_pShmHead->shmStart+l_pShmHead->maxPoolSize;
while(l_pCrusingContainer != l_pShmHead->shmEnd)
{
l_pCrusingContainer->status = false;
l_pCrusingContainer->next = NULL;
l_pCrusingContainer = l_pCrusingContainer++;
}
this->asynEnd();
}
template <class st, class eq> bool shmobjlinkeq<st, eq>::moveNext()
{
bool ret = false;
shmHead *l_pShmHead = (shmHead *)m_pShm;
//this->asynStart();
if(l_pShmHead->first->next != NULL)
{
ret = true;
l_pShmHead->last = l_pShmHead->first;
l_pShmHead->first = l_pShmHead->last->next;
}
//this->asynEnd();
return ret;
}
template <class st, class eq> void shmobjlinkeq<st, eq>::delCur()
{
}
template <class st, class eq> void shmobjlinkeq<st, eq>::asynInit(int ipckey)
{
key_t semkey;
int value;
semkey = ipckey;
mylog("semkey=%d",semkey);
m_iSemid = semget(semkey, 0, 0640);
if(m_iSemid <0)
{
m_iSemid = semget(semkey, 1, IPC_CREAT|0640);
if(m_iSemid<0)
{
mylog("error:%s",strerror( errno ));
}
arg.val = 1;
value = semctl(m_iSemid,0, SETVAL, arg);
value = semctl(m_iSemid,0, GETVAL, arg);
mylog("create sem value=%d",value);
return;
}
else
{
value = semctl(m_iSemid,0, GETVAL, arg);
mylog("sem exist,value=%d",value);
return;
}
}
template <class st, class eq> void shmobjlinkeq<st, eq>::asynStart()
{
struct sembuf sops;
int value;
sops.sem_num=0;
sops.sem_op=-1;
sops.sem_flg=0;
value=semctl(m_iSemid,sops.sem_num,GETVAL,0);
mylog("before AsyStart %d", value);
value = semop(m_iSemid,&sops,1);
mylog("after AsyStart %d", value);
return;
}
template <class st, class eq> void shmobjlinkeq<st, eq>::asynEnd()
{
struct sembuf sops;
int value;
sops.sem_num=0;
sops.sem_op=1;
sops.sem_flg=0;
value=semctl(m_iSemid,sops.sem_num,GETVAL,0);
mylog("before AsyEnd %d", value);
value = semop(m_iSemid,&sops,1);
value=semctl(m_iSemid,sops.sem_num,GETVAL,0);
mylog("after AsyEnd %d", value);
return;
}
template <class st, class eq> void shmobjlinkeq<st, eq>::detach()
{
if(m_pShm > (void *)0)
shmdt(m_pShm);
}
template <class st, class eq> bool shmobjlinkeq<st, eq>::isEmpty()
{
if(m_pShmHead->actPoolSize == 0)
return true;
else
return false;
}
shmobjlinkeq.h
/*
* this file provide obj pool realization
* composed by antony
* 2003-3-24
* copyright reserved
*/
/*
* last modified 2003-3-25
*/
#ifndef __SHMBOJLINK_H_
#define __SHMBOJLINK_H_
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include "obj.h"
struct eqint
{
bool operator()(const int c1, const int c2) const
{
return c1 == c2;
}
};
template <class st, class eq> class shmobjlinkeq
{
private:
union semun {
int val;
struct semid_ds *buf;
ushort *array;
} arg;
typedef struct container
{
bool status;
st obj;
container *next;
};
typedef struct
{
unsigned int maxPoolSize;
unsigned int actPoolSize;
container *shmStart;
container *shmEnd;
container *last;
container *first;
}shmHead;
char *m_pShm;
shmHead *m_pShmHead;
int m_iSemid;
char *shmcreate(int ipckey, unsigned int count);
void asynInit(int ipckey);
void asynStart();
void asynEnd();
/* move to next node */
bool moveNext();
void delCur();
public:
//create memory to contain num st obj
shmobjlinkeq(int ipckey, unsigned int count);
~shmobjlinkeq();
//get first obj from pool
bool get(st *) ;
//search obj from pool
bool search(st *) ;
//get a obj by index
bool get(st *out, st *in);
//put a obj to pool
bool put(st *);
//clear up all objs in pool
void clearup();
//detach from shm
void detach();
//return true if empty
bool isEmpty();
};
/*
* just realize the following class
*/
template class shmobjlinkeq<int,eqint>;
//template class shmobjlinkeq<int>;
//template class shmobjlinkeq<testObj>;
#endif
shmobjqueue.cpp
/*
* this file provide obj queue in share memory realization
* composed by antony
* 2003-3-17
* copyright reserved
*/
/*
*m_ppObjLast modified 2003-3-18
*still need to add code to maintain shm consistent
*/
//modified by antony 2003-03-23
//change shm create mode
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include "shmobjqueue.h"
#include "mylog.h"
template <class st > shmobjqueue<st>::shmobjqueue(int ipckey,int num)
{
m_ipckey = ipckey;
mylog("init queue shmobjqueue key=%x", ipckey);
this->m_iObjSize = sizeof(st);
//m_pShm = this->shmcreate(shmfilename, proj_id, num*this->m_iObjSize +sizeof(int)*4);
m_pShm = this->shmcreate(ipckey, num);
if(m_pShm == NULL)
{
assert(0);
}
this->m_piMaxPoolSize = (int *)m_pShm;
if(*this->m_piMaxPoolSize != num)
{
mylog("pool size actual size:%d,reques size:%d",*this->m_piMaxPoolSize,num);
assert(0);
}
this->m_piPoolSize = (int *)((char *)this->m_piMaxPoolSize+sizeof(this->m_piMaxPoolSize));
this->m_ppObjFirst = (st **)((char *)this->m_piPoolSize+sizeof(this->m_piPoolSize));
this->m_ppObjLast = (st **)((char *)this->m_ppObjFirst+sizeof(this->m_ppObjFirst));
this->m_pMemStart = (st *)((char *)this->m_ppObjLast+ sizeof(this->m_ppObjLast));
this->m_pMemEnd = (st *)(this->m_pMemStart + *(this->m_piMaxPoolSize));
this->asynInit(ipckey);
}
template <class st > shmobjqueue<st>::~shmobjqueue()
{
mylog("destruct[%x]",m_ipckey);
this->detach();
}
template <class st > char* shmobjqueue<st>::shmcreate(int ipckey, unsigned long num)
{
int shmid = 0;
int size;
key_t shmkey;
if(num != 0)
size = num*this->m_iObjSize +sizeof(int)*4;
else
size = 0;
shmkey = ipckey;
shmid = shmget( shmkey, size, 0640 );
if( shmid < 0 ) {
shmid = shmget( shmkey, size, IPC_CREAT | 0640);
if( shmid < 0 )
return NULL;
m_pShm = (char *) shmat( shmid, NULL, 0 );
if( m_pShm == (char *)-1 )
return NULL;
memset( m_pShm, 0, size );
*(int *)m_pShm = num;
*(int *)((int)m_pShm+sizeof(int)) = 0;
*(void **)((int)m_pShm+sizeof(int)*2) = (void *)((int)m_pShm + sizeof(int)*4);
*(void **)((int)m_pShm+sizeof(int)*3) = (void *)((int)m_pShm + sizeof(int)*4);
} else {
mylog("attaching shm");
m_pShm = (char *) shmat( shmid, NULL, 0 );
if( m_pShm == (void *)-1 )
{
mylog("error:%s",strerror(errno));
return NULL;
}
}
return m_pShm;
}
template <class st > bool shmobjqueue<st>::get(st *p_st)
{
bool ret;
this->asynStart();
mylog("before get,pool size=%d",*this->m_piPoolSize);
if( *this->m_piPoolSize <0)
{
ret = false;
mylog("m_piPoolSize error:%d", *this->m_piPoolSize);
//force to clearup;
this->clearup();
}
else if(*this->m_piPoolSize == 0)
{
ret = false;
mylog("pool is empty");
if(*this->m_ppObjFirst != *this->m_ppObjLast )
{
mylog("consistent error");
}
}
else
{
ret = true;
(*this->m_piPoolSize)--;
memcpy(p_st, *this->m_ppObjFirst, sizeof(st));
*this->m_ppObjFirst = (st *)((char *)*this->m_ppObjFirst+this->m_iObjSize );
//reach m_pMemEnd,loop to m_pMemStart point
if(*this->m_ppObjFirst == this->m_pMemEnd)
*this->m_ppObjFirst = this->m_pMemStart;
if(*this->m_ppObjFirst == *this->m_ppObjLast)
{
*this->m_piPoolSize = 0;
}
}
mylog("after get,pool size=%d",*this->m_piPoolSize);
this->asynEnd();
return ret;
}
template <class st > bool shmobjqueue<st>::put(st *p_st)
{
bool ret;
this->asynStart();
mylog("before put,pool size=%d",*this->m_piPoolSize);
if(*this->m_piPoolSize >*this->m_piMaxPoolSize)
{
mylog("pool size error,max size:%d,actual size:%d",
*this->m_piMaxPoolSize,*this->m_piPoolSize);
ret = false;
}
else if(*this->m_piPoolSize ==*this->m_piMaxPoolSize)
{
ret = false;
mylog("pool is full,max size:%d",*this->m_piMaxPoolSize);
if(*this->m_ppObjFirst != *this->m_ppObjLast )
{
mylog("consistent error");
}
}
else
{
ret = true;
memcpy(*this->m_ppObjLast,p_st, sizeof(st));
*this->m_ppObjLast = (st *)((char *)*this->m_ppObjLast+this->m_iObjSize );
if(*this->m_ppObjLast == this->m_pMemEnd)
*this->m_ppObjLast = this->m_pMemStart;
(*this->m_piPoolSize)++;
}
mylog("after put,pool size=%d",*this->m_piPoolSize);
this->asynEnd();
return ret;
}
template <class st > void shmobjqueue<st>::clearup()
{
this->asynStart();
*this->m_ppObjFirst = this->m_pMemStart;
*this->m_ppObjLast = this->m_pMemStart;
*this->m_piPoolSize = 0;
this->asynEnd();
}
template <class st > void shmobjqueue<st>::asynInit(int ipckey)
{
key_t semkey;
int value;
semkey = ipckey;
m_iSemid = semget(semkey, 0, 0640);
if(m_iSemid <0)
{
m_iSemid = semget(semkey, 1, IPC_CREAT|0640);
if(m_iSemid<0)
{
mylog("error:%s",strerror( errno ));
}
arg.val = 1;
value = semctl(m_iSemid,0, SETVAL, arg);
mylog("create sem value=%d",value);
return;
}
else
{
value = semctl(m_iSemid,0, GETVAL, arg);
mylog("sem exist,value=%d",value);
return;
}
}
template <class st > void shmobjqueue<st>::asynStart()
{
struct sembuf sops;
int value;
sops.sem_num=0;
sops.sem_op=-1;
sops.sem_flg=0;
// value=semctl(m_iSemid,sops.sem_num,GETVAL,0);
// mylog("before AsyStart %d", value);
value = semop(m_iSemid,&sops,1);
// mylog("after AsyStart %d", value);
return;
}
template <class st > void shmobjqueue<st>::asynEnd()
{
struct sembuf sops;
int value;
sops.sem_num=0;
sops.sem_op=1;
sops.sem_flg=0;
// value=semctl(m_iSemid,sops.sem_num,GETVAL,0);
// mylog("before AsyEnd %d", value);
value = semop(m_iSemid,&sops,1);
// value=semctl(m_iSemid,sops.sem_num,GETVAL,0);
// mylog("after AsyEnd %d", value);
return;
}
template <class st > void shmobjqueue<st>::detach()
{
if(m_pShm > (void *)0)
shmdt(m_pShm);
mylog("ipckey=%x", m_ipckey);
}
template <class st > bool shmobjqueue<st>::isEmpty()
{
if(*(this->m_piPoolSize) == 0)
return true;
else
return false;
}
template <class st > int shmobjqueue<st>::getSize()
{
int l_size;
asynStart();
l_size = *m_piPoolSize;
asynEnd();
return l_size;
}
template <class st > bool shmobjqueue<st>::isFull()
{
bool l_bRet;
asynStart();
l_bRet = (*m_piPoolSize == *m_piMaxPoolSize);
asynEnd();
return l_bRet;
}
shmobjqueue.h
/*
* this file provide obj queue in share memory realization
* composed by antony
* 2003-3-17
* copyright reserved
*/
#ifndef __SHMBOJQUEUE_H_
#define __SHMBOJQUEUE_H_
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include "../include/msg_struct.h"
template <class st> class shmobjqueue
{
private:
char *m_pShm;
int m_iSemid;
int m_iObjSize;
int *m_piPoolSize;
int *m_piMaxPoolSize;
st *m_pMemStart; //memory m_pMemStart
st *m_pMemEnd; //memorr m_pMemEnd;
st **m_ppObjFirst; //m_ppObjFirst node;
st **m_ppObjLast; //m_ppObjLast node;
union semun {
int val;
struct semid_ds *buf;
ushort *array;
} arg;
char *shmcreate(int ipckey, unsigned long size);
void asynInit(int ipckey);
void asynStart();
void asynEnd();
public:
//create memory to contain num st obj
shmobjqueue(int ipckey, int num = 5000 );
~shmobjqueue();
//get a obj from pool
bool get(st *);
//put a obj to pool
bool put(st *);
//clear up all objs in pool
void clearup();
//detach from shm
void detach();
//return true if empty
bool isEmpty();
//return pool size
int getSize();
//return is full
bool isFull();
int m_ipckey;
};
/*
* just realize the following class
*/
template class shmobjqueue<char>;
template class shmobjqueue<int>;
template class shmobjqueue<recv_node_stru>;
template class shmobjqueue<submit_node_stru>;
#endif
shmobjvector.cpp
/*
* this file provide obj pool realization
* composed by antony
* 2003-3-17
* copyright reserved
*/
/*
*last modified 2003-3-25
*still need to add code to realize search function
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include "shmobjvector.h"
#include "mylog.h"
#include "obj.h"
template <class st > shmobjvector<st>::shmobjvector(int ipckey,unsigned int count)
{
m_pCurContainer = NULL;
m_pShm = this->shmcreate(ipckey, count);
if(m_pShm == NULL)
{
mylog("shm init error");
assert(0);
}
this->m_pShmHead = (shmHead *)this->m_pShm;
if(m_pShmHead->maxPoolSize != count)
{
mylog("max num %d,req count %d",m_pShmHead->maxPoolSize, count);
assert(0);
}
//m_pCurContainer = m_pShmHead->shmStart;
this->asynInit(ipckey);
}
template <class st > shmobjvector<st>::~shmobjvector()
{
this->detach();
}
template <class st > bool shmobjvector<st>::setId(unsigned int id)
{
bool ret = false;
if(m_pShmHead->maxPoolSize >id)
{
ret = true;
m_pCurContainer = m_pShmHead->shmStart+ id;
}
else
{
m_pCurContainer = NULL;
mylog("id error");
}
return ret;
}
template <class st > char* shmobjvector<st>::shmcreate(int ipckey, unsigned int count)
{
int shmid = 0;
unsigned int i;
char *l_pShm = NULL;
container *l_pContainer = NULL;
key_t shmkey;
shmkey = ipckey;
unsigned int size = sizeof(shmHead)+count*sizeof(container);
mylog("shmkey:%d",shmkey);
shmid = shmget( shmkey, size, 0660 );
if( shmid < 0 ) {
shmid = shmget( shmkey, size, IPC_CREAT | 0660);
if( shmid < 0 )
return NULL;
l_pShm = (char *) shmat( shmid, NULL, 0 );
if( l_pShm == (void *)-1 )
return NULL;
((shmHead *)l_pShm)->maxPoolSize = count;
((shmHead *)l_pShm)->actPoolSize = 0;
/* m_pShm 未赋值 */
m_pShm = l_pShm;
((shmHead *)l_pShm)->shmStart =(container *)((char *)l_pShm+sizeof(shmHead));
((shmHead *)l_pShm)->shmEnd =((shmHead *)l_pShm)->shmStart+count;
l_pContainer = ((shmHead *)l_pShm)->shmStart;
for(i=0;i<count;i++)
{
l_pContainer->status = false;
l_pContainer++;
}
} else {
mylog("attaching shm");
l_pShm = (char *) shmat( shmid, NULL, 0 );
if( l_pShm == (char *)-1 )
return NULL;
}
return l_pShm;
}
template <class st > bool shmobjvector<st>::get(st *p_st)
{
bool ret = false;
if(m_pCurContainer != NULL)
{
if(m_pCurContainer->status == true)
{
ret = true;
mylog("get valid status");
this->asynStart();
memcpy( p_st, &m_pCurContainer->obj, sizeof(st));
this->asynEnd();
}
else
mylog("get invalid status");
}
else
{
mylog("init error");
}
return ret;
}
template <class st > bool shmobjvector<st>::put(st *p_st)
{
bool ret = false;
if(m_pCurContainer != NULL)
{
ret = true;
this->asynStart();
if(m_pCurContainer->status == true)
{
mylog("update status");
}
else
{
mylog("init status");
m_pCurContainer->status = true;
}
memcpy(&m_pCurContainer->obj, p_st, sizeof(st));
this->asynEnd();
}
else
{
mylog("init error");
}
return ret;
}
template <class st > void shmobjvector<st>::asynInit(int ipckey)
{
key_t semkey;
int value;
semkey = ipckey;
mylog("semkey=%d",semkey);
m_iSemid = semget(semkey, 0, 0640);
if(m_iSemid <0)
{
m_iSemid = semget(semkey, 1, IPC_CREAT|0640);
if(m_iSemid<0)
{
mylog("error:%s",strerror( errno ));
}
arg.val = 1;
value = semctl(m_iSemid,0, SETVAL, arg);
value = semctl(m_iSemid,0, GETVAL, arg);
mylog("create sem value=%d",value);
return;
}
else
{
value = semctl(m_iSemid,0, GETVAL, arg);
mylog("sem exist,value=%d",value);
return;
}
}
template <class st > void shmobjvector<st>::asynStart()
{
struct sembuf sops;
int value;
sops.sem_num=0;
sops.sem_op=-1;
sops.sem_flg=0;
value=semctl(m_iSemid,sops.sem_num,GETVAL,0);
mylog("before AsyStart %d", value);
value = semop(m_iSemid,&sops,1);
mylog("after AsyStart %d", value);
return;
}
template <class st > void shmobjvector<st>::asynEnd()
{
struct sembuf sops;
int value;
sops.sem_num=0;
sops.sem_op=1;
sops.sem_flg=0;
value=semctl(m_iSemid,sops.sem_num,GETVAL,0);
mylog("before AsyEnd %d", value);
value = semop(m_iSemid,&sops,1);
value=semctl(m_iSemid,sops.sem_num,GETVAL,0);
mylog("after AsyEnd %d", value);
return;
}
template <class st > void shmobjvector<st>::detach()
{
if(m_pShm > (void *)0)
shmdt(m_pShm);
}
template <class st > bool shmobjvector<st>::isEmpty()
{
if(m_pShmHead->actPoolSize == 0)
return true;
else
return false;
}
/*
* just realize the following class
*/
template class shmobjvector<char>;
template class shmobjvector<int>;
template class shmobjvector<testObj>;
shmobjvector.h
/*
* this file provide obj pool realization
* composed by antony
* 2003-3-24
* copyright reserved
*/
/*
* last modified 2003-3-25
*/
#ifndef __SHMBOJVECTOR_H_
#define __SHMBOJVECTOR_H_
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
template <class st> class shmobjvector
{
private:
union semun {
int val;
struct semid_ds *buf;
ushort *array;
} arg;
typedef struct container
{
bool status;
st obj;
};
typedef struct
{
unsigned int maxPoolSize;
unsigned int actPoolSize;
container *shmStart;
container *shmEnd;
}shmHead;
char *m_pShm;
shmHead *m_pShmHead;
container *m_pCurContainer;
int m_iSemid;
char *shmcreate(int ipckey, unsigned int count);
void asynInit(int ipckey);
void asynStart();
void asynEnd();
public:
//create memory to contain num st obj
shmobjvector(int ipckey, unsigned int count);
~shmobjvector();
//get first obj from pool
bool setId(unsigned int) ;
//put a obj to pool
bool update(st *);
//put a obj to pool
bool put(st *);
bool get(st *);
bool isEmpty();
//detach from shm
void detach();
};
#endif
vcli.cpp
#include "shmobjvector.h"
#include <unistd.h>
#include "mylog.h"
int main()
{
shmobjvector<int> charPoolIns(100,2000);
int i;
for(i=0;i<2000;i++)
{
int j=0;
charPoolIns.setId(1999);
charPoolIns.put(&i);
charPoolIns.get(&j);
sleep(1);
mylog("%d = %d",i,j);
}
return 0;
}
makefile
CFLAGS=-g -O2 -Wall
DLLFLAGS = -fPIC -DPIC
TARGET=qcli qser lcli lser vcli rmipcs libshmobjpool.a
OBJS=shmobjvector.o shmobjqueue.o shmobjlink.o shmobjlinkeq.o obj.o
ORACLE_HOME=/usr/local/oracle/app
CC=g++
all:$(TARGET)
cp *.h ../include/
cp *.a ../lib/
qcli:$(OBJS) qcli.o
$(CC) $(LDFLAGS) -g -o $@ $^
qser:$(OBJS) qser.o
$(CC) $(LDFLAGS) -g -o $@ $^
lcli:$(OBJS) lcli.o
$(CC) $(LDFLAGS) -g -o $@ $^
lser:$(OBJS) lser.o
$(CC) $(LDFLAGS) -g -o $@ $^
vcli:$(OBJS) vcli.o
$(CC) $(LDFLAGS) -g -o $@ $^
leqcli:$(OBJS) leqcli.o
$(CC) $(LDFLAGS) -g -o $@ $^
leqser:$(OBJS) leqser.o
$(CC) $(LDFLAGS) -g -o $@ $^
rmipcs:rmipcs.o
$(CC) $(LDFLAGS) -g -o $@ $^
libshmobjpool.a:$(OBJS)
ar -rv $@ $^
.SUFFIXES:.o .h
.SUFFIXES:.cpp .o
.cpp.o:
$(CC) -c $(CFLAGS) -o $@ $< -I $(ORACLE_HOME)/rdbms/demo -I$(ORACLE_HOME)/rdbms/public -I$(ORACLE_HOME)/network/public
clean:
rm -f *.o $(TARGET)
remake: clean $(TARGET)