Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
MPSendRecv.cxx
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 #include "MPSendRecv.h"
13 #include "TBufferFile.h"
14 #include "MPCode.h"
15 #include <memory> //unique_ptr
16 
17 //////////////////////////////////////////////////////////////////////////
18 /// Send a message with the specified code on the specified socket.
19 /// This standalone function can be used to send a code
20 /// on a given socket. It does not check whether the socket connection is
21 /// in a valid state. The message code can then be retrieved via MPRecv().\n
22 /// **Note:** only objects the headers of which have been parsed by
23 /// cling can be sent by MPSend(). User-defined types can be made available to
24 /// cling via a call like `gSystem->ProcessLine("#include \"header.h\"")`.
25 /// Pointer types are not supported (with the exception of const char*),
26 /// but the user can simply dereference the pointer and send the
27 /// pointed object instead.\n
28 /// **Note:** for readability, codes should be enumerated as in EMPCode.\n
29 /// \param s a pointer to a valid TSocket. No validity checks are performed\n
30 /// \param code the code to be sent
31 /// \return the number of bytes sent, as per TSocket::SendRaw
32 int MPSend(TSocket *s, unsigned code)
33 {
34  TBufferFile wBuf(TBuffer::kWrite);
35  wBuf.WriteUInt(code);
36  wBuf.WriteULong(0);
37  return s->SendRaw(wBuf.Buffer(), wBuf.Length());
38 }
39 
40 
41 //////////////////////////////////////////////////////////////////////////
42 /// Receive message from a socket.
43 /// This standalone function can be used to read a message that
44 /// has been sent via MPSend(). The smart pointer contained in the returned
45 /// ::MPCodeBufPair is null if the message does not contain an object,
46 /// otherwise it points to a TBufferFile.
47 /// To retrieve the object from the buffer different methods must be used
48 /// depending on the type of the object to be read:\n
49 /// * non-pointer built-in types: TBufferFile::operator>> must be used\n
50 /// * c-strings: TBufferFile::ReadString must be used\n
51 /// * class types: TBufferFile::ReadObjectAny must be used\n
52 /// \param s a pointer to a valid TSocket. No validity checks are performed\n
53 /// \return ::MPCodeBufPair, i.e. an std::pair containing message code and (possibly) object
54 MPCodeBufPair MPRecv(TSocket *s)
55 {
56  char *rawbuf = new char[sizeof(UInt_t)];
57  //receive message code
58  unsigned nBytes = s->RecvRaw(rawbuf, sizeof(UInt_t));
59  if (nBytes == 0) {
60  return std::make_pair(MPCode::kRecvError, nullptr);
61  }
62  //read message code
63  TBufferFile bufReader(TBuffer::kRead, sizeof(UInt_t), rawbuf, false);
64  unsigned code;
65  bufReader.ReadUInt(code);
66  delete [] rawbuf;
67 
68  //receive object size
69  //ULong_t is sent as 8 bytes irrespective of the size of the type
70  rawbuf = new char[8];
71  s->RecvRaw(rawbuf, 8);
72  bufReader.SetBuffer(rawbuf, 8, false);
73  ULong_t classBufSize;
74  bufReader.ReadULong(classBufSize);
75  delete [] rawbuf;
76 
77  //receive object if needed
78  std::unique_ptr<TBufferFile> objBuf; //defaults to nullptr
79  if (classBufSize != 0) {
80  char *classBuf = new char[classBufSize];
81  s->RecvRaw(classBuf, classBufSize);
82  objBuf.reset(new TBufferFile(TBuffer::kRead, classBufSize, classBuf, true)); //the buffer is deleted by TBuffer's dtor
83  }
84 
85  return std::make_pair(code, std::move(objBuf));
86 }