⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 shmobjqueue.cpp

📁 uclinux的进程间通信例子
💻 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;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -