#include "rigid_paradise/piano/piano.h"
|
|
#include "rigid_paradise/piano/function.hpp"
|
|
#include <thread>
|
|
#include <atomic>
|
|
#include <chrono>
|
|
#include <iostream>
|
|
|
|
using namespace std::chrono_literals;
|
|
|
|
rp_piano::locked_list<rp_piano::abstract_channel> registry;
|
|
std::array<rp_piano::locked_list<rp_piano::coro>, queue_count> sched_queue;
|
|
std::atomic_bool running;
|
|
|
|
|
|
void clear_registry() {
|
|
auto sz = registry.data.size();
|
|
while( sz != 0 ){
|
|
sz--;
|
|
auto tmp = registry.pop();
|
|
if(tmp)
|
|
if(tmp.value().waiters.use_count() != 1)
|
|
registry.push( { tmp.value() } );
|
|
}
|
|
return;
|
|
}
|
|
|
|
void rp_piano::abstract_channel::put_waiter(std::list<rp_piano::coro> coros) {
|
|
waiters->push(std::move(coros));
|
|
}
|
|
|
|
std::optional<rp_piano::coro> rp_piano::abstract_channel::get_waiter() {
|
|
return waiters->pop();
|
|
}
|
|
|
|
void spawn(rp_piano::coro&& coro)
|
|
{
|
|
static thread_local std::default_random_engine eng{};
|
|
sched_queue[eng() & (sched_queue.size() - 1)].push({std::move(coro)});
|
|
}
|
|
|
|
int main(int argc, char** argv)
|
|
{
|
|
std::vector<std::string_view> args{argv, argv+argc};
|
|
std::vector<std::thread> threads;
|
|
std::vector<std::shared_ptr<std::atomic_int>> activity;
|
|
std::mutex mtx;
|
|
std::atomic_bool poll_activity = false;
|
|
running.store(true);
|
|
|
|
for(auto n = 0; n < std::thread::hardware_concurrency(); ++n)
|
|
{
|
|
activity.push_back(std::make_shared<std::atomic_int>());
|
|
threads.emplace_back([&, n](){
|
|
size_t idx;
|
|
while(running)
|
|
{
|
|
auto data = sched_queue[idx & (sched_queue.size() - 1)].pop();
|
|
if(data)
|
|
{
|
|
data.value()();
|
|
if(poll_activity)
|
|
{
|
|
activity[n]->fetch_add(1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
std::this_thread::yield();
|
|
}
|
|
++idx;
|
|
}
|
|
});
|
|
}
|
|
|
|
auto ret = piano(std::move(args));
|
|
|
|
while(running)
|
|
{
|
|
size_t cnt = 0;
|
|
for(auto& queue : sched_queue)
|
|
{
|
|
auto q = queue.size();
|
|
std::cout << q << "\t";
|
|
cnt+=q;
|
|
}
|
|
if(poll_activity)
|
|
{
|
|
bool test = false;
|
|
for(auto& a : activity)
|
|
{
|
|
test |= a->load();
|
|
}
|
|
if(!test)
|
|
{
|
|
if(!cnt)
|
|
{
|
|
running.store(false);
|
|
}
|
|
}
|
|
poll_activity.store(false);
|
|
}
|
|
else
|
|
{
|
|
if(!cnt)
|
|
{
|
|
for(auto& a : activity)
|
|
{
|
|
*a = 0;
|
|
}
|
|
poll_activity.store(true);
|
|
}
|
|
}
|
|
std::cout << "pa="<< poll_activity.load() << "\tr="<< running.load() << std::endl;
|
|
|
|
std::this_thread::sleep_for(2s);
|
|
}
|
|
|
|
for(auto& t : threads)
|
|
{
|
|
t.join();
|
|
}
|
|
|
|
return ret;
|
|
}
|