Home | History | Annotate | Download | only in Orc
      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