-
-
Save rightfold/ab904b959e87f70d5ab2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <cstddef> | |
#include <functional> | |
#include "gc.hpp" | |
#include <mutex> | |
#include <random> | |
#include <vector> | |
namespace Styx { | |
namespace detail { | |
template<typename T> | |
T takeRandomElement(std::vector<T>& elements) { | |
thread_local std::mt19937 prng; | |
std::uniform_int_distribution<std::size_t> dist(0, elements.size() - 1); | |
auto it = elements.begin() + dist(prng); | |
auto result = *it; | |
elements.erase(it); | |
return result; | |
} | |
} | |
class Channel { | |
public: | |
template<typename F> | |
void send(F sendCallback) { | |
std::lock_guard<decltype(mutex)> lock(mutex); | |
if (!receiveCallbacks.empty()) { | |
auto receiveCallback = detail::takeRandomElement(receiveCallbacks); | |
receiveCallback(sendCallback()); | |
} else { | |
sendCallbacks.push_back(std::move(sendCallback)); | |
} | |
} | |
template<typename F> | |
void receive(F receiveCallback) { | |
std::lock_guard<decltype(mutex)> lock(mutex); | |
if (!sendCallbacks.empty()) { | |
auto sendCallback = detail::takeRandomElement(sendCallbacks); | |
receiveCallback(sendCallback()); | |
} else { | |
receiveCallbacks.push_back(std::move(receiveCallback)); | |
} | |
} | |
private: | |
std::mutex mutex; | |
std::vector<std::function<void(GCPtr<>)>> receiveCallbacks; | |
std::vector<std::function<GCPtr<>()>> sendCallbacks; | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment