cmake_minimum_required(VERSION 3.0.0)
project(hash VERSION 0.1.0)
MESSAGE(${PROJECT_SOURCE_DIR})
SET(
APP_SRC
${PROJECT_SOURCE_DIR}/main.cpp
${PROJECT_SOURCE_DIR}/PortMapHashtable.cpp
)
add_executable(${PROJECT_NAME} ${APP_SRC})
add_compile_options(-Wall)
target_link_libraries(${PROJECT_NAME} pthread)
#include <iostream>
#include <windows.h>
#include "PortMapHashtable.h"
using std::cout;
PortMapHashtable test;
int port = 50,ip = 100;
void TEST_1() {
test.InsertPort(1,123,456);
test.InsertPort(1,123,789);
test.InsertPort(10,123,456);
test.InsertPort(12,12,12);
cout << test.GetBindPort(1,123) << "\n";
cout << test.GetBindPort(456,456) << "\n";
cout << test.GetBindPort(10,123) << "\n";
cout << test.GetBindPort(12,12) << "\n";
}
void* readFunc(void*);
void* writeFunc(void*);
void TEST_2() {
pthread_t readThread[2];
pthread_t writeThread[2];
pthread_create(readThread + 0, nullptr, readFunc, nullptr);
pthread_create(writeThread + 0, nullptr, writeFunc, nullptr);
pthread_create(readThread + 1, nullptr, readFunc, nullptr);
pthread_create(writeThread + 1, nullptr, writeFunc, nullptr);
for (int i = 0;i < 2;++i) {
pthread_join(readThread[i], nullptr);
pthread_join(writeThread[i], nullptr);
}
}
int main() {
if (test.Init()) {
// TEST_1();
TEST_2();
}
else {
cout << "初始化失败!\n";
}
return 0;
}
void* writeFunc(void*) {
while (1) {
++port;
test.InsertPort(ip,100,port);
// printf("w data:%6d, tid:%6d\n", port, pthread_self());
}
}
void* readFunc(void*) {
while (1) {
int result = test.GetBindPort(ip,100);
// printf("r data:%6d, tid:%6d\n",result, pthread_self());
}
}
#include "PortMapHashtable.h"
#include <iostream>
#include <algorithm>
#include <cstring>
#include <stdlib.h>
#include <pthread.h>
#include <windows.h>
using std::cout;
using std::endl;
HashTableIndexNode::HashTableIndexNode(VOS_UINT32 key,VOS_UINT16* value)
: key(key),value(value)
{}
bool HashTableIndexNode::operator < (const HashTableIndexNode rhs) const {
return key < rhs.key;
}
static VOS_VOID ErrorLog(const char * const errLog) {
printf("%s\n",errLog);
}
PortMapHashtable::PortMapHashtable()
:m_numOfIp(0)
{}
PortMapHashtable::~PortMapHashtable() {
pthread_rwlock_destroy(&rwlock);
}
VOS_BOOL PortMapHashtable::Init() {
for (auto i = 0;i < m_numOfIp;++i) {
if (m_ipToTableIndex[i].value != nullptr) {
free(m_ipToTableIndex[i].value);
m_ipToTableIndex[i].value = nullptr;
}
}
m_numOfIp = 0;
auto lockInitResult = pthread_rwlock_init(&rwlock,nullptr);
if (lockInitResult == 0) {
return VOS_TRUE;
}
else {
ErrorLog("ReadWriteLock init fail");
return VOS_FALSE;
}
}
VOS_BOOL PortMapHashtable::InsertPort(VOS_UINT32 ip,VOS_UINT16 portIn,VOS_UINT16 portOut) {
using std::swap;
auto hashTablePtr = GetHashTablePtr(ip);
if (hashTablePtr == nullptr) {
if (m_numOfIp == MAXIMUM_NUMBER_OF_MACHINE) {
ErrorLog("Too much machine");
return VOS_FALSE;
}
else {
// 加读写锁
auto initHashTablePtr = InitHashTable();
if (initHashTablePtr == nullptr) {
ErrorLog("initHashTablePtr == nullptr");
return VOS_FALSE;
}
else {
AddHashTable(ip,portIn,portOut,initHashTablePtr);
return VOS_TRUE;
}
}
}
else {
hashTablePtr[portIn] = portOut;
return VOS_TRUE;
}
}
VOS_VOID PortMapHashtable::AddHashTable(VOS_UINT32 ip,VOS_UINT16 portIn,VOS_UINT16 portOut,VOS_UINT16* initHashTablePtr) {
using std::swap;
pthread_rwlock_wrlock(&rwlock);
Sleep(1000);
printf("w data:%6d, tid:%6d\n", portOut, pthread_self());
m_ipToTableIndex[m_numOfIp] = HashTableIndexNode(ip,initHashTablePtr);
initHashTablePtr[portIn] = portOut;
for (VOS_UINT32 i = m_numOfIp; i > 0; --i) {
if (m_ipToTableIndex[i - 1].key > m_ipToTableIndex[i].key) {
swap(m_ipToTableIndex[i - 1].key,m_ipToTableIndex[i].key);
swap(m_ipToTableIndex[i - 1].value,m_ipToTableIndex[i].value);
}
else {
break;
}
}
++m_numOfIp;
pthread_rwlock_unlock(&rwlock);
}
VOS_UINT16* PortMapHashtable::GetHashTablePtr(VOS_UINT32 ip) {
using std::make_pair;
pthread_rwlock_rdlock(&rwlock);
Sleep(1000);
auto lowPtr = std::lower_bound(m_ipToTableIndex,m_ipToTableIndex + m_numOfIp,HashTableIndexNode(ip,nullptr));
auto uppPtr = std::upper_bound(m_ipToTableIndex,m_ipToTableIndex + m_numOfIp,HashTableIndexNode(ip,nullptr));
VOS_UINT16* result = nullptr;
if (lowPtr != uppPtr) {
result = lowPtr -> value;
}
pthread_rwlock_unlock(&rwlock);
return result;
}
VOS_UINT16 PortMapHashtable::GetBindPort(VOS_UINT32 ip,VOS_UINT16 portIn) {
auto hashTablePtr = GetHashTablePtr(ip);
if (hashTablePtr == nullptr) {
ErrorLog("invalid ip");
return 0;
}
else {
return hashTablePtr[portIn];
}
}
VOS_UINT16* PortMapHashtable::InitHashTable() {
constexpr VOS_UINT32 hashTableSize = (1 << 16);
auto ptr = (VOS_UINT16*)malloc(hashTableSize * sizeof(VOS_UINT16));
if (ptr == nullptr) {
ErrorLog("malloc() == nullptr");
return ptr;
}
else {
memset(ptr ,0 ,hashTableSize * sizeof(VOS_UINT16));
return ptr;
}
}
#include <cstdint>
#include <map>
#include <pthread.h>
using VOS_VOID = void;
using VOS_UINT16 = std::uint16_t;
using VOS_UINT32 = std::uint32_t;
using VOS_BOOL = int;
constexpr VOS_BOOL VOS_TRUE = 1;
constexpr VOS_BOOL VOS_FALSE = 0;
struct HashTableIndexNode {
HashTableIndexNode() = default;
HashTableIndexNode(VOS_UINT32 key,VOS_UINT16* value);
VOS_UINT32 key;
VOS_UINT16* value;
bool operator < (const HashTableIndexNode rhs) const;
};
class PortMapHashtable {
public :
static constexpr VOS_UINT32 MAXIMUM_NUMBER_OF_MACHINE = 1000;
public :
PortMapHashtable();
~PortMapHashtable();
VOS_BOOL Init();
VOS_BOOL InsertPort(VOS_UINT32 ip,VOS_UINT16 portIn,VOS_UINT16 portOut);
VOS_UINT16 GetBindPort(VOS_UINT32 ip,VOS_UINT16 portIn);
private :
VOS_VOID AddHashTable(VOS_UINT32 ip,VOS_UINT16 portIn,VOS_UINT16 portOut,VOS_UINT16* initHashTablePtr);
VOS_UINT16* GetHashTablePtr(VOS_UINT32 ip);
VOS_UINT16* InitHashTable();
private :
pthread_rwlock_t rwlock;
HashTableIndexNode m_ipToTableIndex[MAXIMUM_NUMBER_OF_MACHINE];
VOS_UINT32 m_numOfIp;
};
标签:UMF,ip,并发,UINT16,VOS,UINT32,ipToTableIndex,PortMapHashtable
From: https://www.cnblogs.com/XDU-mzb/p/16885398.html