Skip to content

Commit 76bb789

Browse files
committed
Add string pool
1 parent ca91ea8 commit 76bb789

File tree

5 files changed

+138
-0
lines changed

5 files changed

+138
-0
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ target_sources(scratchcpp
4040
include/scratchcpp/value_functions.h
4141
include/scratchcpp/stringptr.h
4242
include/scratchcpp/string_functions.h
43+
include/scratchcpp/string_pool.h
4344
include/scratchcpp/entity.h
4445
include/scratchcpp/variable.h
4546
include/scratchcpp/list.h

include/scratchcpp/string_pool.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
3+
#pragma once
4+
5+
#include "global.h"
6+
7+
namespace libscratchcpp
8+
{
9+
10+
struct StringPtr;
11+
12+
extern "C"
13+
{
14+
LIBSCRATCHCPP_EXPORT StringPtr *string_pool_new();
15+
LIBSCRATCHCPP_EXPORT StringPtr *string_pool_new_assign(const char *str);
16+
LIBSCRATCHCPP_EXPORT void string_pool_free(StringPtr *str);
17+
}
18+
19+
} // namespace libscratchcpp

src/scratch/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ target_sources(scratchcpp
33
value_functions.cpp
44
value_functions_p.h
55
string_functions.cpp
6+
string_pool.cpp
7+
string_pool_p.h
68
drawable.cpp
79
drawable_p.cpp
810
drawable_p.h

src/scratch/string_pool.cpp

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
3+
#include <scratchcpp/string_pool.h>
4+
#include <scratchcpp/stringptr.h>
5+
#include <scratchcpp/string_functions.h>
6+
#include <memory>
7+
#include <unordered_set>
8+
#include <unordered_map>
9+
#include <map>
10+
#include <cassert>
11+
12+
namespace libscratchcpp
13+
{
14+
15+
class Thread;
16+
17+
std::unordered_set<std::unique_ptr<StringPtr>> strings;
18+
std::multimap<size_t, StringPtr *> freeStrings; // sorted by allocated space
19+
20+
std::unordered_map<Thread *, std::unordered_set<StringPtr *>> threadStrings;
21+
Thread *currentThread = nullptr;
22+
23+
extern "C"
24+
{
25+
/*! Use this instead of dynamically allocating StringPtr. */
26+
StringPtr *string_pool_new()
27+
{
28+
if (freeStrings.empty()) {
29+
auto str = std::make_unique<StringPtr>();
30+
StringPtr *ptr = str.get();
31+
assert(strings.find(str) == strings.cend());
32+
strings.insert(std::move(str));
33+
34+
if (currentThread)
35+
threadStrings[currentThread].insert(ptr);
36+
37+
return ptr;
38+
}
39+
40+
// Optimization: pick string with the highest capacity to minimize allocs
41+
auto last = std::prev(freeStrings.end());
42+
StringPtr *ptr = last->second;
43+
freeStrings.erase(last);
44+
ptr->size = 0;
45+
46+
if (ptr->allocatedSize > 0)
47+
ptr->data[0] = u'\0';
48+
49+
if (currentThread)
50+
threadStrings[currentThread].insert(ptr);
51+
52+
return ptr;
53+
}
54+
55+
/*! Calls string_pool_new() and assigns the given string. */
56+
StringPtr *string_pool_new_assign(const char *str)
57+
{
58+
StringPtr *ret = string_pool_new();
59+
string_assign_cstring(ret, str);
60+
return ret;
61+
}
62+
63+
/*! Invalidates the given StringPtr so that it can be used for new strings later. */
64+
void string_pool_free(StringPtr *str)
65+
{
66+
if (currentThread) {
67+
assert(threadStrings[currentThread].find(str) != threadStrings[currentThread].cend());
68+
threadStrings[currentThread].erase(str);
69+
}
70+
71+
freeStrings.insert(std::pair<size_t, StringPtr *>(str->allocatedSize, str));
72+
}
73+
}
74+
75+
/* string_pool_p.h */
76+
77+
void string_pool_add_thread(Thread *thread)
78+
{
79+
// Start capturing allocated strings in the thread
80+
assert(threadStrings.find(thread) == threadStrings.cend());
81+
threadStrings[thread] = {};
82+
}
83+
84+
void string_pool_remove_thread(Thread *thread)
85+
{
86+
// Free all strings in the thread (garbage collection)
87+
assert(threadStrings.find(thread) != threadStrings.cend());
88+
auto &strings = threadStrings[thread];
89+
90+
for (StringPtr *str : strings)
91+
freeStrings.insert(std::pair<size_t, StringPtr *>(str->allocatedSize, str));
92+
93+
strings.clear();
94+
95+
if (currentThread == thread)
96+
currentThread = nullptr;
97+
}
98+
99+
void string_pool_set_thread(Thread *thread)
100+
{
101+
currentThread = thread;
102+
}
103+
104+
} // namespace libscratchcpp

src/scratch/string_pool_p.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
3+
namespace libscratchcpp
4+
{
5+
6+
class Thread;
7+
8+
void string_pool_add_thread(Thread *thread);
9+
void string_pool_remove_thread(Thread *thread);
10+
void string_pool_set_thread(Thread *thread);
11+
12+
} // namespace libscratchcpp

0 commit comments

Comments
 (0)