1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
//===----------------------- Queue.h - RPC Queue ------------------*-c++-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_UNITTESTS_EXECUTIONENGINE_ORC_QUEUECHANNEL_H
#define LLVM_UNITTESTS_EXECUTIONENGINE_ORC_QUEUECHANNEL_H
#include "llvm/ExecutionEngine/Orc/RawByteChannel.h"
#include "llvm/Support/Error.h"
#include <condition_variable>
#include <queue>
namespace llvm {
class QueueChannelError : public ErrorInfo<QueueChannelError> {
public:
static char ID;
};
class QueueChannelClosedError
: public ErrorInfo<QueueChannelClosedError, QueueChannelError> {
public:
static char ID;
std::error_code convertToErrorCode() const override {
return inconvertibleErrorCode();
}
void log(raw_ostream &OS) const override {
OS << "Queue closed";
}
};
class Queue : public std::queue<char> {
public:
using ErrorInjector = std::function<Error()>;
Queue()
: ReadError([]() { return Error::success(); }),
WriteError([]() { return Error::success(); }) {}
Queue(const Queue&) = delete;
Queue& operator=(const Queue&) = delete;
Queue(Queue&&) = delete;
Queue& operator=(Queue&&) = delete;
std::mutex &getMutex() { return M; }
std::condition_variable &getCondVar() { return CV; }
Error checkReadError() { return ReadError(); }
Error checkWriteError() { return WriteError(); }
void setReadError(ErrorInjector NewReadError) {
{
std::lock_guard<std::mutex> Lock(M);
ReadError = std::move(NewReadError);
}
CV.notify_one();
}
void setWriteError(ErrorInjector NewWriteError) {
std::lock_guard<std::mutex> Lock(M);
WriteError = std::move(NewWriteError);
}
private:
std::mutex M;
std::condition_variable CV;
std::function<Error()> ReadError, WriteError;
};
class QueueChannel : public orc::rpc::RawByteChannel {
public:
QueueChannel(std::shared_ptr<Queue> InQueue,
std::shared_ptr<Queue> OutQueue)
: InQueue(InQueue), OutQueue(OutQueue) {}
QueueChannel(const QueueChannel&) = delete;
QueueChannel& operator=(const QueueChannel&) = delete;
QueueChannel(QueueChannel&&) = delete;
QueueChannel& operator=(QueueChannel&&) = delete;
Error readBytes(char *Dst, unsigned Size) override {
std::unique_lock<std::mutex> Lock(InQueue->getMutex());
while (Size) {
{
Error Err = InQueue->checkReadError();
while (!Err && InQueue->empty()) {
InQueue->getCondVar().wait(Lock);
Err = InQueue->checkReadError();
}
if (Err)
return Err;
}
*Dst++ = InQueue->front();
--Size;
++NumRead;
InQueue->pop();
}
return Error::success();
}
Error appendBytes(const char *Src, unsigned Size) override {
std::unique_lock<std::mutex> Lock(OutQueue->getMutex());
while (Size--) {
if (Error Err = OutQueue->checkWriteError())
return Err;
OutQueue->push(*Src++);
++NumWritten;
}
OutQueue->getCondVar().notify_one();
return Error::success();
}
Error send() override { return Error::success(); }
void close() {
auto ChannelClosed = []() { return make_error<QueueChannelClosedError>(); };
InQueue->setReadError(ChannelClosed);
InQueue->setWriteError(ChannelClosed);
OutQueue->setReadError(ChannelClosed);
OutQueue->setWriteError(ChannelClosed);
}
uint64_t NumWritten = 0;
uint64_t NumRead = 0;
private:
std::shared_ptr<Queue> InQueue;
std::shared_ptr<Queue> OutQueue;
};
inline std::pair<std::unique_ptr<QueueChannel>, std::unique_ptr<QueueChannel>>
createPairedQueueChannels() {
auto Q1 = std::make_shared<Queue>();
auto Q2 = std::make_shared<Queue>();
auto C1 = llvm::make_unique<QueueChannel>(Q1, Q2);
auto C2 = llvm::make_unique<QueueChannel>(Q2, Q1);
return std::make_pair(std::move(C1), std::move(C2));
}
}
#endif
|