庫地址:
=========================
ST**表示單線程 
//開始監(jiān)聽
bool Start( int nMaxMonitor );
//增加一個監(jiān)聽對象
bool AddMonitor( SOCKET socket );
//等待事件發(fā)生,block無作用
bool WaitEvent( void *eventArray, int &count, bool block );
//增加一個接受連接的操作,有連接進來,WaitEvent會返回
bool AddAccept(SOCKET listenSocket);
//增加一個接收數(shù)據(jù)的操作,有數(shù)據(jù)到達,WaitEvent會返回
bool AddRecv( SOCKET socket, char* recvBuf, unsigned short bufSize );
//增加一個發(fā)送數(shù)據(jù)的操作,發(fā)送完成,WaitEvent會返回
bool AddSend( SOCKET socket, char* dataBuf, unsigned short dataSize );

抽象控制的api
監(jiān)聽套接字對象的方法,
IOCPMonitor
==========================
typedef struct IO_EVENT
{
SOCKET sock;
EventType type;
SOCKET client;
char *pData;
unsigned short uDataSize;
}IO_EVENT;
MemoryPool m_iocpDataPool;//iocp投遞參數(shù)池
typedef struct IOCP_OVERLAPPED
{
/**
* OVERLAPPED類型指針
* 指向完成操作參數(shù)
* 傳遞給AcceptEx()的最后一個參數(shù)
* 傳遞給WSARecv()的第個參數(shù)
* GetQueuedCompletionStatus()返回的第個參數(shù)
*/
OVERLAPPED m_overlapped;
/**
* 指向存有連接進來的客戶端局域網(wǎng)和外網(wǎng)地址的內(nèi)存
* 必須使用動態(tài)分配的內(nèi)存塊
* 傳遞給AcceptEx()的第個參數(shù)
*
*/
char m_outPutBuf[sizeof(SOCKADDR_IN)*2+32];
/**
* 客戶端局域網(wǎng)IP信息長度
* 傳遞給AcceptEx()的第個參數(shù)
*/
unsigned long m_dwLocalAddressLength;
/**
* 客戶端外網(wǎng)IP信息長度
* 傳遞給AcceptEx()的第個參數(shù)
*/
unsigned long m_dwRemoteAddressLength;
WSABUF m_wsaBuffer;//WSARecv接收緩沖數(shù)據(jù),傳遞給WSARecv()的第個參數(shù)
SOCKET sock;
EventType completiontype;//完成類型recv 2send
}IOCP_OVERLAPPED;
IOCPMonitor::Start( int nMaxMonitor )
端口啟動
創(chuàng)建完全端口
線程數(shù)cpu數(shù)*2+2
IOCPMonitor::AddMonitor( SOCKET sock )
加入套接字到 IOCP列隊
IOCPMonitor::WaitEvent( void *eventArray, int &count, bool block )
等待一次完全端口的 事件
GetQueuedCompletionStatus( )
返回不同的iocp事件類型 或 數(shù)據(jù) 供上層循環(huán)控制
IOCPFrame : public NetEngine
繼承了 netengine 的通用和抽象的方法,
同時針對不同的os平臺實例化不同的網(wǎng)絡(luò)模型
IOCPFrame::IOCPFrame()
{
#ifdef WIN32
m_pNetMonitor = new IOCPMonitor;
#endif
IOCPFrame 控制監(jiān)聽 接收 發(fā)送,集成 NetEngine 抽象
Child: one new IOCPMonitor;
class NetServer
{
friend class NetEngine;
NetEngine* m_pNetCard;
Netserver為 主要控制對象,里面抽象了邏輯的控制的 函數(shù),可以繼承城市
同時 NetServer 和 NetEngine 是friend class
NetEngine 里面有監(jiān)聽過程中的 一些寫業(yè)務(wù)的邏輯調(diào)用到 Netserver,幾個抽象的業(yè)務(wù) 接口 實現(xiàn)的地方 就獨立出來了。
NetEngine 業(yè)務(wù)控制抽象的幾種 業(yè)務(wù)調(diào)用
Threeadpool的任務(wù)

三種:業(yè)務(wù)實現(xiàn)
OnConnect
Onclose
OnMsg
比如

監(jiān)聽到鏈接的 調(diào)用NetEngine 調(diào)用了 iocpframe監(jiān)聽 到連接的事件
調(diào)用父輩方法
NetEngine::OnConnect( SOCKET sock, bool isConnectServer )
創(chuàng)建一個 NetConnect對象,通過內(nèi)存池分配的對象
投遞一個 連接的任務(wù)的task給線程池
Onclose
OnMsg
類似
內(nèi)存池設(shè)計
內(nèi)存池 存儲 NetConnect對象,存儲管理netconnect對象 使用memorypool
//初始化內(nèi)存池 預(yù)分配內(nèi)存池
bool Init(unsigned short uMemorySize, unsigned short uMemoryCount);
// //分配內(nèi)存(鏈表方法)
一個線程讀 一個線程寫 無鎖隊列
Iobuffer
包含vector 一張 Iobufferblock 表,存儲多個緩沖塊
讀取的時候
Iobufferblock 托管在內(nèi)存池mempool BUFBLOCK_SIZE大小的內(nèi)存塊
Iobuffer
Readdata
/**
* IO緩沖
* 定義宏BUFBLOCK_SIZE
* 編譯期靜態(tài)確定類大小
* 不能使用指針在運行時動態(tài)指定大小,參考池對象使用限制二
*/
unsigned char m_buffer[BUFBLOCK_SIZE];
//已收到數(shù)據(jù)的長度
unsigned short m_uLength;
//Recv()函數(shù)下次讀取數(shù)據(jù)的開始位置
unsigned short m_uRecvPos;
unsigned short IOBufferBlock::ReadData( unsigned char *data, unsigned short uLength, bool bDel )
從當前讀取位置開始讀取,如果越界 就用剩下的大小獲取
bool IOBuffer::ReadData( unsigned char *data, int uLength, bool bDel )
//這里檢查m_uDataSize不需要原子操作
//cpu與內(nèi)存次交換最小長度就是byte,對于小于等于byte的類型的取值/賦值操作,
//本身就是原子操作
從頭來
遍歷 所有bufferblock 如果是需要刪除的,那么原子操作減一,標志不使用了內(nèi)存池,同時刪除清理block
一讀一寫,沒有線程安全問題
====================
SharedPtr
通過原子加減操作達到 引用計數(shù)操作的線程安全
ShareMemory
依靠viewmap實現(xiàn) 內(nèi)存映射文件
/*
* 創(chuàng)建/打開共享內(nèi)存
* 參數(shù)
* key 全局標識,linux下只接收數(shù)字id
* size 共享大小
* if ( 是創(chuàng)建)
* 則創(chuàng)建size大小的共享內(nèi)存,
* else //是打開已存在的共享內(nèi)存
* if ( 是文件映射&& 是linux系統(tǒng))
* 則使用當前共享內(nèi)存大小與size中較大的一個,作為共享內(nèi)存的大小
* else 無效
* else 無效
* path 使用文件映射的共享內(nèi)存,文件路徑,key為文件名
*/
ShareMemory(const char *key, unsigned long size, const char *path);
/*
* 創(chuàng)建/打開共享內(nèi)存
* 參數(shù)
* key 全局標識
* size 共享大小
* if ( 是創(chuàng)建)
* 則創(chuàng)建size大小的共享內(nèi)存,
* else //是打開已存在的共享內(nèi)存
* if ( 是文件映射&& 是linux系統(tǒng))
* 則使用當前共享內(nèi)存大小與size中較大的一個,作為共享內(nèi)存的大小
* else 無效
* else 無效
* path 使用文件映射的共享內(nèi)存,文件路徑,key為文件名
*/
ShareMemory(const int key, unsigned long size, const char *path);
public:
void* GetBuffer();
unsigned long GetSize();
void Destory();
一次性獲取數(shù)據(jù),初始化的時候指定 了大小了。
內(nèi)存映射文件的方法,沒啥好看的
Signal
采用事件做信號通知,
=========================================
ThreadPool
包含一個vect的任務(wù)隊列 里面帶的就是task
線程池 采用 事件信號通知。執(zhí)行的函數(shù) ThreadFunc
每次從 從m_tasks取任務(wù),加了鎖地取法。
然后執(zhí)行task的里面的Execute 方法 這樣就調(diào)用到 Executor的CallMethod方法 參數(shù)從入隊進入就提交了。
Memorypool

一、
一塊對象數(shù)據(jù)MEMERY_INFO + uMemorySize

二、一個 MemoryPool的 數(shù)據(jù)結(jié)構(gòu)
存儲對象本身 8Byte
每一塊數(shù)據(jù)包含信息8byte 然后就是指向 目標管理對象的對象內(nèi)存
nBlockStartPos += MEMERY_INFO;
pObject = &(m_pMemery[nBlockStartPos]);
內(nèi)存塊數(shù) 初始化的時候 設(shè)置的 m_uMemoryCount

三、Alloc()
找尋本身memorypool是否存在可用內(nèi)存,
有,就直接獲取地址出去使用
沒有的的話遍歷到最后會發(fā)現(xiàn) pBlock->m_pNext 為空,這個時候重新new memorypool對象 教導(dǎo)鏈表上去
m_uFreeCount 未分配的 個數(shù)
通過遍歷 查詢AtomDec pBlock->m_uFreeCount 減1
if ( 0 < (int32)AtomDec(&pBlock->m_uFreeCount, 1) ) break; 執(zhí)行分配
class MemoryPool void* Alloc();
* 無鎖堆(n讀n寫并發(fā),不需加鎖)
* 內(nèi)存池結(jié)構(gòu)
* n個池組成鏈表
*
* 池結(jié)構(gòu)
* 每個池都是一段連續(xù)內(nèi)存保存在char數(shù)組中
* 0~7byte為池地址,后面是n個用于固定長度分配的內(nèi)存塊(即內(nèi)存塊是定長的)
*
* 內(nèi)存塊結(jié)構(gòu)
* 狀態(tài)byte+留空byte+內(nèi)存塊塊序號byte
* 所以一個內(nèi)存池最大可以保存的對象(內(nèi)存塊)數(shù)量為unsigned short的最大值
*
* 狀態(tài)就個(分配/未分配),個byte就可以表示,使用byte是為了使用原子操作實現(xiàn)lock-free,而原子操作操作的是byte地址
* 2byte留空,是為了保證后面用于分配的內(nèi)存守地址都是byte對齊
* 因為真實new出來的對象首地址是保證這點的,
* 且IOCP投遞緩沖struct,也要求首地址對齊,否則返回錯誤
初始化
//預(yù)分配內(nèi)存=MemoryPool對象自身地址,byte,支持位機尋址
//記錄對象地址
//頭個字節(jié)保存對象自身地址,用于從內(nèi)存地址找到內(nèi)存池對象地址
if ( 8 == uAddrSize )
{
m_pMemery[nPos++] = (unsigned char)(uThis >> 56);
m_pMemery[nPos++] = (unsigned char)(uThis >> 48);
m_pMemery[nPos++] = (unsigned char)(uThis >> 40);
m_pMemery[nPos++] = (unsigned char)(uThis >> 32);
}
else
{
m_pMemery[nPos++] = 0;
m_pMemery[nPos++] = 0;
m_pMemery[nPos++] = 0;
m_pMemery[nPos++] = 0;
}
m_pMemery[nPos++] = (unsigned char)(uThis >> 24);
m_pMemery[nPos++] = (unsigned char)(uThis >> 16);
m_pMemery[nPos++] = (unsigned char)(uThis >> 8);
m_pMemery[nPos++] = (unsigned char)uThis;
//初始化內(nèi)存
unsigned short i;
for ( i = 0; i < m_uMemoryCount; i++ )
{
//狀態(tài)未分配
m_pMemery[nPos++] = 0;
m_pMemery[nPos++] = 0;
m_pMemery[nPos++] = 0;
m_pMemery[nPos++] = 0;
//留空字節(jié)
m_pMemery[nPos++] = 0;
m_pMemery[nPos++] = 0;
//保存內(nèi)存序號
m_pMemery[nPos++] = (unsigned char) (i >> 8);
m_pMemery[nPos++] = (unsigned char) i;
nPos += uMemorySize;
}
鏈表 內(nèi)存池組
每個內(nèi)存池
通過對象算出索引
通過索引算出對象都很方便
詳細參考另外一個筆記