Logo ROOT  
Reference Guide
MPSendRecv.h
Go to the documentation of this file.
1/* @(#)root/multiproc:$Id$ */
2// Author: Enrico Guiraud July 2015
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#ifndef ROOT_MPSendRecv
13#define ROOT_MPSendRecv
14
15#include "TBufferFile.h"
16#include "TClass.h"
17#include "TError.h"
18#include "TSocket.h"
19#include <memory> //unique_ptr
20#include <type_traits> //enable_if
21#include <typeinfo> //typeid
22#include <utility> //pair
23#include <string>
24
25//////////////////////////////////////////////////////////////////////////
26/// An std::pair that wraps the code and optional object contained in a message.
27/// \param first message code
28/// \param second a smart pointer to a TBufferFile that contains the message object\n
29/// The smart pointer is null if the message does not contain an object
30/// but only consists of a code. See MPRecv() description on how to
31/// retrieve the object from the TBufferFile.
32using MPCodeBufPair = std::pair<unsigned, std::unique_ptr<TBufferFile>>;
33
34
35/************ FUNCTIONS' DECLARATIONS *************/
36
37// There are several versions of this function: this is one sends a
38// message with a code and no object. The templated versions are used
39// to send a code and an object of any non-pointer type.
40int MPSend(TSocket *s, unsigned code);
41
42template<class T, typename std::enable_if<std::is_class<T>::value>::type * = nullptr>
43int MPSend(TSocket *s, unsigned code, T obj);
44
45template < class T, typename std::enable_if < !std::is_class<T>::value &&!std::is_pointer<T>::value >::type * = nullptr >
46int MPSend(TSocket *s, unsigned code, T obj);
47
48template<class T, typename std::enable_if<std::is_same<const char *, T>::value>::type * = nullptr>
49int MPSend(TSocket *s, unsigned code, T obj);
50
51template < class T, typename std::enable_if < std::is_pointer<T>::value &&std::is_constructible<TObject *, T>::value >::type * = nullptr >
52int MPSend(TSocket *s, unsigned code, T obj);
53
55
56
57//this version reads classes from the message
58template<class T, typename std::enable_if<std::is_class<T>::value>::type * = nullptr>
60
61//this version reads built-in types from the message
62template < class T, typename std::enable_if < !std::is_class<T>::value &&!std::is_pointer<T>::value >::type * = nullptr >
64
65//this version reads std::string and c-strings from the message
66template<class T, typename std::enable_if<std::is_same<const char *, T>::value>::type * = nullptr>
68
69//this version reads a TObject* from the message
70template < class T, typename std::enable_if < std::is_pointer<T>::value &&std::is_constructible<TObject *, T>::value >::type * = nullptr >
72
73
74/************ TEMPLATE FUNCTIONS' IMPLEMENTATIONS *******************/
75
76//////////////////////////////////////////////////////////////////////////
77/// Send a message with a code and an object to socket s.
78/// The number of bytes sent is returned, as per TSocket::SendRaw.
79/// This standalone function can be used to send a code and possibly
80/// an object on a given socket. This function does not check whether the
81/// socket connection is in a valid state. MPRecv() must be used to
82/// retrieve the contents of the message.\n
83/// **Note:** only objects the headers of which have been parsed by
84/// cling can be sent using MPSend(). User-defined types can be made available to
85/// cling via a call like `gSystem->ProcessLine("#include \"header.h\"")`.
86/// Pointer types cannot be sent via MPSend() (with the exception of const char*).
87/// \param s a pointer to a valid TSocket. No validity checks are performed\n
88/// \param code the code to be sent
89/// \param obj the object to be sent
90/// \return the number of bytes sent, as per TSocket::SendRaw
91template<class T, typename std::enable_if<std::is_class<T>::value>::type *>
92int MPSend(TSocket *s, unsigned code, T obj)
93{
94 TClass *c = TClass::GetClass<T>();
95 if (!c) {
96 Error("MPSend", "[E] Could not find cling definition for class %s\n", typeid(T).name());
97 return -1;
98 }
100 objBuf.WriteObjectAny(&obj, c);
102 wBuf.WriteUInt(code);
103 wBuf.WriteULong(objBuf.Length());
104 wBuf.WriteBuf(objBuf.Buffer(), objBuf.Length());
105 return s->SendRaw(wBuf.Buffer(), wBuf.Length());
106}
107
108/// \cond
109// send a built-in type that is not a pointer (under the hypothesis that
110// TBuffer's operator<< works with any built-in type that is not a pointer)
111template < class T, typename std::enable_if < !std::is_class<T>::value &&!std::is_pointer<T>::value >::type * >
112int MPSend(TSocket *s, unsigned code, T obj)
113{
115 ULong_t size = sizeof(T);
116 wBuf << code << size << obj;
117 return s->SendRaw(wBuf.Buffer(), wBuf.Length());
118}
119
120// send an null-terminated c-string or an std::string (which is converted to a c-string)
121//TODO can this become a partial specialization instead?
122template<class T, typename std::enable_if<std::is_same<const char *, T>::value>::type *>
123int MPSend(TSocket *s, unsigned code, T obj)
124{
126 wBuf.WriteUInt(code);
127 wBuf.WriteULong(strlen(obj) + 1); //strlen does not count the trailing \0
128 wBuf.WriteString(obj);
129 return s->SendRaw(wBuf.Buffer(), wBuf.Length());
130}
131
132// send a TObject*. Allows polymorphic behaviour and pters to derived classes
133template < class T, typename std::enable_if < std::is_pointer<T>::value && std::is_constructible<TObject *, T>::value >::type * >
134int MPSend(TSocket *s, unsigned code, T obj)
135{
136 //find out the size of the object
138 if(obj != nullptr)
139 objBuf.WriteObjectAny(obj, obj->IsA());
140
141 //write everything together in a buffer
143 wBuf.WriteUInt(code);
144 wBuf.WriteULong(objBuf.Length());
145 if(objBuf.Length())
146 wBuf.WriteBuf(objBuf.Buffer(), objBuf.Length());
147 return s->SendRaw(wBuf.Buffer(), wBuf.Length());
148}
149
150/// \endcond
151
152//////////////////////////////////////////////////////////////////////////
153/// One of the template functions used to read objects from messages.
154/// Different implementations are provided for different types of objects:
155/// classes, non-pointer built-ins and const char*. Reading pointers is
156/// not implemented (at the time of writing, sending pointers is not either).
157template<class T, typename std::enable_if<std::is_class<T>::value>::type *>
159{
160 TClass *c = TClass::GetClass(typeid(T));
161 T *objp = (T *)buf->ReadObjectAny(c);
162 T obj = *objp; //this is slow, but couldn't find a better way of returning a T without leaking memory
163 delete objp;
164 return obj;
165}
166
167/// \cond
168template < class T, typename std::enable_if < !std::is_class<T>::value &&!std::is_pointer<T>::value >::type * >
170{
171 //read built-in type
172 T obj;
173 *(buf) >> obj;
174 return obj;
175}
176
177template<class T, typename std::enable_if<std::is_same<const char *, T>::value>::type *>
179{
180 //read c-string
181 char *c = new char[buf->BufferSize()];
182 buf->ReadString(c, buf->BufferSize());
183 return c;
184}
185
186template < class T, typename std::enable_if < std::is_pointer<T>::value &&std::is_constructible<TObject *, T>::value >::type * >
188{
189 //read TObject*
190 using objType = typename std::remove_pointer<T>::type;
191 return (T)buf->ReadObjectAny(objType::Class());
192}
193/// \endcond
194
195#endif
void Class()
Definition: Class.C:29
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:32
MPCodeBufPair MPRecv(TSocket *s)
Receive message from a socket.
Definition: MPSendRecv.cxx:54
int MPSend(TSocket *s, unsigned code)
Send a message with the specified code on the specified socket.
Definition: MPSendRecv.cxx:32
T ReadBuffer(TBufferFile *buf)
One of the template functions used to read objects from messages.
Definition: MPSendRecv.h:158
#define c(i)
Definition: RSha256.hxx:101
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
unsigned long ULong_t
Definition: RtypesCore.h:55
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition: TError.cxx:187
char name[80]
Definition: TGX11.cxx:110
int type
Definition: TGX11.cxx:121
The concrete implementation of TBuffer for writing/reading to/from a ROOT file or socket.
Definition: TBufferFile.h:47
void WriteBuf(const void *buf, Int_t max) override
Write max bytes from buf into the I/O buffer.
void WriteUInt(UInt_t i) override
Definition: TBufferFile.h:314
char * ReadString(char *s, Int_t max) override
Read string from I/O buffer.
void WriteULong(ULong_t l) override
Definition: TBufferFile.h:328
void * ReadObjectAny(const TClass *cast) override
Read object from I/O buffer.
Int_t WriteObjectAny(const void *obj, const TClass *ptrClass, Bool_t cacheReuse=kTRUE) override
Write object to I/O buffer.
Definition: TBufferIO.cxx:492
Int_t BufferSize() const
Definition: TBuffer.h:98
@ kWrite
Definition: TBuffer.h:73
Int_t Length() const
Definition: TBuffer.h:100
char * Buffer() const
Definition: TBuffer.h:96
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:80
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:2955
double T(double x)
Definition: ChebyshevPol.h:34
static constexpr double s