lockfree.h

main 78 lines · 2.6 KB Raw
Alex Alex Commit Server upload 18/10/2026 23:38
1/**
2 * The Forgotten Server - a free and open-source MMORPG server emulator
3 * Copyright (C) 2019 Mark Samman <mark.samman@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20#ifndef FS_LOCKFREE_H_8C707AEB7C7235A2FBC5D4EDDF03B008
21#define FS_LOCKFREE_H_8C707AEB7C7235A2FBC5D4EDDF03B008
22
23#if _MSC_FULL_VER >= 190023918 // Workaround for VS2015 Update 2. Boost.Lockfree is a header-only library, so this should be safe to do.
24#define _ENABLE_ATOMIC_ALIGNMENT_FIX
25#endif
26
27#include <boost/lockfree/stack.hpp>
28
29/*
30 * we use this to avoid instantiating multiple free lists for objects of the
31 * same size and it can be replaced by a variable template in C++14
32 *
33 * template <std::size_t TSize, size_t CAPACITY>
34 * boost::lockfree::stack<void*, boost::lockfree::capacity<CAPACITY> lockfreeFreeList;
35 */
36template <std::size_t TSize, size_t CAPACITY>
37struct LockfreeFreeList
38{
39 using FreeList = boost::lockfree::stack<void*, boost::lockfree::capacity<CAPACITY>>;
40 static FreeList& get()
41 {
42 static FreeList freeList;
43 return freeList;
44 }
45};
46
47template <typename T, size_t CAPACITY>
48class LockfreePoolingAllocator : public std::allocator<T>
49{
50 public:
51 LockfreePoolingAllocator() = default;
52
53 template <typename U, class = typename std::enable_if<!std::is_same<U, T>::value>::type>
54 explicit constexpr LockfreePoolingAllocator(const U&) {}
55 using value_type = T;
56
57 T* allocate(size_t) const {
58 auto& inst = LockfreeFreeList<sizeof(T), CAPACITY>::get();
59 void* p; // NOTE: p doesn't have to be initialized
60 if (!inst.pop(p)) {
61 //Acquire memory without calling the constructor of T
62 p = operator new (sizeof(T));
63 }
64 return static_cast<T*>(p);
65 }
66
67 void deallocate(T* p, size_t) const {
68 auto& inst = LockfreeFreeList<sizeof(T), CAPACITY>::get();
69 if (!inst.bounded_push(p)) {
70 //Release memory without calling the destructor of T
71 //(it has already been called at this point)
72 operator delete(p);
73 }
74 }
75};
76
77#endif
78
Top