Skip to content

Commit 304196e

Browse files
authored
Merge pull request #141 from OlehKniaziev/73-free-server-connections
Free server connections
2 parents a827d2c + 9dc8c71 commit 304196e

File tree

4 files changed

+198
-45
lines changed

4 files changed

+198
-45
lines changed

src/Core/ok.hpp

Lines changed: 123 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,57 +71,67 @@
7171
#define OK_ASSERT(x) do { \
7272
if (!(x)) { \
7373
OK_LOG_ERROR("%s:%d: Assertion failed: %s\n", __FILE__, __LINE__, #x); \
74+
/* @Portability */ \
7475
__builtin_trap(); \
7576
} \
7677
} while(0)
7778
#endif // OK_ASSERT
7879
#else
7980
#define OK_ASSERT(x)
80-
#endif // OK_DEBUG
81+
#endif // OK_STRIP_ASSERTIONS
8182

83+
// NOTE(oleh): All of thsse are pretty much duplicates.
8284
#define OK_VERIFY(x) do { \
8385
if (!(x)) { \
8486
OK_LOG_ERROR("%s:%d: Verification failed: %s\n", __FILE__, __LINE__, #x); \
87+
/* @Portability */ \
8588
__builtin_trap(); \
8689
} \
8790
} while(0)
8891

8992
#define OK_TODO() do { \
9093
OK_LOG_ERROR("%s:%d: TODO: Not implemented\n", __FILE__, __LINE__); \
94+
/* @Portability */ \
9195
__builtin_trap(); \
9296
} while (0)
9397

9498
#define OK_TODO_MSG(msg) do { \
9599
OK_LOG_ERROR("%s:%d: TODO: " msg "\n", __FILE__, __LINE__); \
100+
/* @Portability */ \
96101
__builtin_trap(); \
97102
} while (0)
98103

99104
#define OK_TODO_MSG_FMT(fmt, ...) do { \
100105
OK_LOG_ERROR("%s:%d: TODO: " fmt "\n", __FILE__, __LINE__, __VA_ARGS__); \
106+
/* @Portability */ \
101107
__builtin_trap(); \
102108
} while (0)
103109

104110
#define OK_UNUSED(arg) (void)(arg)
105111

106112
#define OK_UNREACHABLE() do { \
107113
OK_LOG_ERROR("%s:%d: Encountered unreachable code\n", __FILE__, __LINE__); \
114+
/* @Portability */ \
108115
__builtin_trap(); \
109116
} while (0)
110117

111118
#define OK_PANIC(msg) do { \
112119
OK_LOG_ERROR("%s:%d: PROGRAM PANICKED: %s\n", __FILE__, __LINE__, (msg)); \
120+
/* @Portability */ \
113121
__builtin_trap(); \
114122
} while (0)
115123

116124
#define OK_PANIC_FMT(fmt, ...) do { \
117125
OK_LOG_ERROR("%s:%d: PROGRAM PANICKED: " fmt "\n", __FILE__, __LINE__, __VA_ARGS__); \
126+
/* @Portability */ \
118127
__builtin_trap(); \
119128
} while (0)
120129

121130
#define OK_ARR_LEN(xs) (sizeof((xs)) / sizeof((xs)[0]))
122131

123132
#if defined(__unix__) || defined(__unix) || defined(__APPLE__)
124133

134+
// NOTE(oleh): No need for values here.
125135
#define OK_UNIX 1
126136
#define OK_WINDOWS 0
127137

@@ -130,10 +140,12 @@
130140
#include <unistd.h>
131141
#include <spawn.h>
132142

143+
// @Customization
133144
#define OK_ALLOC_PAGE(sz) (mmap(NULL, (sz), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0))
134145
#define OK_DEALLOC_PAGE(page, size) (munmap((page), (size)))
135146
#define OK_ALLOC_SMOL(sz) (sbrk((sz)))
136147

148+
// @Customization
137149
#define OK_PAGE_SIZE 4096
138150
#define OK_PAGE_ALIGN OK_PAGE_SIZE
139151

@@ -151,15 +163,18 @@
151163
#undef max
152164
#undef min
153165

166+
// @Customization
154167
#define OK_PAGE_SIZE 4096
155168
#define OK_PAGE_ALIGN (64 * 1024)
156169

170+
// @Customization
157171
#define OK_ALLOC_PAGE(sz) (VirtualAlloc(nullptr, (sz), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE))
158172
#define OK_DEALLOC_PAGE(page, size) (VirtualFree((page), 0, MEM_RELEASE))
159173
#define OK_ALLOC_SMOL(sz) (HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (sz)))
160174

161175
#elif defined(__wasm__)
162176

177+
// NOTE(oleh): Once again, these should be empty defs.
163178
#define OK_UNIX 0
164179
#define OK_WINDOWS 0
165180
#define OK_WASM 1
@@ -175,7 +190,7 @@
175190
#elif SIZE_MAX == UINT64_MAX
176191
# define OK_BITS_64
177192
#else
178-
# error "Could not determine architecture bit size"
193+
# error "Could not determine word size"
179194
#endif // word size check
180195

181196
using U8 = uint8_t;
@@ -222,6 +237,7 @@ namespace ok {
222237
# define OK_PAGE_ALIGN OK_PAGE_SIZE
223238
# endif // OK_PAGE_ALIGN
224239

240+
// NOTE(oleh): This should be optional.
225241
# ifndef OK_VSNPRINTF
226242
# error "you have to define `OK_VSNPRINTF` when compiling with `OK_NO_STDLIB`"
227243
# endif // OK_VSNPRINTF
@@ -310,6 +326,7 @@ struct Allocator {
310326
Slice<T> alloc_slice(UZ);
311327
};
312328

329+
// NOTE(oleh): This should be removed in favor of temp allocator handles.
313330
Allocator *temp_allocator();
314331

315332
struct FixedBufferAllocator : public Allocator {
@@ -378,6 +395,7 @@ struct ArenaAllocator : public Allocator {
378395
}
379396

380397
inline void free() {
398+
// @Leak
381399
for (Region* r = head; r != nullptr; r = r->next) OK_DEALLOC_PAGE(head->data, head->size);
382400
}
383401

@@ -576,6 +594,7 @@ Slice<T> Allocator::alloc_slice(UZ count) {
576594
return Slice<T>{ptr, count};
577595
}
578596

597+
// NOTE(oleh): Just remove this. It's a mess.
579598
template <typename T>
580599
struct MultiListBase {
581600
T *items;
@@ -750,6 +769,7 @@ struct String;
750769
#define OK_SV_FMT "%.*s"
751770
#define OK_SV_ARG(sv) (int)(sv).count, reinterpret_cast<const char*>((sv).data)
752771

772+
// NOTE(oleh): This needs more methods.
753773
template <typename Self, typename Char>
754774
struct StringBase : public ArrayBase<Self, Char> {
755775
inline bool starts_with(const char* prefix) const {
@@ -1062,20 +1082,23 @@ struct Pair {
10621082
B b;
10631083
};
10641084

1085+
// NOTE(oleh): We need more hash implementations, or at least a better default.
10651086
namespace hash {
10661087
U64 fnv1(StringView);
10671088
};
10681089

10691090
template <typename T>
10701091
struct Hash {
10711092
static U64 hash(const T& value) {
1093+
// NOTE(oleh): Just make this a function, not a method.
10721094
return value.ok_hash_value();
10731095
}
10741096
};
10751097

10761098
template <typename T>
10771099
struct HashPtr {
10781100
HashPtr(const T* v) : value{v} {}
1101+
// @Dead
10791102
HashPtr(T* v) : value{v} {}
10801103

10811104
inline bool operator ==(const T* ptr) const {
@@ -1085,7 +1108,10 @@ struct HashPtr {
10851108
const T* value;
10861109
};
10871110

1111+
// NOTE(oleh): Remove these all in favor of `ok_hash_value`.
1112+
10881113
// Default hash implementations
1114+
// NOTE(oleh): Is this even needed?
10891115
template <typename T>
10901116
struct Hash<HashPtr<T>> {
10911117
static U64 hash(const HashPtr<T>& ptr) {
@@ -1161,14 +1187,27 @@ struct Table {
11611187

11621188
void put(const TKey& key, const TValue& value);
11631189

1164-
Optional<TValue> get(const TKey& key);
1190+
// NOTE(oleh): Not sure if we need the `get_ref` methods.
1191+
// Also not sure if we shouldn't just keep the template overloads?
1192+
Optional<TValue> get(const TKey& key) const;
1193+
11651194
template <typename K>
1166-
Optional<TValue> get(const K& key);
1195+
Optional<TValue> get(const K& key) const;
1196+
1197+
Optional<TValue&> get_ref(const TKey& key);
1198+
Optional<const TValue&> get_ref(const TKey& key) const;
1199+
1200+
template <typename K>
1201+
Optional<TValue&> get_ref(const K& key);
1202+
template <typename K>
1203+
Optional<const TValue&> get_ref(const K& key) const;
11671204

11681205
bool has(const TKey& key) const;
11691206
template <typename K>
11701207
bool has(const K& key) const;
11711208

1209+
bool remove(const TKey&);
1210+
11721211
static constexpr UZ DEFAULT_CAPACITY = 47;
11731212

11741213
inline void clear() {
@@ -1200,7 +1239,7 @@ struct Table {
12001239
allocator->dealloc(keys, capacity);
12011240
allocator->dealloc(values, capacity);
12021241

1203-
memset(this, 0, sizeof(this));
1242+
memset(this, 0, sizeof(*this));
12041243
}
12051244

12061245
TKey* keys;
@@ -1478,7 +1517,7 @@ void Table<K, V>::put(const K& key, const V& value) {
14781517
}
14791518

14801519
template <typename K, typename V>
1481-
Optional<V> Table<K, V>::get(const K& key) {
1520+
Optional<V> Table<K, V>::get(const K& key) const {
14821521
U64 idx = Hash<K>::hash(key) % capacity;
14831522
U64 initial_idx = idx;
14841523

@@ -1495,7 +1534,7 @@ Optional<V> Table<K, V>::get(const K& key) {
14951534

14961535
template <typename TKey, typename TValue>
14971536
template <typename K>
1498-
Optional<TValue> Table<TKey, TValue>::get(const K& key) {
1537+
Optional<TValue> Table<TKey, TValue>::get(const K& key) const {
14991538
U64 idx = Hash<K>::hash(key) % capacity;
15001539
U64 initial_idx = idx;
15011540

@@ -1510,6 +1549,72 @@ Optional<TValue> Table<TKey, TValue>::get(const K& key) {
15101549
return Optional<TValue>::empty();
15111550
}
15121551

1552+
template <typename K, typename V>
1553+
Optional<V&> Table<K, V>::get_ref(const K& key) {
1554+
U64 idx = Hash<K>::hash(key) % capacity;
1555+
U64 initial_idx = idx;
1556+
1557+
do {
1558+
if (OK_TAB_IS_OCCUPIED(meta[idx]) && keys[idx] == key) {
1559+
return values[idx];
1560+
}
1561+
1562+
idx = (idx + 1) % capacity;
1563+
} while (idx != initial_idx);
1564+
1565+
return Optional<V&>::empty();
1566+
}
1567+
1568+
template <typename K, typename V>
1569+
Optional<const V&> Table<K, V>::get_ref(const K& key) const {
1570+
U64 idx = Hash<K>::hash(key) % capacity;
1571+
U64 initial_idx = idx;
1572+
1573+
do {
1574+
if (OK_TAB_IS_OCCUPIED(meta[idx]) && keys[idx] == key) {
1575+
return values[idx];
1576+
}
1577+
1578+
idx = (idx + 1) % capacity;
1579+
} while (idx != initial_idx);
1580+
1581+
return Optional<const V&>::empty();
1582+
}
1583+
1584+
template <typename TKey, typename TValue>
1585+
template <typename K>
1586+
Optional<TValue&> Table<TKey, TValue>::get_ref(const K& key) {
1587+
U64 idx = Hash<K>::hash(key) % capacity;
1588+
U64 initial_idx = idx;
1589+
1590+
do {
1591+
if (OK_TAB_IS_OCCUPIED(meta[idx]) && keys[idx] == key) {
1592+
return values[idx];
1593+
}
1594+
1595+
idx = (idx + 1) % capacity;
1596+
} while (idx != initial_idx);
1597+
1598+
return Optional<TValue&>::empty();
1599+
}
1600+
1601+
template <typename TKey, typename TValue>
1602+
template <typename K>
1603+
Optional<const TValue&> Table<TKey, TValue>::get_ref(const K& key) const {
1604+
U64 idx = Hash<K>::hash(key) % capacity;
1605+
U64 initial_idx = idx;
1606+
1607+
do {
1608+
if (OK_TAB_IS_OCCUPIED(meta[idx]) && keys[idx] == key) {
1609+
return values[idx];
1610+
}
1611+
1612+
idx = (idx + 1) % capacity;
1613+
} while (idx != initial_idx);
1614+
1615+
return Optional<const TValue&>::empty();
1616+
}
1617+
15131618
template <typename K, typename V>
15141619
bool Table<K, V>::has(const K& key) const {
15151620
U64 idx = Hash<K>::hash(key) % capacity;
@@ -1526,7 +1631,6 @@ bool Table<K, V>::has(const K& key) const {
15261631
return false;
15271632
}
15281633

1529-
15301634
template <typename TKey, typename TValue>
15311635
template <typename K>
15321636
bool Table<TKey, TValue>::has(const K& key) const {
@@ -1544,6 +1648,16 @@ bool Table<TKey, TValue>::has(const K& key) const {
15441648
return false;
15451649
}
15461650

1651+
// NOTE(oleh): Should we call destructors here?
1652+
template <typename TKey, typename TValue>
1653+
bool Table<TKey, TValue>::remove(const TKey& key) {
1654+
U64 idx = Hash<TKey>::hash(key) % capacity;
1655+
bool result = OK_TAB_IS_OCCUPIED(meta[idx]);
1656+
if (result) --count;
1657+
meta[idx] &= ~OK_TAB_META_OCCUPIED;
1658+
return result;
1659+
}
1660+
15471661
// SET IMPLEMENTATION
15481662
template <typename T>
15491663
Set<T> Set<T>::alloc(Allocator* a, UZ capacity) {
@@ -1715,6 +1829,7 @@ struct File {
17151829
};
17161830

17171831
// Procedures.
1832+
// NOTE(oleh): These should accept format strings like `std::print`.
17181833
void println(const char*);
17191834
void println(StringView);
17201835
void println(String);

0 commit comments

Comments
 (0)