Created
October 24, 2019 15:11
-
-
Save byyam/841e07516337327c0ac2560f737bed03 to your computer and use it in GitHub Desktop.
fifo cache demo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "fifo_cache.hpp" | |
tFifoCache::~tFifoCache() | |
{ | |
if (p_cache_buffer != reinterpret_cast<char *>(-1)) | |
{ | |
int nRet = ::shmdt(p_cache_buffer); | |
if (0 != nRet) | |
{ | |
std::cerr << "shmdt failed"; | |
} | |
} | |
} | |
void tFifoCache::Reset() | |
{ | |
p_meta_info->ShowMetaInfo(); | |
p_meta_info->Reset(); | |
} | |
int tFifoCache::Init() | |
{ | |
int nShmId = ::shmget(n_key, n_total_size, IPC_CREAT|0666); | |
if (nShmId < 0) | |
{ | |
std::cerr << " error: " << strerror(errno); | |
return -1; | |
} | |
p_cache_buffer = ::shmat(nShmId, NULL, 0); | |
if ((char *)-1 == (char *)p_cache_buffer) | |
{ | |
std::cerr << " error: " << strerror(errno); | |
return -2; | |
} | |
p_meta_info = (tFifoCacheMeta *)p_cache_buffer; | |
p_meta_info->cache_size = n_total_size; | |
p_meta_info->usage_space = n_data_size; | |
p_data_buffer = (char *)p_cache_buffer + sizeof(tFifoCacheMeta); | |
return 0; | |
} | |
size_t tFifoCache::_GetFillLength() | |
{ | |
return (((p_meta_info->tail_place + n_data_size) - p_meta_info->head_place) % n_data_size); | |
} | |
size_t tFifoCache::_GetFreeLength() | |
{ | |
return (n_data_size - _GetFillLength() - 1); | |
} | |
void tFifoCache::_SetDataHead(const uint32_t nType, const size_t nLen) | |
{ | |
t_data_head.data_type = nType; | |
t_data_head.data_len = nLen; | |
} | |
void tFifoCache::_GetDataHead(uint32_t &nType, size_t &nLen) | |
{ | |
nType = t_data_head.data_type; | |
nLen = t_data_head.data_len; | |
} | |
void tFifoCache::_Write(const char * pBuf, const size_t nLen) | |
{ | |
if (p_meta_info->head_place > p_meta_info->tail_place) | |
{ | |
memcpy(&p_data_buffer[p_meta_info->tail_place], pBuf, nLen); | |
} | |
else | |
{ | |
size_t nPartLen = n_data_size - p_meta_info->tail_place; | |
if (nPartLen < nLen) | |
{ | |
memcpy(&p_data_buffer[p_meta_info->tail_place], pBuf, nPartLen); | |
memcpy(&p_data_buffer[0], pBuf + nPartLen, nLen - nPartLen); | |
} | |
else | |
{ | |
memcpy(&p_data_buffer[p_meta_info->tail_place], pBuf, nLen); | |
} | |
} | |
p_meta_info->tail_place = (p_meta_info->tail_place + nLen) % n_data_size; | |
} | |
int tFifoCache::Write(const char * pBodyBuf, const size_t nBodyLen, const uint32_t nBodyType) | |
{ | |
if (NULL == p_meta_info) | |
{ | |
return -1; | |
} | |
if (0 == nBodyLen) | |
{ | |
return -2; | |
} | |
size_t nTotalLen = nBodyLen + sizeof(tDataHead); | |
_SetDataHead(nBodyType, nBodyLen); | |
if (_GetFreeLength() < nTotalLen) | |
{ | |
//full | |
return 1; | |
} | |
_Write((char *)&t_data_head, sizeof(tDataHead)); | |
_Write(pBodyBuf, nBodyLen); | |
return 0; | |
} | |
int tFifoCache::_Peek() | |
{ | |
if (_GetFillLength() < sizeof(tDataHead)) | |
{ | |
return 1; | |
} | |
tDataHead tTmpHead; | |
_Read((char *)&tTmpHead, sizeof(tDataHead), false); | |
if (_GetFillLength() < sizeof(tDataHead) + tTmpHead.data_len) | |
{ | |
return 2; | |
} | |
return 0; | |
} | |
void tFifoCache::_Read(char *pBuf, const size_t nLen, bool bUpdatePtr) | |
{ | |
if (p_meta_info->head_place < p_meta_info->tail_place) | |
{ | |
memcpy(pBuf, &p_data_buffer[p_meta_info->head_place], nLen); | |
} | |
else | |
{ | |
size_t nPartLen = n_data_size - p_meta_info->head_place; | |
if (nPartLen < nLen) | |
{ | |
memcpy(pBuf, &p_data_buffer[p_meta_info->head_place], nPartLen); | |
memcpy(pBuf + nPartLen, &p_data_buffer[0], nLen - nPartLen); | |
} | |
else | |
{ | |
memcpy(pBuf, &p_data_buffer[p_meta_info->head_place], nLen); | |
} | |
} | |
if (bUpdatePtr) | |
{ | |
p_meta_info->head_place = (p_meta_info->head_place + nLen) % n_data_size; | |
} | |
} | |
int tFifoCache::Read(std::string &sBuf, uint32_t &nType) | |
{ | |
int nRet = _Peek(); | |
if (0 != nRet) | |
{ | |
return nRet; | |
} | |
size_t nLen; | |
_Read((char *)&t_data_head, sizeof(tDataHead)); | |
_GetDataHead(nType, nLen); | |
sBuf.resize(nLen); | |
_Read(reinterpret_cast<char *>(&sBuf[0]), nLen); | |
return 0; | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef FIFO_CACHE | |
#define FIFO_CACHE | |
#include <stdint.h> | |
#include <time.h> | |
#include <string.h> | |
#include <errno.h> | |
#include <stdio.h> | |
#include <iostream> | |
#include <string> | |
#include <unistd.h> | |
#include <sys/types.h> | |
#include <sys/ipc.h> | |
#include <sys/shm.h> | |
#include <sys/file.h> | |
#pragma pack(1) | |
struct tFifoCacheMeta | |
{ | |
volatile size_t head_place; | |
volatile size_t tail_place; | |
size_t cache_size; | |
size_t usage_space; | |
tFifoCacheMeta() | |
{ | |
Reset(); | |
} | |
void Reset() | |
{ | |
head_place = 0; | |
tail_place = 0; | |
cache_size = 0; | |
usage_space = 0; | |
} | |
void ShowMetaInfo(){std::cout << " head: " << head_place | |
<< " tail: " << tail_place | |
<< " size: " << cache_size | |
<< " usage: " << usage_space << std::endl;} | |
}; | |
struct tDataHead{ | |
uint32_t data_type; | |
size_t data_len; | |
uint32_t checksum; | |
}; | |
#pragma pack() | |
class tFifoCache | |
{ | |
public: | |
tFifoCache(const int32_t nKey, const size_t nUserSize) | |
: n_key(nKey) | |
{ | |
n_data_size = nUserSize + 1; | |
n_total_size = n_data_size + sizeof(tFifoCacheMeta); | |
p_cache_buffer = reinterpret_cast<char *>(-1); | |
p_data_buffer = NULL; | |
} | |
virtual ~tFifoCache(); | |
int Write(const char* buf, const size_t len, const uint32_t type); | |
int Read(std::string &buf, uint32_t &type); | |
void Reset(); | |
int Init(); | |
private: | |
int n_key; | |
size_t n_total_size; | |
size_t n_data_size; | |
tFifoCacheMeta *p_meta_info; | |
void *p_cache_buffer; | |
char *p_data_buffer; | |
tDataHead t_data_head; | |
size_t _GetFillLength(); | |
size_t _GetFreeLength(); | |
void _SetDataHead(const uint32_t nType, const size_t nLen); | |
void _GetDataHead(uint32_t &nType, size_t &nLen); | |
void _Write(const char *buf, const size_t len); | |
void _Read(char *buf, const size_t len, bool update_ptr = true); | |
int _Peek(); | |
}; | |
#endif | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include "fifo_cache.h" | |
#define BUF_LEN 1024*100 | |
int main(int argc, char *argv[]) | |
{ | |
tFifoCache mem_obj(0x20151103, 1024*1024); | |
int ret = mem_obj.Init(); | |
if (ret!=0) | |
{ | |
printf("Init failed: %d\n", ret); | |
return -1; | |
} | |
char buf[BUF_LEN]; | |
std::string out; | |
uint32_t type; | |
uint32_t value = 1; | |
while(true) | |
{ | |
memcpy(buf, (void *)&value, sizeof(uint32_t)); | |
ret = mem_obj.Write(buf, BUF_LEN, value); | |
if (ret) break; | |
printf("write value=%u\n", value); | |
value ++; | |
} | |
while(true) | |
{ | |
ret = mem_obj.Read(out, type); | |
if(ret) break; | |
memcpy((void *)&value, out.c_str(), sizeof(uint32_t)); | |
printf("value=%u, type=%u\n", value, type); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment