mirror of
https://github.com/usatiuk/ficus.git
synced 2025-10-28 16:17:51 +01:00
Less crappy skiplist
This commit is contained in:
103
ficus-toolchain/newlib/newlib-4.4.0.20231231/.idea/editor.xml
generated
Normal file
103
ficus-toolchain/newlib/newlib-4.4.0.20231231/.idea/editor.xml
generated
Normal file
@@ -0,0 +1,103 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="BackendCodeEditorSettings">
|
||||
<option name="/Default/Housekeeping/GlobalSettingsUpgraded/IsUpgraded/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppClangFormat/EnableClangFormatSupport/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/EditorConfig/EnableClangFormatSupport/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_BINARY_EXPRESSIONS_CHAIN/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_CALLS_CHAIN/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXPRESSION/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_FOR_STMT/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTIPLE_DECLARATION/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_TERNARY/@EntryValue" value="ALIGN_ALL" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_CLASS_DEFINITION/@EntryValue" value="1" type="int" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue" value="2" type="int" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_CODE/@EntryValue" value="2" type="int" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_USER_LINEBREAKS/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CASE_FROM_SWITCH/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_COMMENT/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INT_ALIGN_EQ/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SIMPLE_BLOCK_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_PARAMS/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_SEMICOLON/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_SEMICOLON/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_UNARY_OPERATOR/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_ARRAY_ACCESS_BRACKETS/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_METHOD_PARENTHESES/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPECIAL_ELSE_IF_TREATMENT/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_BINARY_OPSIGN/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_TERNARY_OPSIGNS/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TYPE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/OTHER_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CASE_BLOCK_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DECLARATION/@EntryValue" value="1" type="int" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DEFINITION/@EntryValue" value="1" type="int" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_WHILE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_ELSE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_CATCH_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_INDENTATION/@EntryValue" value="All" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_ARGUMENT/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXTENDS_LIST/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_PARAMETER/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_ARGUMENT/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_PARAMETER/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_DECLARATIONS/@EntryValue" value="0" type="int" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_ACCESS_SPECIFIERS_FROM_CLASS/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CLASS_MEMBERS_FROM_ACCESS_SPECIFIERS/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/LINE_BREAK_AFTER_COLON_IN_MEMBER_INITIALIZER_LISTS/@EntryValue" value="ON_SINGLE_LINE" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/MEMBER_INITIALIZER_LIST_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_NAMESPACE_DEFINITIONS_ON_SAME_LINE/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_COLON/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_COLON/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_METHOD/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_NESTED_DECLARATOR/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_METHOD/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_METHOD/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_METHOD/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BETWEEN_CLOSING_ANGLE_BRACKETS_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_DECLARATION_PARENTHESES/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_BLOCKS/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_RPAR/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_RPAR/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_ARGUMENTS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_PARAMETERS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BREAK_TEMPLATE_DECLARATION/@EntryValue" value="LINE_BREAK" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/FREE_BLOCK_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INVOCABLE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INITIALIZER_BRACES/@EntryValue" value="END_OF_LINE_NO_SPACE" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_STYLE/@EntryValue" value="Space" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_SIZE/@EntryValue" value="4" type="int" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CONTINUOUS_LINE_INDENT/@EntryValue" value="Double" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TAB_WIDTH/@EntryValue" value="4" type="int" />
|
||||
</component>
|
||||
</project>
|
||||
20
ficus-toolchain/newlib/newlib-4.4.0.20231231/.idea/misc.xml
generated
Normal file
20
ficus-toolchain/newlib/newlib-4.4.0.20231231/.idea/misc.xml
generated
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="MakefileSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<MakefileProjectSettings>
|
||||
<option name="buildDirectory" value="$PROJECT_DIR$/../build" />
|
||||
<option name="buildSystemName" value="GNU Autotools" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
</set>
|
||||
</option>
|
||||
<option name="version" value="2" />
|
||||
</MakefileProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
<component name="MakefileWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
|
||||
</project>
|
||||
6
ficus-toolchain/newlib/newlib-4.4.0.20231231/.idea/vcs.xml
generated
Normal file
6
ficus-toolchain/newlib/newlib-4.4.0.20231231/.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$/../../.." vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -1,3 +1,4 @@
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
||||
add_executable(kernel.elf)
|
||||
|
||||
|
||||
@@ -107,36 +107,36 @@ uint64_t syscall_lseek(uint64_t fd, uint64_t off, uint64_t whence) {
|
||||
}
|
||||
|
||||
uint64_t syscall_print_tasks() {
|
||||
static SkipList<uint64_t, std::pair<String, uint64_t>> last_times = Scheduler::getTaskTimePerPid();
|
||||
static std::atomic<uint64_t> last_print_time = micros;
|
||||
static SkipListMap<uint64_t, std::pair<String, uint64_t>> last_times = Scheduler::getTaskTimePerPid();
|
||||
static std::atomic<uint64_t> last_print_time = micros;
|
||||
|
||||
uint64_t prev_print_time = last_print_time;
|
||||
last_print_time = micros;
|
||||
SkipList<uint64_t, std::pair<String, uint64_t>> prev_times = std::move(last_times);
|
||||
last_times = Scheduler::getTaskTimePerPid();
|
||||
uint64_t prev_print_time = last_print_time;
|
||||
last_print_time = micros;
|
||||
SkipListMap<uint64_t, std::pair<String, uint64_t>> prev_times = std::move(last_times);
|
||||
last_times = Scheduler::getTaskTimePerPid();
|
||||
|
||||
uint64_t slice = last_print_time - prev_print_time;
|
||||
uint64_t slice = last_print_time - prev_print_time;
|
||||
if (slice == 0) return 0;
|
||||
|
||||
for (const auto &t: prev_times) {
|
||||
auto f = last_times.find(t.key);
|
||||
if (!f->end && f->key == t.key) {
|
||||
assert(f->data.second >= t.data.second);
|
||||
auto f = last_times.find(t.first);
|
||||
if (f != last_times.end()) {
|
||||
assert(f->second.second >= t.second.second);
|
||||
String buf;
|
||||
buf += "PID: ";
|
||||
buf += t.key;
|
||||
buf += t.first;
|
||||
buf += " ";
|
||||
buf += t.data.first;
|
||||
buf += t.second.first;
|
||||
buf += " usage: ";
|
||||
buf += (((f->data.second - t.data.second) * 100ULL) / slice);
|
||||
buf += (((f->second.second - t.second.second) * 100ULL) / slice);
|
||||
buf += "%\n";
|
||||
GlobalTtyManager.all_tty_putstr(buf.c_str());
|
||||
} else {
|
||||
String buf;
|
||||
buf += "PID: ";
|
||||
buf += t.key;
|
||||
buf += t.first;
|
||||
buf += " ";
|
||||
buf += t.data.first;
|
||||
buf += t.second.first;
|
||||
buf += " dead \n";
|
||||
GlobalTtyManager.all_tty_putstr(buf.c_str());
|
||||
}
|
||||
|
||||
@@ -37,14 +37,14 @@ void sanity_check_frame(Arch::TaskFrame *cur_frame) {
|
||||
assert2((cur_frame->cs == Arch::GDT::gdt_code.selector() || (cur_frame->ss == Arch::GDT::gdt_code_user.selector()) | 0x3), "CS wrong!");
|
||||
}
|
||||
|
||||
std::atomic<uint64_t> max_pid = 0;
|
||||
Mutex AllTasks_lock;
|
||||
SkipList<uint64_t, UniquePtr<Task>> AllTasks;
|
||||
std::atomic<uint64_t> max_pid = 0;
|
||||
Mutex AllTasks_lock;
|
||||
SkipListMap<uint64_t, UniquePtr<Task>> AllTasks;
|
||||
|
||||
static List<Task *>::Node *RunningTask;
|
||||
static List<Task *>::Node *RunningTask;
|
||||
|
||||
static Spinlock NextTasks_lock;
|
||||
static List<Task *> NextTasks;
|
||||
static Spinlock NextTasks_lock;
|
||||
static List<Task *> NextTasks;
|
||||
|
||||
// Task freer
|
||||
Mutex TasksToFree_lock;
|
||||
@@ -52,11 +52,11 @@ CV TasksToFree_cv;
|
||||
List<List<Task *>::Node *> TasksToFree;
|
||||
|
||||
// Waiting
|
||||
Mutex WaitingTasks_mlock;
|
||||
CV WaitingTasks_cv;
|
||||
SkipList<uint64_t, List<Task *>::Node *> WaitingTasks;
|
||||
Mutex WaitingTasks_mlock;
|
||||
CV WaitingTasks_cv;
|
||||
SkipListMultiMap<uint64_t, List<Task *>::Node *> WaitingTasks;
|
||||
|
||||
static std::atomic<bool> initialized = false;
|
||||
static std::atomic<bool> initialized = false;
|
||||
|
||||
//
|
||||
void Scheduler::remove_self() {
|
||||
@@ -147,7 +147,7 @@ Task::Task(Task::TaskMode mode, void (*entrypoint)(), const char *name) {
|
||||
sanity_check_frame(&_frame);
|
||||
{
|
||||
LockGuard l(AllTasks_lock);
|
||||
AllTasks.add(_pid, UniquePtr(this));
|
||||
AllTasks.emplace(_pid, UniquePtr(this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,12 +155,12 @@ Task::~Task() {
|
||||
assert(_state != TaskState::TS_RUNNING);
|
||||
}
|
||||
|
||||
SkipList<uint64_t, std::pair<String, Task::TaskPID>> Scheduler::getTaskTimePerPid() {
|
||||
SkipList<uint64_t, std::pair<String, Task::TaskPID>> ret;
|
||||
SkipListMap<uint64_t, std::pair<String, Task::TaskPID>> Scheduler::getTaskTimePerPid() {
|
||||
SkipListMap<uint64_t, std::pair<String, Task::TaskPID>> ret;
|
||||
{
|
||||
LockGuard l(AllTasks_lock);
|
||||
for (const auto &t: AllTasks) {
|
||||
ret.add(t.data->pid(), std::make_pair(t.data->name(), t.data->used_time()));
|
||||
ret.emplace(t.second->pid(), std::make_pair(t.second->name(), t.second->used_time()));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
@@ -216,7 +216,7 @@ void Scheduler::sleep_self(uint64_t diff) {
|
||||
{
|
||||
WaitingTasks_mlock.lock();
|
||||
assert(cur_task() != nullptr);
|
||||
assert(WaitingTasks.add(wake_time, extract_running_task_node()) != nullptr);
|
||||
WaitingTasks.emplace(wake_time, extract_running_task_node());
|
||||
Scheduler::self_block(WaitingTasks_mlock);
|
||||
}
|
||||
}
|
||||
@@ -233,22 +233,17 @@ static void task_waker() {
|
||||
{
|
||||
WaitingTasks_mlock.lock();
|
||||
|
||||
while (WaitingTasks.begin() != WaitingTasks.end() && WaitingTasks.begin()->key <= micros && WaitingTasks.begin()->data->val->state() != Task::TaskState::TS_RUNNING) {
|
||||
auto *node = &*WaitingTasks.begin();
|
||||
auto task = WaitingTasks.begin()->data;
|
||||
while (WaitingTasks.begin() != WaitingTasks.end() && WaitingTasks.begin()->first <= micros && WaitingTasks.begin()->second->val->state() != Task::TaskState::TS_RUNNING) {
|
||||
auto node = WaitingTasks.begin();
|
||||
// FIXME:
|
||||
auto node2 = node;
|
||||
++node2;
|
||||
auto task = WaitingTasks.begin()->second;
|
||||
|
||||
// TODO this is all ugly
|
||||
uint64_t l1 = 0;
|
||||
for (auto cur = node; !cur->end; cur = cur->next[0]) l1++;
|
||||
|
||||
WaitingTasks.erase(node, node->next[0], false);
|
||||
|
||||
uint64_t l2 = 0;
|
||||
for (auto *cur = &*WaitingTasks.begin(); !cur->end; cur = cur->next[0]) l2++;
|
||||
WaitingTasks.erase(node, node2);
|
||||
|
||||
WaitingTasks_mlock.unlock();
|
||||
|
||||
assert(l1 - l2 == 1);
|
||||
task->val->_sleep_until = 0;
|
||||
task->val->_state = Task::TaskState::TS_RUNNING;
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ namespace Scheduler {
|
||||
extern "C" void switch_task(Arch::TaskFrame *cur_frame);
|
||||
|
||||
// TODO: that's quite inefficient!
|
||||
SkipList<uint64_t, std::pair<String, Task::TaskPID>> getTaskTimePerPid();
|
||||
SkipListMap<uint64_t, std::pair<String, Task::TaskPID>> getTaskTimePerPid();
|
||||
|
||||
void yield_self();
|
||||
} // namespace Scheduler
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
#include "TestTemplates.hpp"
|
||||
|
||||
|
||||
#include "assert.h"
|
||||
#include "List.hpp"
|
||||
#include "PointersCollection.hpp"
|
||||
#include "SkipList.hpp"
|
||||
#include "SkipListSet.hpp"
|
||||
#include "String.hpp"
|
||||
#include "Vector.hpp"
|
||||
#include "assert.h"
|
||||
|
||||
#include "TtyManager.hpp"
|
||||
|
||||
@@ -153,28 +153,28 @@ public:
|
||||
class SkipListTester {
|
||||
public:
|
||||
bool test() {
|
||||
SkipList<int, String> test1;
|
||||
SkipListMap<int, String> test1;
|
||||
|
||||
test1.add(5, "test5", false);
|
||||
test1.add(999, "test999", false);
|
||||
test1.add(5, "test5", false);
|
||||
test1.add(1, "test1", false);
|
||||
test1.add(999, "test999", false);
|
||||
test1.emplace(5, "test5");
|
||||
test1.emplace(999, "test999");
|
||||
test1.emplace(5, "test5");
|
||||
test1.emplace(1, "test1");
|
||||
test1.emplace(999, "test999");
|
||||
|
||||
assert(test1.find(5)->data == "test5");
|
||||
assert(test1.find(1)->data == "test1");
|
||||
assert(test1.find(999)->data == "test999");
|
||||
assert(test1.find(5)->second == "test5");
|
||||
assert(test1.find(1)->second == "test1");
|
||||
assert(test1.find(999)->second == "test999");
|
||||
|
||||
typename decltype(test1)::iterator tit = test1.begin();
|
||||
typename decltype(test1)::const_iterator tcit = tit;
|
||||
|
||||
test1.erase(1);
|
||||
assert(test1.find(1)->data != "test1");
|
||||
test1.add(87, "test87", false);
|
||||
assert(test1.find(87)->data == "test87");
|
||||
|
||||
auto p2 = test1.lower_bound_update(78);
|
||||
assert(p2->data == "test87");
|
||||
test1.add(78, "test78", true);
|
||||
assert(test1.find(78)->data == "test78");
|
||||
assert(test1.find(1) == test1.cend());
|
||||
test1.emplace(87, "test87");
|
||||
assert(test1.find(87)->second == "test87");
|
||||
|
||||
test1.emplace(78, "test78");
|
||||
assert(test1.find(78)->second == "test78");
|
||||
// GlobalTtyManager.all_tty_putstr("SkipList tests ok!\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
VMA::VMA(AddressSpace *space) : space(space) {
|
||||
LockGuard l(regions_lock);
|
||||
regions.add(0x1000, {0x1000, 0xFFF8000000000000ULL - 0x20000, EntryType::FREE});
|
||||
regions.emplace(std::make_pair<uintptr_t, ListEntry>(0x1000, {0x1000, 0xFFF8000000000000ULL - 0x20000, EntryType::FREE}));
|
||||
}
|
||||
|
||||
VMA::ListEntry *VMA::get_entry(uintptr_t v_addr, size_t length) {
|
||||
@@ -24,7 +24,9 @@ VMA::ListEntry *VMA::get_entry(uintptr_t v_addr, size_t length) {
|
||||
|
||||
// Find the region with start before or at v_addr
|
||||
if (v_addr) {
|
||||
found = ®ions.find(v_addr)->data;
|
||||
auto ub = regions.upper_bound(v_addr);
|
||||
--ub;
|
||||
found = &ub->second;
|
||||
// Check if it fits
|
||||
if (found->length < length || found->type != EntryType::FREE) found = nullptr;
|
||||
}
|
||||
@@ -32,8 +34,8 @@ VMA::ListEntry *VMA::get_entry(uintptr_t v_addr, size_t length) {
|
||||
// Otherwise try to find something else
|
||||
if (!found)
|
||||
for (auto &n: regions) {
|
||||
if (n.data.type == EntryType::FREE && n.data.length >= length) {
|
||||
found = &n.data;
|
||||
if (n.second.type == EntryType::FREE && n.second.length >= length) {
|
||||
found = &n.second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -46,13 +48,13 @@ VMA::ListEntry *VMA::get_entry(uintptr_t v_addr, size_t length) {
|
||||
|
||||
// If our region actually starts before what we requested, then cut it up
|
||||
if ((tmpFound.begin < v_addr) && (tmpFound.length > ((v_addr - tmpFound.begin) + length))) {
|
||||
regions.add(tmpFound.begin, {tmpFound.begin, v_addr - tmpFound.begin, EntryType::FREE});
|
||||
regions.emplace(std::make_pair<uintptr_t, ListEntry>((uintptr_t) tmpFound.begin, {tmpFound.begin, v_addr - tmpFound.begin, EntryType::FREE}));
|
||||
tmpFound.begin = v_addr;
|
||||
tmpFound.length -= v_addr - tmpFound.begin;
|
||||
}
|
||||
|
||||
regions.add(tmpFound.begin + length, {tmpFound.begin + length, tmpFound.length - length, EntryType::FREE});
|
||||
found = ®ions.add(tmpFound.begin, {tmpFound.begin, length, EntryType::ANON})->data;
|
||||
regions.emplace(std::make_pair<uintptr_t, ListEntry>(tmpFound.begin + length, {tmpFound.begin + length, tmpFound.length - length, EntryType::FREE}));
|
||||
found = ®ions.emplace(std::make_pair<uintptr_t, ListEntry>((uintptr_t) tmpFound.begin, {tmpFound.begin, length, EntryType::ANON})).first->second;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
@@ -106,11 +108,11 @@ int VMA::munmap(void *addr, size_t length) {
|
||||
}
|
||||
VMA::~VMA() {
|
||||
for (const auto &e: regions) {
|
||||
if (e.data.type == EntryType::ANON) {
|
||||
assert((e.data.length & (PAGE_SIZE - 1)) == 0);
|
||||
uint64_t page_len = e.data.length / PAGE_SIZE;
|
||||
if (e.second.type == EntryType::ANON) {
|
||||
assert((e.second.length & (PAGE_SIZE - 1)) == 0);
|
||||
uint64_t page_len = e.second.length / PAGE_SIZE;
|
||||
for (int i = 0; i < page_len; i++) {
|
||||
free4k((void *) HHDM_P2V(space->virt2real(reinterpret_cast<void *>(e.data.begin + i * PAGE_SIZE))));
|
||||
free4k((void *) HHDM_P2V(space->virt2real(reinterpret_cast<void *>(e.second.begin + i * PAGE_SIZE))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ private:
|
||||
ListEntry *get_entry(uintptr_t v_addr, size_t length);
|
||||
|
||||
//
|
||||
SkipList<uintptr_t, ListEntry> regions;
|
||||
SkipListMap<uintptr_t, ListEntry> regions;
|
||||
Mutex regions_lock;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
#ifndef SKIPLIST_H
|
||||
#define SKIPLIST_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <new>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
@@ -10,21 +14,34 @@
|
||||
|
||||
extern "C" int rand(void);
|
||||
|
||||
template<typename K, typename V>
|
||||
class SkipList {
|
||||
template<typename Data>
|
||||
class SkipListBase {
|
||||
protected:
|
||||
static constexpr size_t maxL{31};
|
||||
|
||||
public:
|
||||
struct Node {
|
||||
Node *next[maxL + 1] = {nullptr};
|
||||
Node *before = nullptr;
|
||||
bool end = false;
|
||||
K key = K();
|
||||
|
||||
V data = V();
|
||||
alignas(Data) std::array<unsigned char, sizeof(Data)> data;
|
||||
|
||||
Data &get() {
|
||||
assert(!end);
|
||||
return *std::launder(reinterpret_cast<Data *>(&data[0]));
|
||||
}
|
||||
const Data &get() const {
|
||||
assert(!end);
|
||||
return *std::launder(reinterpret_cast<const Data *>(&data[0]));
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
// static_assert(std::is_trivially_constructible<Node>::value);
|
||||
// static_assert(std::is_trivially_destructible<Node>::value);
|
||||
// static_assert(std::is_trivially_copyable<Node>::value);
|
||||
// static_assert(std::is_trivially_move_assignable<Node>::value);
|
||||
// static_assert(std::is_trivially_move_constructible<Node>::value);
|
||||
|
||||
class NodeAllocator {
|
||||
static constexpr int size{64};
|
||||
Node *nodes[size];
|
||||
@@ -39,6 +56,12 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
NodeAllocator(const NodeAllocator &) = delete;
|
||||
// NodeAllocator(NodeAllocator &&) = delete;
|
||||
NodeAllocator &operator=(const NodeAllocator &) = delete;
|
||||
// NodeAllocator &operator=(NodeAllocator &&) = delete;
|
||||
|
||||
//
|
||||
void push(Node *&e) {
|
||||
if (top >= size - 1) {
|
||||
delete e;
|
||||
@@ -58,8 +81,6 @@ private:
|
||||
node->end = false;
|
||||
node->before = nullptr;
|
||||
node->next[0] = nullptr;
|
||||
node->key = K();
|
||||
// node->data = V();
|
||||
|
||||
return node;
|
||||
}
|
||||
@@ -79,8 +100,7 @@ private:
|
||||
mutable Node *toUpdate[maxL + 1];
|
||||
size_t curL = 0;
|
||||
|
||||
public:
|
||||
SkipList() noexcept {
|
||||
SkipListBase() noexcept {
|
||||
root = (Node *) nodeAllocator.get();
|
||||
root->end = true;
|
||||
endnode = (Node *) nodeAllocator.get();
|
||||
@@ -92,16 +112,21 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
~SkipList() noexcept {
|
||||
// FIXME: Should this be protected?
|
||||
public:
|
||||
~SkipListBase() noexcept {
|
||||
auto cur = root;
|
||||
while (cur != nullptr) {
|
||||
if (!cur->end)
|
||||
std::destroy_at(&cur->get());
|
||||
|
||||
auto prev = cur;
|
||||
cur = cur->next[0];
|
||||
nodeAllocator.push(prev);
|
||||
}
|
||||
}
|
||||
|
||||
SkipList(SkipList const &l) noexcept : SkipList() {
|
||||
SkipListBase(SkipListBase const &l) noexcept : SkipListBase() {
|
||||
toUpdate[0] = root;
|
||||
|
||||
for (auto n = l.root->next[0]; n != nullptr && !n->end; n = n->next[0]) {
|
||||
@@ -114,7 +139,6 @@ public:
|
||||
}
|
||||
|
||||
auto newNode = (Node *) nodeAllocator.get();
|
||||
newNode->key = n->key;
|
||||
newNode->data = n->data;
|
||||
newNode->before = toUpdate[0];
|
||||
if (toUpdate[0]->next[0] != nullptr) toUpdate[0]->next[0]->before = newNode;
|
||||
@@ -127,7 +151,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
SkipList(SkipList &&l) noexcept {
|
||||
SkipListBase(SkipListBase &&l) noexcept {
|
||||
this->root = l.root;
|
||||
l.root = nullptr;
|
||||
this->endnode = l.endnode;
|
||||
@@ -136,62 +160,129 @@ public:
|
||||
l.curL = 0;
|
||||
}
|
||||
|
||||
SkipList &operator=(SkipList l) noexcept {
|
||||
SkipListBase &operator=(SkipListBase l) noexcept {
|
||||
std::swap(l.root, root);
|
||||
std::swap(l.endnode, endnode);
|
||||
std::swap(l.curL, curL);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void add(V *p, size_t n, bool reuseUpdate = false) {
|
||||
if (!reuseUpdate) {
|
||||
Node *cur = root;
|
||||
for (int i = curL; i >= 0; i--) {
|
||||
while (cur->next[i]->key < p->l && !cur->next[i]->end)
|
||||
cur = cur->next[i];
|
||||
toUpdate[i] = cur;
|
||||
}
|
||||
protected:
|
||||
// void add(V *p, size_t n, bool reuseUpdate = false) {
|
||||
// if (!reuseUpdate) {
|
||||
// Node *cur = root;
|
||||
// for (int i = curL; i >= 0; i--) {
|
||||
// while (cur->next[i]->key < p->l && !cur->next[i]->end)
|
||||
// cur = cur->next[i];
|
||||
// toUpdate[i] = cur;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// for (size_t i = 0; i < n; i++, p++) {
|
||||
// size_t newLevel = randomL();
|
||||
//
|
||||
// if (newLevel > curL) {
|
||||
// for (size_t j = curL + 1; j <= newLevel; j++)
|
||||
// toUpdate[j] = root;
|
||||
//
|
||||
// curL = newLevel;
|
||||
// }
|
||||
//
|
||||
// auto newNode = (Node *) nodeAllocator.get();
|
||||
// newNode->key = p->l;
|
||||
// newNode->data = *p;
|
||||
//
|
||||
// newNode->before = toUpdate[0];
|
||||
// if (toUpdate[0]->next[0] != nullptr) toUpdate[0]->next[0]->before = newNode;
|
||||
//
|
||||
// for (size_t j = 0; j <= newLevel; j++) {
|
||||
// newNode->next[j] = toUpdate[j]->next[j];
|
||||
// toUpdate[j]->next[j] = newNode;
|
||||
// toUpdate[j] = newNode;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
template<typename value_type_arg>
|
||||
struct SkipListBaseIteratorBase {
|
||||
using iterator_category = std::bidirectional_iterator_tag;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using value_type = value_type_arg;
|
||||
using pointer = value_type *;
|
||||
using reference = value_type &;
|
||||
|
||||
explicit SkipListBaseIteratorBase(Node *n) : n(std::move(n)){};
|
||||
|
||||
reference operator*() const { return n->get(); }
|
||||
|
||||
pointer operator->() const { return &n->get(); }
|
||||
|
||||
SkipListBaseIteratorBase &operator--() {
|
||||
if (n->before)
|
||||
n = n->before;
|
||||
return *this;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < n; i++, p++) {
|
||||
size_t newLevel = randomL();
|
||||
|
||||
if (newLevel > curL) {
|
||||
for (size_t j = curL + 1; j <= newLevel; j++)
|
||||
toUpdate[j] = root;
|
||||
|
||||
curL = newLevel;
|
||||
}
|
||||
|
||||
auto newNode = (Node *) nodeAllocator.get();
|
||||
newNode->key = p->l;
|
||||
newNode->data = *p;
|
||||
|
||||
newNode->before = toUpdate[0];
|
||||
if (toUpdate[0]->next[0] != nullptr) toUpdate[0]->next[0]->before = newNode;
|
||||
|
||||
for (size_t j = 0; j <= newLevel; j++) {
|
||||
newNode->next[j] = toUpdate[j]->next[j];
|
||||
toUpdate[j]->next[j] = newNode;
|
||||
toUpdate[j] = newNode;
|
||||
}
|
||||
SkipListBaseIteratorBase &operator++() {
|
||||
if (n->next[0])
|
||||
n = n->next[0];
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
bool erase(Node *begin, Node *end, bool reuseUpdate = false) {
|
||||
if (begin == end) return false;
|
||||
SkipListBaseIteratorBase operator++(int) {
|
||||
SkipListBaseIteratorBase tmp = *this;
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
if (!reuseUpdate) {
|
||||
Node *cur = root;
|
||||
for (int i = curL; i >= 0; i--) {
|
||||
while (cur->next[i]->key < begin->key && !cur->next[i]->end)
|
||||
cur = cur->next[i];
|
||||
toUpdate[i] = cur;
|
||||
}
|
||||
template<typename L, typename R>
|
||||
friend bool operator==(const SkipListBaseIteratorBase<L> &a, const SkipListBaseIteratorBase<R> &b);
|
||||
|
||||
template<typename L, typename R>
|
||||
friend bool operator!=(const SkipListBaseIteratorBase<L> &a, const SkipListBaseIteratorBase<R> &b);
|
||||
|
||||
friend SkipListBase;
|
||||
|
||||
protected:
|
||||
Node *n;
|
||||
};
|
||||
|
||||
public:
|
||||
template<typename L, typename R>
|
||||
friend bool operator==(const SkipListBaseIteratorBase<L> &a, const SkipListBaseIteratorBase<R> &b) {
|
||||
if (a.n->end && b.n->end) return true;
|
||||
return a.n == b.n;
|
||||
};
|
||||
|
||||
template<typename L, typename R>
|
||||
friend bool operator!=(const SkipListBaseIteratorBase<L> &a, const SkipListBaseIteratorBase<R> &b) {
|
||||
if (a.n->end && (a.n->end == b.n->end)) return false;
|
||||
return a.n != b.n;
|
||||
};
|
||||
|
||||
using iterator = SkipListBaseIteratorBase<Data>;
|
||||
|
||||
struct const_iterator : public SkipListBaseIteratorBase<const Data> {
|
||||
using SkipListBaseIteratorBase<const Data>::SkipListBaseIteratorBase;
|
||||
const_iterator(const iterator &i) : SkipListBaseIteratorBase<const Data>(i.n) {}
|
||||
};
|
||||
|
||||
protected:
|
||||
// Comparator true if less than, 0 if equal
|
||||
template<class Comparator>
|
||||
std::pair<Node *, bool> erase(const_iterator begin, const_iterator end) {
|
||||
if (begin == end) return {root->next[0], false};
|
||||
|
||||
Node *cur = root;
|
||||
for (int i = curL; i >= 0; i--) {
|
||||
while (!cur->next[i]->end && Comparator()(cur->next[i]->get(), *begin))
|
||||
cur = cur->next[i];
|
||||
toUpdate[i] = cur;
|
||||
}
|
||||
|
||||
Node *prev = nullptr;
|
||||
for (auto cur = begin; cur != end; cur = cur->next[0]) {
|
||||
for (auto cur = begin.n; cur != end.n; cur = cur->next[0]) {
|
||||
if (prev)
|
||||
nodeAllocator.push(prev);
|
||||
|
||||
@@ -210,60 +301,24 @@ public:
|
||||
prev = cur;
|
||||
}
|
||||
|
||||
auto ret = std::make_pair(prev->next[0], true);
|
||||
if (prev)
|
||||
nodeAllocator.push(prev);
|
||||
return true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
Node *add(K const &k, V v, bool reuseUpdate = false) {
|
||||
if (!reuseUpdate) {
|
||||
Node *cur = root;
|
||||
|
||||
for (int i = curL; i >= 0; i--) {
|
||||
while (cur->next[i]->key < k && !cur->next[i]->end)
|
||||
cur = cur->next[i];
|
||||
toUpdate[i] = cur;
|
||||
}
|
||||
cur = cur->next[0];
|
||||
// Without this it's a multimap TODO: multiple variants of this and merge it with set
|
||||
// if (cur->key == k && !cur->end) return nullptr;
|
||||
}
|
||||
|
||||
size_t newLevel = randomL();
|
||||
|
||||
if (newLevel > curL) {
|
||||
for (size_t i = curL + 1; i <= newLevel; i++)
|
||||
toUpdate[i] = root;
|
||||
|
||||
curL = newLevel;
|
||||
}
|
||||
|
||||
auto newNode = (Node *) nodeAllocator.get();
|
||||
newNode->key = k;
|
||||
newNode->data = std::move(v);
|
||||
|
||||
newNode->before = toUpdate[0];
|
||||
if (toUpdate[0]->next[0] != nullptr) toUpdate[0]->next[0]->before = newNode;
|
||||
|
||||
for (size_t i = 0; i <= newLevel; i++) {
|
||||
newNode->next[i] = toUpdate[i]->next[i];
|
||||
toUpdate[i]->next[i] = newNode;
|
||||
toUpdate[i] = newNode;
|
||||
}
|
||||
return newNode;
|
||||
}
|
||||
|
||||
bool erase(K const &k) {
|
||||
// Comparator true if less than, 0 if equal
|
||||
std::pair<Node *, bool> erase(const const_iterator &k) {
|
||||
Node *cur = root;
|
||||
|
||||
for (int i = curL; i >= 0; i--) {
|
||||
while (cur->next[i]->key < k && !cur->next[i]->end)
|
||||
while (!cur->next[i]->end && cur->next[i] != k.n)
|
||||
cur = cur->next[i];
|
||||
toUpdate[i] = cur;
|
||||
}
|
||||
cur = cur->next[0];
|
||||
|
||||
if (cur->end || cur->key != k) return false;
|
||||
if (cur->end || cur != k.n) return {cur, false};
|
||||
|
||||
cur->next[0]->before = toUpdate[0];
|
||||
|
||||
@@ -277,71 +332,125 @@ public:
|
||||
while (curL > 0 &&
|
||||
root->next[curL] == nullptr)
|
||||
curL--;
|
||||
cur->data = V();
|
||||
|
||||
std::destroy_at(&cur->get());
|
||||
auto ret = std::make_pair(cur->next[0], true);
|
||||
nodeAllocator.push(cur);
|
||||
return true;
|
||||
return ret;
|
||||
};
|
||||
|
||||
|
||||
// Returns the node PRECEDING the node with a key that is GREATER than k
|
||||
Node *find(K const &k) const {
|
||||
Node *cur = root;
|
||||
|
||||
for (int i = curL; i >= 0; i--)
|
||||
while (cur->next[i]->key <= k && !cur->next[i]->end)
|
||||
cur = cur->next[i];
|
||||
|
||||
return cur;
|
||||
}
|
||||
|
||||
Node *upper_bound(K const &k) const {
|
||||
// Comparator true if less than, 0 if equal
|
||||
template<class Comparator, bool Duplicate>
|
||||
std::pair<Node *, bool> insert(Node *newNode) {
|
||||
Node *cur = root;
|
||||
|
||||
for (int i = curL; i >= 0; i--) {
|
||||
while (cur->next[i]->key <= k && !cur->next[i]->end)
|
||||
cur = cur->next[i];
|
||||
}
|
||||
|
||||
cur = cur->next[0];
|
||||
|
||||
return cur;
|
||||
}
|
||||
|
||||
Node *lower_bound_update(K const &k) const {
|
||||
Node *cur = root;
|
||||
|
||||
for (int i = curL; i >= 0; i--) {
|
||||
while (cur->next[i]->key < k && !cur->next[i]->end)
|
||||
while (!cur->next[i]->end && Comparator()(cur->next[i]->get(), newNode->get()))
|
||||
cur = cur->next[i];
|
||||
toUpdate[i] = cur;
|
||||
}
|
||||
|
||||
cur = cur->next[0];
|
||||
if constexpr (!Duplicate)
|
||||
if (!cur->end && Comparator().eq(cur->get(), newNode->get())) return {cur, false};
|
||||
|
||||
return cur;
|
||||
size_t newLevel = randomL();
|
||||
|
||||
if (newLevel > curL) {
|
||||
for (size_t i = curL + 1; i <= newLevel; i++)
|
||||
toUpdate[i] = root;
|
||||
|
||||
curL = newLevel;
|
||||
}
|
||||
|
||||
newNode->before = toUpdate[0];
|
||||
if (toUpdate[0]->next[0] != nullptr) toUpdate[0]->next[0]->before = newNode;
|
||||
|
||||
for (size_t i = 0; i <= newLevel; i++) {
|
||||
newNode->next[i] = toUpdate[i]->next[i];
|
||||
toUpdate[i]->next[i] = newNode;
|
||||
toUpdate[i] = newNode;
|
||||
}
|
||||
return {newNode, true};
|
||||
}
|
||||
|
||||
template<class Comparator, bool Duplicate>
|
||||
std::pair<Node *, bool> insert(Data d) {
|
||||
Node *n = nodeAllocator.get();
|
||||
new (n->data) Data(std::move(d));
|
||||
return insert<Comparator, Duplicate>(n);
|
||||
}
|
||||
|
||||
Node *lower_bound(K const &k) const {
|
||||
template<class Comparator, bool Duplicate, class... Args>
|
||||
std::pair<Node *, bool> emplace(Args &&...args) {
|
||||
Node *n = nodeAllocator.get();
|
||||
new (&n->get()) Data(std::forward<Args>(args)...);
|
||||
return insert<Comparator, Duplicate>(n);
|
||||
}
|
||||
|
||||
// Comparator true if less than, 0 if equal
|
||||
template<class Comparator, typename CmpArg>
|
||||
std::pair<Node *, bool> erase(const CmpArg &k) {
|
||||
Node *cur = root;
|
||||
|
||||
for (int i = curL; i >= 0; i--) {
|
||||
while (cur->next[i]->key < k && !cur->next[i]->end)
|
||||
while (!cur->next[i]->end && Comparator()(cur->next[i]->get(), k))
|
||||
cur = cur->next[i];
|
||||
toUpdate[i] = cur;
|
||||
}
|
||||
|
||||
cur = cur->next[0];
|
||||
|
||||
if (cur->end || !Comparator().eq(cur->get(), k)) return {cur, false};
|
||||
|
||||
cur->next[0]->before = toUpdate[0];
|
||||
|
||||
for (size_t i = 0; i <= curL; i++) {
|
||||
if (toUpdate[i]->next[i] != cur)
|
||||
break;
|
||||
|
||||
toUpdate[i]->next[i] = cur->next[i];
|
||||
}
|
||||
|
||||
while (curL > 0 &&
|
||||
root->next[curL] == nullptr)
|
||||
curL--;
|
||||
|
||||
std::destroy_at(&cur->get());
|
||||
auto ret = std::make_pair(cur->next[0], true);
|
||||
nodeAllocator.push(cur);
|
||||
return ret;
|
||||
};
|
||||
|
||||
template<class Comparator, typename CmpArg>
|
||||
Node *upper_bound(const CmpArg &k) const {
|
||||
Node *cur = root;
|
||||
|
||||
for (int i = curL; i >= 0; i--)
|
||||
while (!cur->next[i]->end && (Comparator()(cur->next[i]->get(), k) || Comparator().eq(cur->next[i]->get(), k)))
|
||||
cur = cur->next[i];
|
||||
if (!cur->end && (Comparator()(cur->get(), k) || Comparator().eq(cur->get(), k)))
|
||||
cur = cur->next[0];
|
||||
return cur;
|
||||
}
|
||||
|
||||
template<class Comparator, typename CmpArg>
|
||||
Node *lower_bound(const CmpArg &k) const {
|
||||
Node *cur = root;
|
||||
|
||||
bool operator==(SkipList const &r) const {
|
||||
for (int i = curL; i >= 0; i--)
|
||||
while (!cur->next[i]->end && Comparator()(cur->next[i]->get(), k))
|
||||
cur = cur->next[i];
|
||||
|
||||
return cur->next[0];
|
||||
}
|
||||
|
||||
public:
|
||||
bool operator==(SkipListBase const &r) const {
|
||||
auto n = root->next[0];
|
||||
auto n2 = r.root->next[0];
|
||||
|
||||
while (!n->end && !n2->end) {
|
||||
if (!(n->data == n2->data)) return false;
|
||||
if (!(n->get() == n2->get())) return false;
|
||||
n = n->next[0];
|
||||
n2 = n2->next[0];
|
||||
}
|
||||
@@ -351,54 +460,16 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
iterator begin() { return iterator(root->next[0]); }
|
||||
iterator end() { return iterator(endnode); }
|
||||
|
||||
// TODO: pair
|
||||
struct SkipListIterator {
|
||||
// using iterator_category = std::forward_iterator_tag;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using value_type = Node;
|
||||
using pointer = value_type *;
|
||||
using reference = value_type &;
|
||||
const_iterator begin() const { return const_iterator(root->next[0]); }
|
||||
const_iterator end() const { return const_iterator(endnode); }
|
||||
|
||||
explicit SkipListIterator(Node *n) : n(std::move(n)){};
|
||||
|
||||
reference operator*() const { return *n; }
|
||||
|
||||
pointer operator->() const { return n; }
|
||||
|
||||
SkipListIterator &operator--() {
|
||||
if (!n->end)
|
||||
n = n->before;
|
||||
return *this;
|
||||
}
|
||||
|
||||
SkipListIterator &operator++() {
|
||||
if (!n->end)
|
||||
n = n->next[0];
|
||||
return *this;
|
||||
}
|
||||
|
||||
SkipListIterator operator++(int) {
|
||||
SkipListIterator tmp = *this;
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
friend bool operator==(const SkipListIterator &a, const SkipListIterator &b) { return a.n == b.n; };
|
||||
|
||||
friend bool operator!=(const SkipListIterator &a, const SkipListIterator &b) { return a.n != b.n; };
|
||||
|
||||
private:
|
||||
Node *n;
|
||||
};
|
||||
|
||||
using iterator = SkipListIterator;
|
||||
// using const_iterator = SkipListIterator;
|
||||
|
||||
iterator begin() const { return SkipListIterator(root->next[0]); }
|
||||
|
||||
iterator end() const { return SkipListIterator(endnode); }
|
||||
const_iterator cbegin() const { return const_iterator(root->next[0]); }
|
||||
const_iterator cend() const { return const_iterator(endnode); }
|
||||
|
||||
protected:
|
||||
// void print() const {
|
||||
// std::cout << "LIST STATUS" << std::endl;
|
||||
//
|
||||
@@ -416,4 +487,99 @@ public:
|
||||
};
|
||||
|
||||
|
||||
template<bool Duplicates, typename K, typename V, typename CmpBase = std::less<K>>
|
||||
class SkipListMapBase : public SkipListBase<std::pair<K, V>> {
|
||||
using BaseT = SkipListBase<std::pair<K, V>>;
|
||||
|
||||
public:
|
||||
using iterator = typename BaseT::iterator;
|
||||
using const_iterator = typename BaseT::const_iterator;
|
||||
using value_type = std::pair<K, V>;
|
||||
|
||||
private:
|
||||
struct Cmp {
|
||||
constexpr bool operator()(const value_type &lhs, const K &rhs) const {
|
||||
return CmpBase()(lhs.first, rhs);
|
||||
}
|
||||
constexpr bool operator()(const K &lhs, const value_type &rhs) const {
|
||||
return CmpBase()(lhs, rhs.first);
|
||||
}
|
||||
constexpr bool eq(const value_type &lhs, const K &rhs) const {
|
||||
return lhs.first == rhs;
|
||||
}
|
||||
constexpr bool eq(const K &rhs, const value_type &lhs) const {
|
||||
return lhs.first == rhs;
|
||||
}
|
||||
constexpr bool operator()(const value_type &lhs, const value_type &rhs) const {
|
||||
return CmpBase()(lhs.first, rhs.first);
|
||||
}
|
||||
constexpr bool eq(const value_type &lhs, const value_type &rhs) const {
|
||||
return lhs.first == rhs.first;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
iterator begin() { return BaseT::begin(); }
|
||||
iterator end() { return BaseT::end(); }
|
||||
const_iterator begin() const { return BaseT::begin(); }
|
||||
const_iterator end() const { return BaseT::end(); }
|
||||
const_iterator cbegin() const { return BaseT::cbegin(); }
|
||||
const_iterator cend() const { return BaseT::cend(); }
|
||||
|
||||
template<class... Args>
|
||||
std::pair<iterator, bool> emplace(Args &&...args) {
|
||||
auto r = BaseT::template emplace<Cmp, Duplicates, Args...>(std::forward<Args>(args)...);
|
||||
return {iterator(r.first), r.second};
|
||||
}
|
||||
|
||||
const_iterator find(const K &k) const {
|
||||
typename BaseT::Node *n = BaseT::template lower_bound<Cmp>(k);
|
||||
if (n->end || n->get().first != k) return end();
|
||||
return const_iterator(n);
|
||||
}
|
||||
|
||||
iterator find(const K &k) {
|
||||
typename BaseT::Node *n = BaseT::template lower_bound<Cmp>(k);
|
||||
if (n->end || n->get().first != k) return end();
|
||||
return iterator(n);
|
||||
}
|
||||
|
||||
const_iterator upper_bound(const K &k) const {
|
||||
typename BaseT::Node *n = BaseT::template upper_bound<Cmp>(k);
|
||||
if (n->end) return end();
|
||||
return const_iterator(n);
|
||||
}
|
||||
|
||||
iterator upper_bound(const K &k) {
|
||||
typename BaseT::Node *n = BaseT::template upper_bound<Cmp>(k);
|
||||
if (n->end) return end();
|
||||
return iterator(n);
|
||||
}
|
||||
|
||||
iterator erase(const K &k) {
|
||||
std::pair<typename BaseT::Node *, bool> n = BaseT::template erase<Cmp>(k);
|
||||
if (n.first->end) return end();
|
||||
return iterator(n.first);
|
||||
}
|
||||
|
||||
iterator erase(const_iterator first, const_iterator last) {
|
||||
std::pair<typename BaseT::Node *, bool> n = BaseT::template erase<Cmp>(first, last);
|
||||
if (n.first->end) return end();
|
||||
return iterator(n.first);
|
||||
}
|
||||
|
||||
iterator erase(const_iterator el) {
|
||||
std::pair<typename BaseT::Node *, bool> n = BaseT::erase(el);
|
||||
if (n.first->end) return end();
|
||||
return iterator(n.first);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename K, typename V, typename CmpBase = std::less<K>>
|
||||
using SkipListMap = SkipListMapBase<false, K, V, CmpBase>;
|
||||
|
||||
//FIXME: erase is probably janky with this
|
||||
template<typename K, typename V, typename CmpBase = std::less<K>>
|
||||
using SkipListMultiMap = SkipListMapBase<true, K, V, CmpBase>;
|
||||
|
||||
#endif
|
||||
@@ -15,7 +15,7 @@
|
||||
FDT::FD FDT::open(const Path &p, FileOpts opts) {
|
||||
if (auto n = VFSGlobals::root.traverse(p); n.get() != nullptr) {
|
||||
LockGuard l(_mtx);
|
||||
_files.add(_cur_fd++, UniquePtr<File>(new File(n, opts)));
|
||||
_files.emplace(_cur_fd++, UniquePtr<File>(new File(n, opts)));
|
||||
return _cur_fd - 1;
|
||||
}
|
||||
if (opts & FileOpts::O_CREAT) {
|
||||
@@ -27,18 +27,13 @@ FDT::FD FDT::open(const Path &p, FileOpts opts) {
|
||||
|
||||
void FDT::close(FDT::FD fd) {
|
||||
LockGuard l(_mtx);
|
||||
if (auto f = _files.find(fd))
|
||||
if (!f->end)
|
||||
if (f->key == fd) {
|
||||
_files.erase(fd);
|
||||
}
|
||||
if (auto f = _files.find(fd); f != _files.end())
|
||||
_files.erase(fd);
|
||||
}
|
||||
File *FDT::get(FDT::FD fd) const {
|
||||
LockGuard l(_mtx);
|
||||
if (auto f = _files.find(fd))
|
||||
if (!f->end)
|
||||
if (f->key == fd)
|
||||
return f->data.get();
|
||||
if (auto f = _files.find(fd); f != _files.end())
|
||||
return f->second.get();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -46,8 +41,8 @@ FDT *FDT::current() {
|
||||
return Scheduler::cur_task()->_addressSpace->getFdt();
|
||||
}
|
||||
FDT::FDT() {
|
||||
_files.add(0, UniquePtr(new File(static_ptr_cast<Node>(TtyPipe::create()), O_RDONLY)));
|
||||
_files.add(1, UniquePtr(new File(static_ptr_cast<Node>(TtyPipe::create()), O_RDWR)));
|
||||
_files.emplace(0, UniquePtr(new File(static_ptr_cast<Node>(TtyPipe::create()), O_RDONLY)));
|
||||
_files.emplace(1, UniquePtr(new File(static_ptr_cast<Node>(TtyPipe::create()), O_RDWR)));
|
||||
}
|
||||
FDHandle::FDHandle(FDT::FD fd) : _fd(fd) {
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ public:
|
||||
static FDT *current();
|
||||
|
||||
private:
|
||||
SkipList<FD, UniquePtr<File>> _files;
|
||||
SkipListMap<FD, UniquePtr<File>> _files;
|
||||
int64_t _cur_fd = 10;
|
||||
mutable Mutex _mtx;
|
||||
};
|
||||
|
||||
@@ -12,7 +12,7 @@ Vector<SharedPtr<Node>> MemFs::MemFsNodeDir::children() {
|
||||
|
||||
Vector<SharedPtr<Node>> out;
|
||||
for (auto c: _children) {
|
||||
out.emplace_back(c.data);
|
||||
out.emplace_back(c.second);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
@@ -20,13 +20,13 @@ Vector<SharedPtr<Node>> MemFs::MemFsNodeDir::children() {
|
||||
SharedPtr<NodeDir> MemFs::MemFsNodeDir::mkdir(const String &name) {
|
||||
LockGuard l(_lock);
|
||||
auto newnode = MemFsNodeDir::create(name);
|
||||
_children.add(name, static_ptr_cast<Node>(newnode));
|
||||
_children.emplace(name, static_ptr_cast<Node>(newnode));
|
||||
return static_ptr_cast<NodeDir>(newnode);
|
||||
}
|
||||
SharedPtr<NodeFile> MemFs::MemFsNodeDir::mkfile(const String &name) {
|
||||
LockGuard l(_lock);
|
||||
auto newfile = MemFsNodeFile::create(name);
|
||||
_children.add(name, static_ptr_cast<Node>(newfile));
|
||||
_children.emplace(name, static_ptr_cast<Node>(newfile));
|
||||
return static_ptr_cast<NodeFile>(newfile);
|
||||
}
|
||||
int64_t MemFs::MemFsNodeFile::read(char *buf, size_t start, size_t num) {
|
||||
|
||||
@@ -26,7 +26,7 @@ class MemFs : public Filesystem {
|
||||
|
||||
private:
|
||||
MemFsNodeDir(const String &name) { _name = name; }
|
||||
SkipList<String, SharedPtr<Node>> _children;
|
||||
SkipListMap<String, SharedPtr<Node>> _children;
|
||||
};
|
||||
|
||||
struct MemFsNodeFile : public NodeFile {
|
||||
|
||||
@@ -38,7 +38,7 @@ public:
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &out, const CRange &p) {
|
||||
std::ios::fmtflags f(out.flags());
|
||||
out << std::dec;
|
||||
out << std::dec << std::resetiosflags(std::ios_base::hex) << std::resetiosflags(std::ios_base::left);
|
||||
if (p.l == p.r) out << p.l;
|
||||
else
|
||||
out << "<" << p.l << ".." << p.r << ">";
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
return out;
|
||||
}
|
||||
|
||||
bool includes(const IntType &p) const {
|
||||
bool includes(const IntType p) const {
|
||||
return p >= l && p <= r;
|
||||
}
|
||||
|
||||
@@ -57,101 +57,109 @@ public:
|
||||
bool operator==(const CRange &p) const {
|
||||
return p.l == l && p.r == r;
|
||||
}
|
||||
|
||||
operator std::pair<IntType, IntType>() const { return {l, r}; }
|
||||
};
|
||||
|
||||
|
||||
template<template<class, class, class...> class Storage = std::map>
|
||||
class CRangeList {
|
||||
private:
|
||||
SkipList<IntType, CRange> data;
|
||||
Storage<IntType, std::pair<CRange, bool>> data;
|
||||
|
||||
public:
|
||||
// constructor
|
||||
CRangeList() = default;
|
||||
CRangeList() {
|
||||
auto p = std::make_pair(LLONG_MIN, std::make_pair(CRange(LLONG_MIN, LLONG_MAX), false));
|
||||
data.emplace(p.first, p.second);
|
||||
}
|
||||
|
||||
CRangeList(std::initializer_list<CRange> l) {
|
||||
for (auto const &r: l)
|
||||
auto p = std::make_pair(LLONG_MIN, std::make_pair(CRange(LLONG_MIN, LLONG_MAX), false));
|
||||
data.emplace(p.first, p.second);
|
||||
for (auto const &r: l) {
|
||||
*this += r;
|
||||
}
|
||||
|
||||
CRangeList(CRangeList &&l) {
|
||||
data = std::move(l.data);
|
||||
}
|
||||
|
||||
CRangeList(CRangeList const &l) {
|
||||
data = l.data;
|
||||
}
|
||||
|
||||
CRangeList &operator=(CRangeList l) {
|
||||
std::swap(l.data, data);
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
// includes long long / range
|
||||
bool includes(const IntType l) const {
|
||||
auto f = findInData(l);
|
||||
if (!f->end && f->data.includes(l)) return true;
|
||||
return false;
|
||||
return findInData(l)->second.second;
|
||||
}
|
||||
|
||||
bool includes(const CRange &r) const {
|
||||
auto f = findInData(r.l);
|
||||
if (!f->end && f->data.includes(r)) return true;
|
||||
return false;
|
||||
if (!f->second.second) return false;
|
||||
return f->second.first.includes(r);
|
||||
}
|
||||
|
||||
CRangeList operator+(const CRange &rhs) const {
|
||||
return CRangeList(*this) += rhs;
|
||||
auto nl = CRangeList();
|
||||
nl += *this;
|
||||
nl += rhs;
|
||||
return nl;
|
||||
}
|
||||
|
||||
CRangeList operator-(const CRange &rhs) const {
|
||||
return CRangeList(*this) -= rhs;
|
||||
auto nl = CRangeList();
|
||||
nl += *this;
|
||||
nl -= rhs;
|
||||
return nl;
|
||||
}
|
||||
|
||||
|
||||
decltype(data)::Node *findInData(IntType const &l) const {
|
||||
return data.find(l);
|
||||
typename decltype(data)::const_iterator findInData(IntType l) const {
|
||||
typename decltype(data)::const_iterator ret = data.upper_bound(l);
|
||||
--ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void set(CRange r, bool visible) {
|
||||
auto lb = findInData(r.l);
|
||||
auto ub = findInData(r.r);
|
||||
|
||||
bool lbHasPoint = !lb->end && lb->data.includes(r.l);
|
||||
if (visible && !lbHasPoint && !lb->end && r.l != LLONG_MIN && lb->data.includes(r.l - 1)) {
|
||||
r.l--;
|
||||
lbHasPoint = true;
|
||||
auto lb = findInData(r.l);
|
||||
if (lb != data.begin() && !lb->second.first.includes(r.l - 1)) {
|
||||
auto lbm = lb;
|
||||
--lbm;
|
||||
if (lbm->second.second == visible) {
|
||||
r.l--;
|
||||
lb = lbm;
|
||||
}
|
||||
}
|
||||
|
||||
bool ubHasPoint = !ub->end && ub->data.includes(r.r);
|
||||
if (visible && !ubHasPoint && r.r != LLONG_MAX && ub->next[0]->data.includes(r.r + 1)) {
|
||||
ub = ub->next[0];
|
||||
r.r++;
|
||||
ubHasPoint = true;
|
||||
auto ub = findInData(r.r);
|
||||
if (ub != (--data.end()) && !ub->second.first.includes(r.r + 1)) {
|
||||
auto ubp = ub;
|
||||
++ubp;
|
||||
if (ubp->second.second == visible) {
|
||||
r.r++;
|
||||
ub = ubp;
|
||||
}
|
||||
}
|
||||
|
||||
if (!lbHasPoint) lb = lb->next[0];
|
||||
if (lb == data.end() || ub == data.end()) throw;
|
||||
auto lbc = lb->second;
|
||||
auto ubc = ub->second;
|
||||
ub++;
|
||||
|
||||
CRange toInsert[3];
|
||||
std::map<IntType, std::pair<CRange, bool>> toInsert;
|
||||
|
||||
if (visible) {
|
||||
if (lbHasPoint)
|
||||
r.l = std::min(lb->data.l, r.l);
|
||||
if (ubHasPoint)
|
||||
r.r = std::max(ub->data.r, r.r);
|
||||
toInsert[0] = {r};
|
||||
data.add(toInsert, 1, data.erase(lb, ub->next[0], false));
|
||||
} else {
|
||||
int inserted = 0;
|
||||
if (lbHasPoint && lb->data.l != r.l) {
|
||||
toInsert[0] = {lb->data.l, r.l - 1};
|
||||
inserted++;
|
||||
if (r.l != lbc.first.l) {
|
||||
if (lbc.second == visible) {
|
||||
r.l = std::min(lbc.first.l, r.l);
|
||||
} else {
|
||||
toInsert.emplace(lbc.first.l, std::make_pair(CRange(lbc.first.l, r.l - 1), lbc.second));
|
||||
}
|
||||
if (ubHasPoint && ub->data.r != r.r) {
|
||||
toInsert[inserted] = {r.r + 1, ub->data.r};
|
||||
inserted++;
|
||||
}
|
||||
|
||||
if (r.r != ubc.first.r) {
|
||||
if (ubc.second == visible)
|
||||
r.r = std::max(ubc.first.r, r.r);
|
||||
else {
|
||||
toInsert.emplace(r.r + 1, std::make_pair(CRange(r.r + 1, ubc.first.r), ubc.second));
|
||||
}
|
||||
data.add(toInsert, inserted, data.erase(lb, ub->next[0], false));
|
||||
}
|
||||
toInsert.emplace(r.l, std::make_pair(r, visible));
|
||||
data.erase(lb, ub);
|
||||
for (auto &r: toInsert) {
|
||||
data.emplace(std::move(r));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,8 +170,10 @@ public:
|
||||
}
|
||||
|
||||
CRangeList &operator+=(const CRangeList &r) {
|
||||
for (auto const &l: r)
|
||||
*this += l;
|
||||
for (auto const &l: r.data) {
|
||||
if (l.second.second)
|
||||
*this += l.second.first;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -174,14 +184,17 @@ public:
|
||||
}
|
||||
|
||||
CRangeList &operator-=(const CRangeList &r) {
|
||||
for (auto const &l: r)
|
||||
*this -= l;
|
||||
for (auto const &l: r.data) {
|
||||
if (l.second.second)
|
||||
*this -= l.second.first;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// = range / range list
|
||||
CRangeList &operator=(const CRange &r) {
|
||||
data = decltype(data)();
|
||||
auto p = std::make_pair(LLONG_MIN, std::make_pair(CRange(LLONG_MIN, LLONG_MAX), false));
|
||||
data.emplace(p.first, p.second);
|
||||
*this += (r);
|
||||
return *this;
|
||||
}
|
||||
@@ -193,41 +206,47 @@ public:
|
||||
|
||||
// operator !=
|
||||
bool operator!=(const CRangeList &r) const {
|
||||
return !(*this == r);
|
||||
return !(this->data == r.data);
|
||||
}
|
||||
|
||||
|
||||
// operator <<
|
||||
friend std::ostream &operator<<(std::ostream &out, const CRangeList &rl) {
|
||||
out << "{";
|
||||
bool first = true;
|
||||
for (const auto &i: rl) {
|
||||
if (!first) out << ",";
|
||||
out << i;
|
||||
first = false;
|
||||
for (const auto &i: rl.data) {
|
||||
if (i.second.second) {
|
||||
if (!first) out << ",";
|
||||
out << i.second.first;
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
out << "}";
|
||||
return out;
|
||||
}
|
||||
|
||||
struct CRangeListIterator {
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using value_type = const CRange;
|
||||
using pointer = value_type *;
|
||||
using reference = value_type &;
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using value_type = const CRange;
|
||||
using pointer = value_type *;
|
||||
using reference = value_type &;
|
||||
|
||||
CRangeListIterator(CRangeListIterator const &it) = default;
|
||||
CRangeListIterator(CRangeListIterator const &it) : it(it.it){};
|
||||
|
||||
CRangeListIterator(decltype(data)::Node *n) : n(n){};
|
||||
CRangeListIterator(decltype(data)::const_iterator it, decltype(data)::const_iterator end) : it(it), end(end) {
|
||||
if (it != end && !it->second.second)
|
||||
this->it++;
|
||||
}
|
||||
|
||||
reference operator*() const { return n->data; }
|
||||
|
||||
pointer operator->() const { return &(n->data); }
|
||||
reference operator*() const { return (it->second.first); }
|
||||
|
||||
pointer operator->() const { return &(it->second.first); }
|
||||
|
||||
CRangeListIterator &operator++() {
|
||||
if (n != nullptr && !n->end)
|
||||
n = n->next[0];
|
||||
++it;
|
||||
if (it == end) return *this;
|
||||
++it;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -237,47 +256,44 @@ public:
|
||||
return tmp;
|
||||
}
|
||||
|
||||
friend bool operator==(const CRangeListIterator &a, const CRangeListIterator &b) { return a.n == b.n; };
|
||||
|
||||
friend bool operator!=(const CRangeListIterator &a, const CRangeListIterator &b) { return !(a == b); };
|
||||
friend bool operator==(const CRangeListIterator &a, const CRangeListIterator &b) { return a.it == b.it; };
|
||||
|
||||
friend bool operator!=(const CRangeListIterator &a, const CRangeListIterator &b) { return !(a.it == b.it); };
|
||||
|
||||
private:
|
||||
decltype(data)::Node *n;
|
||||
decltype(data)::const_iterator it;
|
||||
decltype(data)::const_iterator end;
|
||||
};
|
||||
|
||||
using const_iterator = CRangeListIterator;
|
||||
|
||||
const_iterator begin() const {
|
||||
return {data.begin()->before->next[0]};
|
||||
return CRangeListIterator(data.begin(), data.end());
|
||||
}
|
||||
|
||||
const_iterator end() const {
|
||||
return {data.end()->before->next[0]};
|
||||
return CRangeListIterator(data.end(), data.end());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
CRangeList operator+(const CRange &lhs, const CRange &rhs) {
|
||||
return CRangeList{lhs, rhs};
|
||||
}
|
||||
|
||||
CRangeList operator-(const CRange &lhs, const CRange &rhs) {
|
||||
return CRangeList{lhs} - rhs;
|
||||
}
|
||||
|
||||
|
||||
std::string toString(const CRangeList &x) {
|
||||
template<class T>
|
||||
std::string toString(const T &x) {
|
||||
std::ostringstream oss;
|
||||
oss << x;
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
TEST(SkipListDetailedTest, ItWorks) {
|
||||
using sl_detailed_test_list = testing::Types<CRangeList<std::map>, CRangeList<SkipListMap>>;
|
||||
template<class>
|
||||
struct SkipListDetailedTestFixture : testing::Test {};
|
||||
TYPED_TEST_SUITE(SkipListDetailedTestFixture, sl_detailed_test_list);
|
||||
|
||||
TYPED_TEST(SkipListDetailedTestFixture, ItWorks) {
|
||||
assert(std::is_trivially_copyable<CRange>::value);
|
||||
|
||||
CRangeList t;
|
||||
using CRangeListTested = TypeParam;
|
||||
|
||||
CRangeListTested t;
|
||||
|
||||
t = CRange(10, 20);
|
||||
// t.data.print();
|
||||
@@ -285,7 +301,7 @@ TEST(SkipListDetailedTest, ItWorks) {
|
||||
// std::cout << ts;
|
||||
assert(ts == "{<10..20>}");
|
||||
// return 0;
|
||||
t = CRangeList{{10, 15}};
|
||||
t = CRangeListTested{{10, 15}};
|
||||
assert(toString(t) == "{<10..15>}");
|
||||
|
||||
t = CRange(10, 20);
|
||||
@@ -293,13 +309,16 @@ TEST(SkipListDetailedTest, ItWorks) {
|
||||
assert(toString(t) == "{<10..20>}");
|
||||
t += CRange(LLONG_MIN, LLONG_MAX);
|
||||
assert(t.includes(CRange(LLONG_MIN, LLONG_MAX)));
|
||||
ASSERT_EQ(toString(t), "{<-9223372036854775808..9223372036854775807>}");
|
||||
assert(t.includes(LLONG_MIN));
|
||||
assert(t.includes(LLONG_MAX));
|
||||
t -= CRange(LLONG_MIN, LLONG_MAX);
|
||||
ASSERT_EQ(toString(t), "{}");
|
||||
|
||||
t += CRange(LLONG_MIN, LLONG_MAX - 1);
|
||||
ASSERT_EQ(toString(t), "{<-9223372036854775808..9223372036854775806>}");
|
||||
t += CRange(LLONG_MAX, LLONG_MAX);
|
||||
assert(toString(t) == "{<-9223372036854775808..9223372036854775807>}");
|
||||
ASSERT_EQ(toString(t), "{<-9223372036854775808..9223372036854775807>}");
|
||||
t -= CRange(LLONG_MIN, LLONG_MAX);
|
||||
assert(toString(t) == "{}");
|
||||
|
||||
@@ -358,7 +377,7 @@ TEST(SkipListDetailedTest, ItWorks) {
|
||||
|
||||
t += CRange(50, 55);
|
||||
assert(toString(t) == "{<2..4>,<10..80>,<100..150>}");
|
||||
auto t2 = CRange(6, 9) + CRange(151, 160);
|
||||
auto t2 = CRangeListTested() + CRange(6, 9) + CRange(151, 160);
|
||||
assert(toString(t2) == "{<6..9>,<151..160>}");
|
||||
t += t2;
|
||||
s = toString(t);
|
||||
@@ -371,9 +390,9 @@ TEST(SkipListDetailedTest, ItWorks) {
|
||||
t -= CRange(1000, 1100);
|
||||
assert(toString(t) == "{<-100..200>}");
|
||||
|
||||
t = CRangeList{{10, 15},
|
||||
{20, 25},
|
||||
{30, 40}};
|
||||
t = CRangeListTested{{10, 15},
|
||||
{20, 25},
|
||||
{30, 40}};
|
||||
// t.data.print();
|
||||
assert(toString(t) == "{<10..15>,<20..25>,<30..40>}");
|
||||
t -= CRange(40, 9999);
|
||||
@@ -389,7 +408,7 @@ TEST(SkipListDetailedTest, ItWorks) {
|
||||
t -= CRange(22, 22);
|
||||
assert(toString(t) == "{<14..15>,<20..21>,<23..25>,<30..34>}");
|
||||
|
||||
t = CRangeList();
|
||||
t = CRangeListTested();
|
||||
t += CRange(0, 100);
|
||||
assert(toString(t) == "{<0..100>}");
|
||||
t += CRange(200, 300);
|
||||
@@ -401,19 +420,19 @@ TEST(SkipListDetailedTest, ItWorks) {
|
||||
t -= CRange(170, 170);
|
||||
assert(toString(t) == "{<0..100>,<160..169>,<171..180>,<251..300>}");
|
||||
|
||||
t = CRangeList();
|
||||
t = CRangeListTested();
|
||||
t += CRange(10, 90);
|
||||
t -= CRange(20, 30);
|
||||
t -= CRange(40, 50);
|
||||
t -= CRange(60, 90);
|
||||
t += CRange(70, 80);
|
||||
|
||||
t2 = CRange(10, 90) - CRange(20, 30) - CRange(40, 50) - CRange(60, 90) + CRange(70, 80);
|
||||
t2 = CRangeListTested() + CRange(10, 90) - CRange(20, 30) - CRange(40, 50) - CRange(60, 90) + CRange(70, 80);
|
||||
ts = toString(t);
|
||||
auto ts2 = toString(t2);
|
||||
assert(ts == ts2);
|
||||
|
||||
CRangeList a, b;
|
||||
CRangeListTested a, b;
|
||||
|
||||
assert(sizeof(CRange) <= 2 * sizeof(long long));
|
||||
a = CRange(5, 10);
|
||||
@@ -422,22 +441,22 @@ TEST(SkipListDetailedTest, ItWorks) {
|
||||
a += CRange(-5, 0);
|
||||
a += CRange(8, 50);
|
||||
assert(toString(a) == "{<-5..0>,<5..100>}");
|
||||
a += CRange(101, 105) + CRange(120, 150) + CRange(160, 180) + CRange(190, 210);
|
||||
a += CRangeListTested() + CRange(101, 105) + CRange(120, 150) + CRange(160, 180) + CRange(190, 210);
|
||||
assert(toString(a) == "{<-5..0>,<5..105>,<120..150>,<160..180>,<190..210>}");
|
||||
a += CRange(106, 119) + CRange(152, 158);
|
||||
a += CRangeListTested() + CRange(106, 119) + CRange(152, 158);
|
||||
assert(toString(a) == "{<-5..0>,<5..150>,<152..158>,<160..180>,<190..210>}");
|
||||
a += CRange(-3, 170);
|
||||
a += CRange(-30, 1000);
|
||||
assert(toString(a) == "{<-30..1000>}");
|
||||
b = CRange(-500, -300) + CRange(2000, 3000) + CRange(700, 1001);
|
||||
b = CRangeListTested() + CRange(-500, -300) + CRange(2000, 3000) + CRange(700, 1001);
|
||||
a += b;
|
||||
assert(toString(a) == "{<-500..-300>,<-30..1001>,<2000..3000>}");
|
||||
a -= CRange(-400, -400);
|
||||
assert(toString(a) == "{<-500..-401>,<-399..-300>,<-30..1001>,<2000..3000>}");
|
||||
a -= CRange(10, 20) + CRange(900, 2500) + CRange(30, 40) + CRange(10000, 20000);
|
||||
a -= CRangeListTested() + CRange(10, 20) + CRange(900, 2500) + CRange(30, 40) + CRange(10000, 20000);
|
||||
assert(toString(a) == "{<-500..-401>,<-399..-300>,<-30..9>,<21..29>,<41..899>,<2501..3000>}");
|
||||
try {
|
||||
a += CRange(15, 18) + CRange(10, 0) + CRange(35, 38);
|
||||
a += CRangeListTested() + CRange(15, 18) + CRange(10, 0) + CRange(35, 38);
|
||||
assert("Exception not thrown" == nullptr);
|
||||
} catch (const std::logic_error &e) {
|
||||
} catch (...) {
|
||||
@@ -449,6 +468,7 @@ TEST(SkipListDetailedTest, ItWorks) {
|
||||
assert(!(a != b));
|
||||
b += CRange(2600, 2700);
|
||||
assert(toString(b) == "{<-500..-401>,<-399..-300>,<-30..9>,<21..29>,<41..899>,<2501..3000>}");
|
||||
assert(toString(a) == "{<-500..-401>,<-399..-300>,<-30..9>,<21..29>,<41..899>,<2501..3000>}");
|
||||
assert(a == b);
|
||||
assert(!(a != b));
|
||||
b += CRange(15, 15);
|
||||
@@ -463,28 +483,28 @@ TEST(SkipListDetailedTest, ItWorks) {
|
||||
assert(!b.includes(CRange(800, 900)));
|
||||
assert(!b.includes(CRange(-1000, -450)));
|
||||
assert(!b.includes(CRange(0, 500)));
|
||||
a += CRange(-10000, 10000) + CRange(10000000, 1000000000);
|
||||
a += CRangeListTested() + CRange(-10000, 10000) + CRange(10000000, 1000000000);
|
||||
assert(toString(a) == "{<-10000..10000>,<10000000..1000000000>}");
|
||||
b += a;
|
||||
assert(toString(b) == "{<-10000..10000>,<10000000..1000000000>}");
|
||||
b -= a;
|
||||
assert(toString(b) == "{}");
|
||||
b += CRange(0, 100) + CRange(200, 300) - CRange(150, 250) + CRange(160, 180) - CRange(170, 170);
|
||||
b += CRangeListTested() + CRange(0, 100) + CRange(200, 300) - CRange(150, 250) + CRange(160, 180) - CRange(170, 170);
|
||||
// b.data.print();
|
||||
assert(toString(b) == "{<0..100>,<160..169>,<171..180>,<251..300>}");
|
||||
// b.data.print();
|
||||
b -=
|
||||
CRange(10, 90) -
|
||||
CRangeListTested() + CRange(10, 90) -
|
||||
CRange(20, 30) -
|
||||
CRange(40, 50) -
|
||||
CRange(60, 90) +
|
||||
CRange(70, 80);
|
||||
s = toString(b);
|
||||
assert(toString(b) == "{<0..9>,<20..30>,<40..50>,<60..69>,<81..100>,<160..169>,<171..180>,<251..300>}");
|
||||
CRangeList x{{5, 20},
|
||||
{150, 200},
|
||||
{-9, 12},
|
||||
{48, 93}};
|
||||
CRangeListTested x{{5, 20},
|
||||
{150, 200},
|
||||
{-9, 12},
|
||||
{48, 93}};
|
||||
assert(toString(x) == "{<-9..20>,<48..93>,<150..200>}");
|
||||
std::ostringstream oss;
|
||||
oss << std::setfill('=') << std::hex << std::left;
|
||||
@@ -497,8 +517,8 @@ TEST(SkipListDetailedTest, ItWorks) {
|
||||
assert(oss.str() == "-100\n<-9..20>\n<48..93>\n<150..200>\n400=======");
|
||||
|
||||
// FIXME: I'll leave it a "stress test" for now
|
||||
for (long long x = 10; x <= 100; x *= 10) {
|
||||
CRangeList t;
|
||||
for (long long x = 25; x <= 250; x *= 10) {
|
||||
CRangeListTested t;
|
||||
std::cout << x << "====" << std::endl;
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
auto stop = std::chrono::high_resolution_clock::now();
|
||||
|
||||
@@ -10,25 +10,81 @@ struct SkipListTestFixture : testing::Test {};
|
||||
TYPED_TEST_SUITE(SkipListTestFixture, sl_test_list);
|
||||
|
||||
TYPED_TEST(SkipListTestFixture, PlaceAdd) {
|
||||
SkipList<int, TypeParam> test1;
|
||||
SkipListMap<int, TypeParam> test1;
|
||||
SkipListMap<int, TypeParam> test2;
|
||||
SkipListMap<long, TypeParam> test3;
|
||||
SkipListMap<long, TypeParam> test4;
|
||||
SkipListMap<long, long> test5;
|
||||
SkipListMap<long, long> test6;
|
||||
SkipListMap<int, long> test7;
|
||||
SkipListMap<int, long> test8;
|
||||
|
||||
test1.add(5, "test5", false);
|
||||
test1.add(999, "test999", false);
|
||||
test1.add(5, "test5", false);
|
||||
test1.add(1, "test1", false);
|
||||
test1.add(999, "test999", false);
|
||||
test1.emplace(5, "test5");
|
||||
test1.emplace(999, "test999");
|
||||
test1.emplace(5, "test5");
|
||||
test1.emplace(1, "test1");
|
||||
test1.emplace(999, "test999");
|
||||
|
||||
ASSERT_EQ(test1.find(5)->data, "test5");
|
||||
ASSERT_EQ(test1.find(1)->data, "test1");
|
||||
ASSERT_EQ(test1.find(999)->data, "test999");
|
||||
ASSERT_EQ(test1.find(5)->second, "test5");
|
||||
ASSERT_EQ(test1.find(1)->second, "test1");
|
||||
ASSERT_EQ(test1.find(999)->second, "test999");
|
||||
|
||||
typename decltype(test1)::iterator tit = test1.begin();
|
||||
typename decltype(test1)::const_iterator tcit = tit;
|
||||
|
||||
test1.erase(1);
|
||||
ASSERT_NE(test1.find(1)->data, "test1");
|
||||
test1.add(87, "test87", false);
|
||||
ASSERT_EQ(test1.find(87)->data, "test87");
|
||||
ASSERT_EQ(test1.find(1), test1.cend());
|
||||
test1.emplace(87, "test87");
|
||||
ASSERT_EQ(test1.find(87)->second, "test87");
|
||||
|
||||
auto p2 = test1.lower_bound_update(78);
|
||||
ASSERT_EQ(p2->data, "test87");
|
||||
test1.add(78, "test78", true);
|
||||
ASSERT_EQ(test1.find(78)->data, "test78");
|
||||
test1.emplace(78, "test78");
|
||||
ASSERT_EQ(test1.find(78)->second, "test78");
|
||||
}
|
||||
TYPED_TEST(SkipListTestFixture, MultiMapTest) {
|
||||
SkipListMultiMap<int, TypeParam> test1;
|
||||
|
||||
test1.emplace(5, "test5");
|
||||
test1.emplace(999, "test999");
|
||||
test1.emplace(5, "test5");
|
||||
test1.emplace(1, "test1");
|
||||
test1.emplace(999, "test999");
|
||||
|
||||
ASSERT_EQ(test1.find(5)->second, "test5");
|
||||
ASSERT_EQ(test1.find(1)->second, "test1");
|
||||
ASSERT_EQ(test1.find(999)->second, "test999");
|
||||
|
||||
test1.erase(1);
|
||||
ASSERT_EQ(test1.find(1), test1.cend());
|
||||
test1.emplace(87, "test87");
|
||||
ASSERT_EQ(test1.find(87)->second, "test87");
|
||||
|
||||
test1.emplace(78, "test78");
|
||||
ASSERT_EQ(test1.find(78)->second, "test78");
|
||||
|
||||
ASSERT_EQ(test1.find(5)->second, "test5");
|
||||
ASSERT_EQ(test1.find(999)->second, "test999");
|
||||
test1.erase(5);
|
||||
test1.erase(999);
|
||||
ASSERT_EQ(test1.find(5)->second, "test5");
|
||||
ASSERT_EQ(test1.find(999)->second, "test999");
|
||||
test1.erase(5);
|
||||
test1.erase(999);
|
||||
ASSERT_EQ(test1.find(5), test1.end());
|
||||
ASSERT_EQ(test1.find(999), test1.end());
|
||||
|
||||
auto r1 = test1.emplace(999, "test9991");
|
||||
ASSERT_TRUE(r1.second);
|
||||
ASSERT_EQ(r1.first->second, "test9991");
|
||||
auto r2 = test1.emplace(999, "test9992");
|
||||
ASSERT_TRUE(r2.second);
|
||||
ASSERT_EQ(r2.first->second, "test9992");
|
||||
auto r3 = test1.emplace(999, "test9993");
|
||||
ASSERT_TRUE(r3.second);
|
||||
ASSERT_EQ(r3.first->second, "test9993");
|
||||
|
||||
test1.erase(r2.first);
|
||||
ASSERT_TRUE(r1.second);
|
||||
ASSERT_EQ(r1.first->second, "test9991");
|
||||
ASSERT_TRUE(r3.second);
|
||||
ASSERT_EQ(r3.first->second, "test9993");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user