|
|
@ -0,0 +1,82 @@ |
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "gp/vfs/process_data.hpp"
|
|
|
|
|
|
|
|
#include <atomic>
|
|
|
|
|
|
|
|
class runqueue{ |
|
|
|
|
|
|
|
struct node{ |
|
|
|
std::atomic_bool is_locked; |
|
|
|
gp::process_data* value; |
|
|
|
std::atomic<struct node*> next; |
|
|
|
|
|
|
|
bool try_acquire() noexcept { |
|
|
|
bool expected = false; |
|
|
|
return !(is_locked.compare_exchange_strong(expected, true)); |
|
|
|
} |
|
|
|
|
|
|
|
void release() noexcept { |
|
|
|
is_locked.store(false); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
using node_ptr = struct node*; |
|
|
|
using node_ptr_rep = std::atomic<struct node*>; |
|
|
|
|
|
|
|
struct topic_list{ |
|
|
|
node_ptr_rep start; |
|
|
|
node_ptr_rep end; |
|
|
|
|
|
|
|
// NODES ARE ACQUIRED ON POP
|
|
|
|
node_ptr try_pop() { |
|
|
|
auto ptr = start.load(); |
|
|
|
if(!ptr) return nullptr; |
|
|
|
|
|
|
|
if(ptr->try_acquire()) { |
|
|
|
auto replace = ptr->next.load(); |
|
|
|
auto expected = ptr; |
|
|
|
if(end.load() == ptr) { |
|
|
|
end.store(nullptr); |
|
|
|
} |
|
|
|
if(start.compare_exchange_strong(expected, replace)) { |
|
|
|
return ptr; |
|
|
|
} else { |
|
|
|
return nullptr; |
|
|
|
} |
|
|
|
} else { |
|
|
|
return nullptr; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// ONLY PUSH ACQUIRED NODES
|
|
|
|
bool try_push(node_ptr node) { |
|
|
|
auto ed = end.load(); |
|
|
|
if(ed) { |
|
|
|
if(ed->try_acquire()) { |
|
|
|
node->next.store(ed); |
|
|
|
if(end.compare_exchange_strong(ed, node)) { |
|
|
|
ed->release(); |
|
|
|
node->release(); |
|
|
|
return true; |
|
|
|
} else { |
|
|
|
ed->release(); |
|
|
|
node->release(); |
|
|
|
return false; |
|
|
|
} |
|
|
|
} else return false; |
|
|
|
} else { |
|
|
|
if(end.compare_exchange_strong(ed, node)) { |
|
|
|
start.store(node); |
|
|
|
node->release(); |
|
|
|
return true; |
|
|
|
} else { |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
topic_list running; |
|
|
|
topic_list waiting; |
|
|
|
}; |