1 //===- llvm/ExecutionEngine/Orc/RPCChannel.h --------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef LLVM_EXECUTIONENGINE_ORC_RPCCHANNEL_H 11 #define LLVM_EXECUTIONENGINE_ORC_RPCCHANNEL_H 12 13 #include "OrcError.h" 14 #include "llvm/ADT/ArrayRef.h" 15 #include "llvm/ADT/STLExtras.h" 16 #include "llvm/ADT/StringRef.h" 17 #include "llvm/Support/Endian.h" 18 #include "llvm/Support/Error.h" 19 #include <cstddef> 20 #include <cstdint> 21 #include <mutex> 22 #include <string> 23 #include <tuple> 24 #include <vector> 25 26 namespace llvm { 27 namespace orc { 28 namespace remote { 29 30 /// Interface for byte-streams to be used with RPC. 31 class RPCChannel { 32 public: 33 virtual ~RPCChannel() {} 34 35 /// Read Size bytes from the stream into *Dst. 36 virtual Error readBytes(char *Dst, unsigned Size) = 0; 37 38 /// Read size bytes from *Src and append them to the stream. 39 virtual Error appendBytes(const char *Src, unsigned Size) = 0; 40 41 /// Flush the stream if possible. 42 virtual Error send() = 0; 43 44 /// Get the lock for stream reading. 45 std::mutex &getReadLock() { return readLock; } 46 47 /// Get the lock for stream writing. 48 std::mutex &getWriteLock() { return writeLock; } 49 50 private: 51 std::mutex readLock, writeLock; 52 }; 53 54 /// Notify the channel that we're starting a message send. 55 /// Locks the channel for writing. 56 inline Error startSendMessage(RPCChannel &C) { 57 C.getWriteLock().lock(); 58 return Error::success(); 59 } 60 61 /// Notify the channel that we're ending a message send. 62 /// Unlocks the channel for writing. 63 inline Error endSendMessage(RPCChannel &C) { 64 C.getWriteLock().unlock(); 65 return Error::success(); 66 } 67 68 /// Notify the channel that we're starting a message receive. 69 /// Locks the channel for reading. 70 inline Error startReceiveMessage(RPCChannel &C) { 71 C.getReadLock().lock(); 72 return Error::success(); 73 } 74 75 /// Notify the channel that we're ending a message receive. 76 /// Unlocks the channel for reading. 77 inline Error endReceiveMessage(RPCChannel &C) { 78 C.getReadLock().unlock(); 79 return Error::success(); 80 } 81 82 /// RPC channel serialization for a variadic list of arguments. 83 template <typename T, typename... Ts> 84 Error serializeSeq(RPCChannel &C, const T &Arg, const Ts &... Args) { 85 if (auto Err = serialize(C, Arg)) 86 return Err; 87 return serializeSeq(C, Args...); 88 } 89 90 /// RPC channel serialization for an (empty) variadic list of arguments. 91 inline Error serializeSeq(RPCChannel &C) { return Error::success(); } 92 93 /// RPC channel deserialization for a variadic list of arguments. 94 template <typename T, typename... Ts> 95 Error deserializeSeq(RPCChannel &C, T &Arg, Ts &... Args) { 96 if (auto Err = deserialize(C, Arg)) 97 return Err; 98 return deserializeSeq(C, Args...); 99 } 100 101 /// RPC channel serialization for an (empty) variadic list of arguments. 102 inline Error deserializeSeq(RPCChannel &C) { return Error::success(); } 103 104 /// RPC channel serialization for integer primitives. 105 template <typename T> 106 typename std::enable_if< 107 std::is_same<T, uint64_t>::value || std::is_same<T, int64_t>::value || 108 std::is_same<T, uint32_t>::value || std::is_same<T, int32_t>::value || 109 std::is_same<T, uint16_t>::value || std::is_same<T, int16_t>::value || 110 std::is_same<T, uint8_t>::value || std::is_same<T, int8_t>::value, 111 Error>::type 112 serialize(RPCChannel &C, T V) { 113 support::endian::byte_swap<T, support::big>(V); 114 return C.appendBytes(reinterpret_cast<const char *>(&V), sizeof(T)); 115 } 116 117 /// RPC channel deserialization for integer primitives. 118 template <typename T> 119 typename std::enable_if< 120 std::is_same<T, uint64_t>::value || std::is_same<T, int64_t>::value || 121 std::is_same<T, uint32_t>::value || std::is_same<T, int32_t>::value || 122 std::is_same<T, uint16_t>::value || std::is_same<T, int16_t>::value || 123 std::is_same<T, uint8_t>::value || std::is_same<T, int8_t>::value, 124 Error>::type 125 deserialize(RPCChannel &C, T &V) { 126 if (auto Err = C.readBytes(reinterpret_cast<char *>(&V), sizeof(T))) 127 return Err; 128 support::endian::byte_swap<T, support::big>(V); 129 return Error::success(); 130 } 131 132 /// RPC channel serialization for enums. 133 template <typename T> 134 typename std::enable_if<std::is_enum<T>::value, Error>::type 135 serialize(RPCChannel &C, T V) { 136 return serialize(C, static_cast<typename std::underlying_type<T>::type>(V)); 137 } 138 139 /// RPC channel deserialization for enums. 140 template <typename T> 141 typename std::enable_if<std::is_enum<T>::value, Error>::type 142 deserialize(RPCChannel &C, T &V) { 143 typename std::underlying_type<T>::type Tmp; 144 Error Err = deserialize(C, Tmp); 145 V = static_cast<T>(Tmp); 146 return Err; 147 } 148 149 /// RPC channel serialization for bools. 150 inline Error serialize(RPCChannel &C, bool V) { 151 uint8_t VN = V ? 1 : 0; 152 return C.appendBytes(reinterpret_cast<const char *>(&VN), 1); 153 } 154 155 /// RPC channel deserialization for bools. 156 inline Error deserialize(RPCChannel &C, bool &V) { 157 uint8_t VN = 0; 158 if (auto Err = C.readBytes(reinterpret_cast<char *>(&VN), 1)) 159 return Err; 160 161 V = (VN != 0); 162 return Error::success(); 163 } 164 165 /// RPC channel serialization for StringRefs. 166 /// Note: There is no corresponding deseralization for this, as StringRef 167 /// doesn't own its memory and so can't hold the deserialized data. 168 inline Error serialize(RPCChannel &C, StringRef S) { 169 if (auto Err = serialize(C, static_cast<uint64_t>(S.size()))) 170 return Err; 171 return C.appendBytes((const char *)S.bytes_begin(), S.size()); 172 } 173 174 /// RPC channel serialization for std::strings. 175 inline Error serialize(RPCChannel &C, const std::string &S) { 176 return serialize(C, StringRef(S)); 177 } 178 179 /// RPC channel deserialization for std::strings. 180 inline Error deserialize(RPCChannel &C, std::string &S) { 181 uint64_t Count; 182 if (auto Err = deserialize(C, Count)) 183 return Err; 184 S.resize(Count); 185 return C.readBytes(&S[0], Count); 186 } 187 188 // Serialization helper for std::tuple. 189 template <typename TupleT, size_t... Is> 190 inline Error serializeTupleHelper(RPCChannel &C, const TupleT &V, 191 llvm::index_sequence<Is...> _) { 192 return serializeSeq(C, std::get<Is>(V)...); 193 } 194 195 /// RPC channel serialization for std::tuple. 196 template <typename... ArgTs> 197 inline Error serialize(RPCChannel &C, const std::tuple<ArgTs...> &V) { 198 return serializeTupleHelper(C, V, llvm::index_sequence_for<ArgTs...>()); 199 } 200 201 // Serialization helper for std::tuple. 202 template <typename TupleT, size_t... Is> 203 inline Error deserializeTupleHelper(RPCChannel &C, TupleT &V, 204 llvm::index_sequence<Is...> _) { 205 return deserializeSeq(C, std::get<Is>(V)...); 206 } 207 208 /// RPC channel deserialization for std::tuple. 209 template <typename... ArgTs> 210 inline Error deserialize(RPCChannel &C, std::tuple<ArgTs...> &V) { 211 return deserializeTupleHelper(C, V, llvm::index_sequence_for<ArgTs...>()); 212 } 213 214 /// RPC channel serialization for ArrayRef<T>. 215 template <typename T> Error serialize(RPCChannel &C, const ArrayRef<T> &A) { 216 if (auto Err = serialize(C, static_cast<uint64_t>(A.size()))) 217 return Err; 218 219 for (const auto &E : A) 220 if (auto Err = serialize(C, E)) 221 return Err; 222 223 return Error::success(); 224 } 225 226 /// RPC channel serialization for std::array<T>. 227 template <typename T> Error serialize(RPCChannel &C, const std::vector<T> &V) { 228 return serialize(C, ArrayRef<T>(V)); 229 } 230 231 /// RPC channel deserialization for std::array<T>. 232 template <typename T> Error deserialize(RPCChannel &C, std::vector<T> &V) { 233 uint64_t Count = 0; 234 if (auto Err = deserialize(C, Count)) 235 return Err; 236 237 V.resize(Count); 238 for (auto &E : V) 239 if (auto Err = deserialize(C, E)) 240 return Err; 241 242 return Error::success(); 243 } 244 245 } // end namespace remote 246 } // end namespace orc 247 } // end namespace llvm 248 249 #endif // LLVM_EXECUTIONENGINE_ORC_RPCCHANNEL_H 250