Skip to content

Instantly share code, notes, and snippets.

@rightfold
Created November 17, 2014 21:04
Show Gist options
  • Save rightfold/ab904b959e87f70d5ab2 to your computer and use it in GitHub Desktop.
Save rightfold/ab904b959e87f70d5ab2 to your computer and use it in GitHub Desktop.
#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