Skip to content

Commit 41a2ca0

Browse files
committed
Clean Project Structure And Change Name Of Area
1 parent ca9e937 commit 41a2ca0

30 files changed

+509
-5660
lines changed

CMakeLists.txt

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
cmake_minimum_required(VERSION 3.3)
2+
3+
PROJECT (Wolf)
4+
5+
ADD_COMPILE_OPTIONS(-std=c++11 -g -Wall)
6+
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
7+
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/)
8+
9+
SET (SRCS
10+
demo/cpp_demo.cpp
11+
)
12+
13+
ADD_EXECUTABLE(demo ${SRCS})

WolfEvent.py

-54
This file was deleted.

area/shm_area.h

+129
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
//
2+
// shm_allocator.h
3+
// ShmArea
4+
//
5+
// Created by Winger Cheng on 2018/1/14.
6+
// Copyright © 2018年 Winger Cheng. All rights reserved.
7+
//
8+
9+
#pragma once
10+
11+
12+
#include <fcntl.h>
13+
#include <sys/mman.h>
14+
#include <sys/stat.h>
15+
#include <unistd.h>
16+
#include <atomic>
17+
#include <exception>
18+
#include <string>
19+
#include <cassert>
20+
21+
namespace area {
22+
class ShmAreaException : public std::exception {
23+
public:
24+
ShmAreaException(uint32_t need, uint32_t used, uint32_t max)
25+
: need_(need), used_(used), max_(max) {}
26+
27+
virtual const char *what() const throw() {
28+
return "No Enough Memory For Alloc Bytes";
29+
}
30+
31+
private:
32+
uint32_t need_;
33+
uint32_t used_;
34+
uint32_t max_;
35+
};
36+
37+
struct SuperBlock {
38+
std::atomic<uint32_t> memory_usage{0};
39+
std::atomic<uint32_t> max_memory_size{0};
40+
};
41+
42+
class ShmArea {
43+
public:
44+
ShmArea(const std::string &shm_path, uint32_t max_memory_size,
45+
bool force_reset = false)
46+
: begin_alloc_ptr_(nullptr), super_block_(nullptr) {
47+
this->shm_fd_ = open(shm_path.c_str(), O_CREAT | O_RDWR, 0660);
48+
49+
fchmod(this->shm_fd_, S_IRWXU | S_IRWXG);
50+
51+
uint32_t memory_file_size = this->Init(max_memory_size, force_reset);
52+
// 共享内存文件已经初始化完毕, 进行成员变量填充
53+
char *shared_mem =
54+
(char *)mmap(NULL, memory_file_size, PROT_READ | PROT_WRITE, MAP_SHARED,
55+
this->shm_fd_, 0);
56+
this->super_block_ = (SuperBlock *)shared_mem;
57+
this->begin_alloc_ptr_ = shared_mem + sizeof(SuperBlock);
58+
};
59+
60+
char *Allocate(uint32_t bytes) {
61+
assert(bytes > 0);
62+
uint32_t current_memory_usage = this->super_block_->memory_usage.load();
63+
uint32_t max_memory_size = this->super_block_->max_memory_size.load();
64+
65+
if (bytes > max_memory_size - current_memory_usage) {
66+
throw ShmAreaException(bytes, current_memory_usage, max_memory_size);
67+
}
68+
69+
// 对共享内存中存储的memory_usage进行CAS操作,
70+
// 如果之前获取的current_memory_usage与当前共享内存中的值不一致
71+
// 则共享内存在此期间已经对外分配过, 需要重新load current_memory_usage的值,
72+
// 再次进行CAS操作, 以保证获取到bytes字节不会被别的线程/进程使用
73+
while (!this->super_block_->memory_usage.compare_exchange_strong(
74+
current_memory_usage, current_memory_usage + bytes)) {
75+
current_memory_usage = this->super_block_->memory_usage.load();
76+
}
77+
78+
// 对于同一块共享内存来说begin_alloc_ptr永远不变, 所以current_memory_usage +
79+
// begin_alloc_ptr可以确定一块内存的分配点
80+
return this->begin_alloc_ptr_ + current_memory_usage;
81+
}
82+
83+
uint32_t MemoryUsage() const {
84+
return this->super_block_->memory_usage.load();
85+
}
86+
87+
char *MemoryStart() const { return this->begin_alloc_ptr_; }
88+
89+
private:
90+
// Init函数可以多进程/线程调用, 但是实际对SharedMemory的Init操作只会被执行一次
91+
// force_reset很危险, 可以直接初始化SuperBlock中的参数,
92+
// 无论这块共享内存是否初始化过
93+
uint32_t Init(uint32_t max_memory_size, bool force_reset = false) {
94+
assert(max_memory_size > 0);
95+
// 对共享内存文件上锁, lockf基于POSIX是线程安全的上锁方式
96+
::lockf(this->shm_fd_, F_LOCK, 0);
97+
98+
// 为了获取当前文件的大小
99+
struct stat file_stat;
100+
if (::fstat(this->shm_fd_, &file_stat) == -1) {
101+
/* TODO: check the value of errno */
102+
}
103+
104+
uint32_t init_memory_file_size = (uint32_t)file_stat.st_size;
105+
106+
// 如果文件大小小于SuperBlock的大小, 则认为这块共享内存文件没有初始化过
107+
if (force_reset || init_memory_file_size < sizeof(SuperBlock)) {
108+
init_memory_file_size = sizeof(SuperBlock) + max_memory_size;
109+
::ftruncate(this->shm_fd_, init_memory_file_size);
110+
this->super_block_ =
111+
(SuperBlock *)mmap(NULL, sizeof(SuperBlock), PROT_READ | PROT_WRITE,
112+
MAP_SHARED, this->shm_fd_, 0);
113+
this->super_block_->max_memory_size.store(max_memory_size);
114+
this->super_block_->memory_usage.store(0);
115+
munmap(this->super_block_, sizeof(SuperBlock));
116+
}
117+
118+
// 成员变量的填充不需要对文件进行操作, 所以在这里就可以解锁
119+
::lockf(this->shm_fd_, F_ULOCK, 0);
120+
121+
return init_memory_file_size;
122+
}
123+
124+
private:
125+
uint32_t shm_fd_;
126+
char *begin_alloc_ptr_;
127+
SuperBlock *super_block_;
128+
};
129+
} // namespace area

container/comparator.h

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//
2+
// comparator.cpp
3+
// Wolf
4+
//
5+
// Created by Winger Cheng on 2018/2/17.
6+
// Copyright © 2018年 Winger Cheng. All rights reserved.
7+
//
8+
9+
#pragma once
10+
namespace container{
11+
12+
template<typename Key>
13+
struct DefaultComparator {
14+
int operator()(const Key& left, const Key& right) const {
15+
if (left < right) {
16+
return -1;
17+
} else if (left > right) {
18+
return 1;
19+
} else {
20+
return 0;
21+
}
22+
}
23+
};
24+
25+
}
File renamed without changes.

lockfree_skiplist.h renamed to container/lockfree_skiplist.h

+14-21
Original file line numberDiff line numberDiff line change
@@ -6,35 +6,23 @@
66
// Copyright © 2018年 Winger Cheng. All rights reserved.
77
//
88
// Key必须是POD类型
9-
9+
#pragma once
1010

1111
#include <string>
1212
#include <atomic>
1313
#include <random>
1414
#include <chrono>
1515

16+
#include "comparator.h"
1617
#include "shm_manager.h"
1718
#include "random.h"
1819

19-
namespace skiplist{
20-
21-
template<typename Key>
22-
struct DefaultComparator {
23-
int operator()(const Key& a, const Key& b) const {
24-
if (a < b) {
25-
return -1;
26-
} else if (a > b) {
27-
return +1;
28-
} else {
29-
return 0;
30-
}
31-
}
32-
};
20+
namespace container{
3321

3422
template<typename Key, class Comparator = DefaultComparator<Key>>
3523
class LockFreeSkipList {
3624
public:
37-
const static int kMaxHeight {24};
25+
const static int kMaxHeight {12};
3826
private:
3927
// 这部分Node需要放在共享内存中, 所以需要是POD类型
4028
// TODO:: 共享内存中最大的Node数量受限于Node的size和next中存储的索引值的上限,即如果next使用long则无法做无锁mark
@@ -86,9 +74,9 @@ struct LockFreeSkipList<Key, Comparator>::Ref {
8674

8775
template<typename Key, class Comparator>
8876
struct LockFreeSkipList<Key, Comparator>::Node {
89-
Node(int in_key, uint32_t in_offset, int in_height): key(in_key),
90-
self_offset(in_offset),
91-
height(in_height) {
77+
Node(int in_key, uint32_t in_offset, int in_height): height(in_height),
78+
key(in_key),
79+
self_offset(in_offset) {
9280
for (int i=0; i<kMaxHeight; ++i) {
9381
this->ref[i] = {0, false};
9482
}
@@ -112,10 +100,10 @@ template<typename Key, class Comparator>
112100
LockFreeSkipList<Key, Comparator>::LockFreeSkipList(ShmManager* shm_manager,
113101
bool reset,
114102
Comparator cmp):
115-
shm_manager_(shm_manager),
116103
//rnd_(static_cast<unsigned int>(std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()))),
117104
rnd_(0xdeadbeef),
118-
compare_(cmp) {
105+
compare_(cmp),
106+
shm_manager_(shm_manager) {
119107

120108
if (reset) {
121109
this->head_ = this->NewNode(0, kMaxHeight);
@@ -263,7 +251,12 @@ bool LockFreeSkipList<Key, Comparator>::Add(Key key) {
263251
Node* second_nodes[kMaxHeight];
264252

265253
while (true) {
254+
// auto first = std::chrono::system_clock::now();
266255
bool found = this->FindWindow(key, first_nodes, second_nodes);
256+
// auto second = std::chrono::system_clock::now();
257+
// std::cout
258+
// << " Time: " << std::chrono::duration_cast<std::chrono::nanoseconds>(second - first).count() << " us"
259+
// << std::endl;
267260
if (found) {
268261
// 不支持重复的Key
269262
return false;
File renamed without changes.

shm_manager.h renamed to container/shm_manager.h

+7-8
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,23 @@
66
// Copyright © 2018年 Winger Cheng. All rights reserved.
77
//
88

9-
#ifndef shm_manager_h
10-
#define shm_manager_h
9+
#pragma once
1110

1211
#include <utility>
13-
#include "shm_allocator.h"
12+
#include "area/shm_area.h"
1413

14+
namespace container {
1515

1616
class ShmManager {
1717
public:
18-
ShmManager(ShmAllocator* allocator);
18+
ShmManager(area::ShmArea* allocator);
1919
std::pair<uint32_t, char*> Allocate(int bytes);
2020
char* GetBufferByIndex(uint32_t index);
2121
private:
22-
ShmAllocator* allocator_;
22+
area::ShmArea* allocator_;
2323
};
2424

25-
ShmManager::ShmManager(ShmAllocator* allocator): allocator_(allocator) {}
25+
ShmManager::ShmManager(area::ShmArea* allocator): allocator_(allocator) {}
2626

2727
std::pair<uint32_t, char*> ShmManager::Allocate(int bytes) {
2828
char* buffer = this->allocator_->Allocate(bytes);
@@ -34,5 +34,4 @@ char* ShmManager::GetBufferByIndex(uint32_t index) {
3434
return this->allocator_->MemoryStart() + index;
3535
}
3636

37-
38-
#endif /* shm_manager_h */
37+
}

0 commit comments

Comments
 (0)