ROOT  6.06/09
Reference Guide
MPSendRecv.h
Go to the documentation of this file.
1 #ifndef ROOT_MPSendRecv
2 #define ROOT_MPSendRecv
3 
4 #include "TBufferFile.h"
5 #include "TClass.h"
6 #include "TSocket.h"
7 #include <typeinfo> //typeid
8 #include <utility> //pair
9 #include <memory> //unique_ptr
10 #include <type_traits> //enable_if
11 #include <iostream>
12 
13 //////////////////////////////////////////////////////////////////////////
14 /// An std::pair that wraps the code and optional object contained in a message.
15 /// \param first message code
16 /// \param second a smart pointer to a TBufferFile that contains the message object\n
17 /// The smart pointer is null if the message does not contain an object
18 /// but only consists of a code. See MPRecv() description on how to
19 /// retrieve the object from the TBufferFile.
20 using MPCodeBufPair = std::pair<unsigned, std::unique_ptr<TBufferFile>>;
21 
22 
23 /************ FUNCTIONS' DECLARATIONS *************/
24 
25 // There are several versions of this function: this is one sends a
26 // message with a code and no object. The templated versions are used
27 // to send a code and an object of any non-pointer type.
28 int MPSend(TSocket *s, unsigned code);
29 
31 int MPSend(TSocket *s, unsigned code, T obj);
32 
34 int MPSend(TSocket *s, unsigned code, T obj);
35 
37 int MPSend(TSocket *s, unsigned code, T obj);
38 
40 int MPSend(TSocket *s, unsigned code, T obj);
41 
43 
44 
45 //this version reads classes from the message
48 
49 //this version reads built-in types from the message
52 
53 //this version reads std::string and c-strings from the message
56 
57 //this version reads a TObject* from the message
60 
61 
62 /************ TEMPLATE FUNCTIONS' IMPLEMENTATIONS *******************/
63 
64 //////////////////////////////////////////////////////////////////////////
65 /// Send a message with a code and an object to socket s.
66 /// The number of bytes sent is returned, as per TSocket::SendRaw.
67 /// This standalone function can be used to send a code and possibly
68 /// an object on a given socket. This function does not check whether the
69 /// socket connection is in a valid state. MPRecv() must be used to
70 /// retrieve the contents of the message.\n
71 /// **Note:** only objects the headers of which have been parsed by
72 /// cling can be sent using MPSend(). User-defined types can be made available to
73 /// cling via a call like `gSystem->ProcessLine("#include \"header.h\"")`.
74 /// Pointer types cannot be sent via MPSend() (with the exception of const char*).
75 /// \param s a pointer to a valid TSocket. No validity checks are performed\n
76 /// \param code the code to be sent
77 /// \param obj the object to be sent
78 /// \return the number of bytes sent, as per TSocket::SendRaw
80 int MPSend(TSocket *s, unsigned code, T obj)
81 {
82  TClass *c = TClass::GetClass(typeid(T));
83  if (!c) {
84  std::cerr << "[E] Could not find cling definition for class " << typeid(T).name() << "\n";
85  return -1;
86  }
88  objBuf.WriteObjectAny(&obj, c);
90  wBuf.WriteUInt(code);
91  wBuf.WriteULong(objBuf.Length());
92  wBuf.WriteBuf(objBuf.Buffer(), objBuf.Length());
93  return s->SendRaw(wBuf.Buffer(), wBuf.Length());
94 }
95 
96 /// \cond
97 // send a built-in type that is not a pointer (under the hypothesis that
98 // TBuffer's operator<< works with any built-in type that is not a pointer)
100 int MPSend(TSocket *s, unsigned code, T obj)
101 {
103  ULong_t size = sizeof(T);
104  wBuf << code << size << obj;
105  return s->SendRaw(wBuf.Buffer(), wBuf.Length());
106 }
107 
108 // send an null-terminated c-string or an std::string (which is converted to a c-string)
109 //TODO can this become a partial specialization instead?
111 int MPSend(TSocket *s, unsigned code, T obj)
112 {
114  wBuf.WriteUInt(code);
115  wBuf.WriteULong(strlen(obj) + 1); //strlen does not count the trailing \0
116  wBuf.WriteString(obj);
117  return s->SendRaw(wBuf.Buffer(), wBuf.Length());
118 }
119 
120 // send a TObject*. Allows polymorphic behaviour and pters to derived classes
122 int MPSend(TSocket *s, unsigned code, T obj)
123 {
124  //find out the size of the object
126  if(obj != nullptr)
127  objBuf.WriteObjectAny(obj, obj->IsA());
128 
129  //write everything together in a buffer
131  wBuf.WriteUInt(code);
132  wBuf.WriteULong(objBuf.Length());
133  if(objBuf.Length())
134  wBuf.WriteBuf(objBuf.Buffer(), objBuf.Length());
135  return s->SendRaw(wBuf.Buffer(), wBuf.Length());
136 }
137 
138 /// \endcond
139 
140 //////////////////////////////////////////////////////////////////////////
141 /// One of the template functions used to read objects from messages.
142 /// Different implementations are provided for different types of objects:
143 /// classes, non-pointer built-ins and const char*. Reading pointers is
144 /// not implemented (at the time of writing, sending pointers is not either).
147 {
148  TClass *c = TClass::GetClass(typeid(T));
149  T *objp = (T *)buf->ReadObjectAny(c);
150  T obj = *objp; //this is slow, but couldn't find a better way of returning a T without leaking memory
151  delete objp;
152  return obj;
153 }
154 
155 /// \cond
158 {
159  //read built-in type
160  T obj;
161  *(buf) >> obj;
162  return obj;
163 }
164 
167 {
168  //read c-string
169  char *c = new char[buf->BufferSize()];
170  buf->ReadString(c, buf->BufferSize());
171  return c;
172 }
173 
176 {
177  //read TObject*
178  using objType = typename std::remove_pointer<T>::type;
179  return (T)buf->ReadObjectAny(objType::Class());
180 }
181 /// \endcond
182 
183 #endif
The concrete implementation of TBuffer for writing/reading to/from a ROOT file or socket...
Definition: TBufferFile.h:51
Small helper to encapsulate whether to return the value pointed to by the iterator or its address...
double T(double x)
Definition: ChebyshevPol.h:34
T ReadBuffer(TBufferFile *buf)
One of the template functions used to read objects from messages.
Definition: MPSendRecv.h:146
int MPSend(TSocket *s, unsigned code)
Send a message with the specified code on the specified socket.
Definition: MPSendRecv.cxx:21
virtual void * ReadObjectAny(const TClass *cast)
Read object from I/O buffer.
virtual void WriteULong(ULong_t l)
Definition: TBufferFile.h:385
virtual Int_t SendRaw(const void *buffer, Int_t length, ESendRecvOptions opt=kDefault)
Send a raw buffer of specified length.
Definition: TSocket.cxx:620
void Class()
Definition: Class.C:29
virtual char * ReadString(char *s, Int_t max)
Read string from I/O buffer.
char * Buffer() const
Definition: TBuffer.h:91
virtual void WriteUInt(UInt_t i)
Definition: TBufferFile.h:371
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:81
virtual void WriteBuf(const void *buf, Int_t max)
Write max bytes from buf into the I/O buffer.
std::pair< unsigned, std::unique_ptr< TBufferFile >> MPCodeBufPair
An std::pair that wraps the code and optional object contained in a message.
Definition: MPSendRecv.h:20
int type
Definition: TGX11.cxx:120
unsigned long ULong_t
Definition: RtypesCore.h:51
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2881
#define name(a, b)
Definition: linkTestLib0.cpp:5
Int_t BufferSize() const
Definition: TBuffer.h:92
Int_t Length() const
Definition: TBuffer.h:94
virtual Int_t WriteObjectAny(const void *obj, const TClass *ptrClass)
Write object to I/O buffer.
TObject * obj
float value
Definition: math.cpp:443
MPCodeBufPair MPRecv(TSocket *s)
Receive message from a socket.
Definition: MPSendRecv.cxx:43