Logo ROOT  
Reference Guide
BidirMMapPipe Class Reference

BidirMMapPipe creates a bidirectional channel between the current process and a child it forks.

Author
Manuel Schiller manue.nosp@m.l.sc.nosp@m.hille.nosp@m.r@ni.nosp@m.khef..nosp@m.nl
Date
2013-07-07

This class creates a bidirectional channel between this process and a child it creates with fork().

The channel is comrised of a small shared pool of buffer memory mmapped into both process spaces, and two pipes to synchronise the exchange of data. The idea behind using the pipes at all is to have some primitive which we can block on without having to worry about atomic operations or polling, leaving these tasks to the OS. In case the anonymous mmap cannot be performed on the OS the code is running on (for whatever reason), the code falls back to mmapping /dev/zero, mmapping a temporary file, or (if those all fail), a dynamically allocated buffer which is then transmitted through the pipe(s), a slightly slower alternative (because the data is copied more often).

The channel supports five major operations: read(), write(), flush(), purge() and close(). Reading and writing may block until the required buffer space is available. Writes may queue up data to be sent to the other end until either enough pages are full, or the user calls flush which forces any unsent buffers to be sent to the other end. flush forces any data that is to be sent to be sent. purge discards any buffered data waiting to be read and/or sent. Closing the channel on the child returns zero, closing it on the parent returns the child's exit status.

The class also provides operator<< and operator>> for C++-style I/O for basic data types (bool, char, short, int, long, long long, float, double and their unsigned counterparts). Data is transmitted binary (i.e. no formatting to strings like std::cout does). There are also overloads to support C-style zero terminated strings and std::string. In terms of performance, the former is to be preferred.

If the caller needs to multiplex input and output to/from several pipes, the class provides the poll() method which allows to block until an event occurs on any of the polled pipes.

After the BidirMMapPipe is closed, no further operations may be performed on that object, save for the destructor which may still be called.

If the BidirMMapPipe has not properly been closed, the destructor will call close. However, the exit code of the child is lost in that case.

Closing the object causes the mmapped memory to be unmapped and the two pipes to be closed. We also install an atexit handler in the process of creating BidirMMapPipes. This ensures that when the current process terminates, a SIGTERM signal is sent to the child processes created for all unclosed pipes to avoid leaving zombie processes in the OS's process table.

BidirMMapPipe creation, closing and destruction are thread safe. If the BidirMMapPipe is used in more than one thread, the other operations have to be protected with a mutex (or something similar), though.

End of file (other end closed its pipe, or died) is indicated with the eof() method, serious I/O errors set a flags (bad(), fail()), and also throw exceptions. For normal read/write operations, they can be suppressed (i.e. error reporting only using flags) with a constructor argument.

Technicalities:

  • there is a pool of mmapped pages, half the pages are allocated to the parent process, half to the child
  • when one side has accumulated enough data (or a flush forces dirty pages out to the other end), it sends these pages to the other end by writing a byte containing the page number into the pipe
  • the other end (which has the pages mmapped, too) reads the page number(s) and puts the corresponding pages on its busy list
  • as the other ends reads, it frees busy pages, and eventually tries to put them on the its list; if a page belongs to the other end of the connection, it is sent back
  • lists of pages are sent across the pipe, not individual pages, in order to minimise the number of read/write operations needed
  • when mmap works properly, only one bytes containing the page number of the page list head is sent back and forth; the contents of that page allow to access the rest of the page list sent, and page headers on the list tell the receiving end if the page is free or has to be added to the busy list
  • when mmap does not work, we transfer one byte to indicate the head of the page list sent, and for each page on the list of sent pages, the page header and the page payload is sent (if the page is free, we only transmit the page header, and we never transmit more payload than the page actually contains)
  • in the child, all open BidirMMapPipes but the current one are closed. this is done for two reasons: first, to conserve file descriptors and address space. second, if more than one process is meant to use such a BidirMMapPipe, synchronisation issues arise which can lead to bugs that are hard to find and understand. it's much better to come up with a design which does not need pipes to be shared among more than two processes.

Here is a trivial example of a parent and a child talking to each other over a BidirMMapPipe:

#include <string>
#include <iostream>
#include <cstdlib>
#include "BidirMMapPipe.h"
int simplechild(BidirMMapPipe& pipe)
{
// child does an echo loop
while (pipe.good() && !pipe.eof()) {
// read a string
std::string str;
pipe >> str;
if (!pipe) return -1;
if (pipe.eof()) break;
// check if parent wants us to shut down
if (!str.empty()) {
std::cout << "[CHILD] : read: " << str << std::endl;
str = "... early in the morning?";
}
pipe << str << BidirMMapPipe::flush;
if (str.empty()) break;
if (!pipe) return -1;
std::cout << "[CHILD] : wrote: " << str << std::endl;
}
// send shutdown request acknowledged
pipe << "" << BidirMMapPipe::flush;
pipe.close();
return 0;
}
BidirMMapPipe* spawnChild(int (*childexec)(BidirMMapPipe&))
{
if (p->isChild()) {
int retVal = childexec(*p);
delete p;
std::exit(retVal);
}
return p;
}
int main()
{
std::cout << "[PARENT]: simple challenge-response test, one child:" <<
std::endl;
BidirMMapPipe* pipe = spawnChild(simplechild);
for (int i = 0; i < 5; ++i) {
std::string str("What shall we do with a drunken sailor...");
*pipe << str << BidirMMapPipe::flush;
if (!*pipe) return -1;
std::cout << "[PARENT]: wrote: " << str << std::endl;
*pipe >> str;
if (!*pipe) return -1;
std::cout << "[PARENT]: read: " << str << std::endl;
}
// ask child to shut down
pipe << "" << BidirMMapPipe::flush;
// wait for it to see the shutdown request
std::string s;
pipe >> s;
std::cout << "[PARENT]: exit status of child: " << pipe->close() <<
std::endl;
delete pipe;
return 0;
}

When designing your own protocols to use over the pipe, there are a few things to bear in mind:

  • Do as http does: When building a request, send all the options and properties of that request with the request itself in a single go (one flush). Then, the server has everything it needs, and hopefully, it'll shut up for a while and to let the client do something useful in the meantime... The same goes when the server replies to the request: include everything there is to know about the result of the request in the reply.
  • The expensive operation should be the request that is made, all other operations should somehow be formulated as options or properties to that request.
  • Include a shutdown handshake in whatever protocol you send over the pipe. That way, you can shut things down in a controlled way. Otherwise, and depending on your OS's scheduling quirks, you may catch a SIGPIPE if one end closes its pipe while the other is still trying to read.

Definition at line 378 of file BidirMMapPipe.h.

Classes

class  PollEntry
 for poll() interface More...
 

Public Types

enum  {
  eofbit = 1, failbit = 2, rderrbit = 4, wrerrbit = 8,
  badbit = rderrbit | wrerrbit, exceptionsbit = 16
}
 flag bits for partial C++ iostream compatibility More...
 
typedef BidirMMapPipe_impl::BidirMMapPipeException Exception
 convenience typedef for BidirMMapPipeException More...
 
enum  PollFlags {
  None = 0, Readable = 1, Writable = 2, ReadError = 4,
  WriteError = 8, Error = ReadError | WriteError, ReadEndOfFile = 32, WriteEndOfFile = 64,
  EndOfFile = ReadEndOfFile | WriteEndOfFile, ReadInvalid = 64, WriteInvalid = 128, Invalid = ReadInvalid | WriteInvalid
}
 condition flags for poll More...
 
typedef std::vector< PollEntryPollVector
 convenience typedef for poll() interface More...
 
typedef std::size_t size_type
 type used to represent sizes More...
 

Public Member Functions

 BidirMMapPipe (bool useExceptions=true, bool useSocketpair=false)
 constructor (forks!) More...
 
 ~BidirMMapPipe ()
 destructor More...
 
bool bad () const
 true on I/O error More...
 
size_type bytesReadableNonBlocking ()
 number of bytes that can be read without blocking More...
 
size_type bytesWritableNonBlocking ()
 number of bytes that can be written without blocking More...
 
int close ()
 flush buffers, close pipe More...
 
bool closed () const
 true if closed More...
 
bool eof () const
 true if end-of-file More...
 
bool fail () const
 logical failure (e.g. More...
 
void flush ()
 flush buffers with unwritten data More...
 
bool good () const
 status of stream is good More...
 
bool isChild () const
 return if this end of the pipe is the child end More...
 
bool isParent () const
 return if this end of the pipe is the parent end More...
 
 operator bool () const
 return true if not serious error (fail/bad) More...
 
bool operator! () const
 return true if serious error (fail/bad) More...
 
BidirMMapPipeoperator<< (BidirMMapPipe &(*manip)(BidirMMapPipe &))
 I/O manipulator support. More...
 
BidirMMapPipeoperator<< (const char *str)
 write a C-style string More...
 
BidirMMapPipeoperator<< (const std::string &str)
 write a std::string object More...
 
template<class T >
BidirMMapPipeoperator<< (const T *tptr)
 write raw pointer to T to other side More...
 
BidirMMapPipeoperator>> (BidirMMapPipe &(*manip)(BidirMMapPipe &))
 I/O manipulator support. More...
 
BidirMMapPipeoperator>> (char *(&str))
 read a C-style string More...
 
BidirMMapPipeoperator>> (std::string &str)
 read a std::string object More...
 
template<class T >
BidirMMapPipeoperator>> (T *&tptr)
 read raw pointer to T from other side More...
 
pid_t pidOtherEnd () const
 return PID of the process on the other end of the pipe More...
 
void purge ()
 purge buffered data waiting to be read and/or written More...
 
int rdstate () const
 return flags (end of file, BidirMMapPipe closed, ...) More...
 
size_type read (void *addr, size_type sz)
 read from pipe More...
 
 STREAMOP (bool)
 C++ style stream operators for bool. More...
 
 STREAMOP (char)
 C++ style stream operators for char. More...
 
 STREAMOP (double)
 C++ style stream operators for double. More...
 
 STREAMOP (float)
 C++ style stream operators for float. More...
 
 STREAMOP (int)
 C++ style stream operators for int. More...
 
 STREAMOP (long long)
 C++ style stream operators for long long. More...
 
 STREAMOP (long)
 C++ style stream operators for long. More...
 
 STREAMOP (short)
 C++ style stream operators for short. More...
 
 STREAMOP (unsigned char)
 C++ style stream operators for unsigned char. More...
 
 STREAMOP (unsigned int)
 C++ style stream operators for unsigned int. More...
 
 STREAMOP (unsigned long long)
 C++ style stream operators for unsigned long long. More...
 
 STREAMOP (unsigned long)
 C++ style stream operators for unsigned long. More...
 
 STREAMOP (unsigned short)
 C++ style stream operators for unsigned short. More...
 
bool usesPipepair () const
 if BidirMMapPipe uses a pipe pair for communications More...
 
bool usesSocketpair () const
 if BidirMMapPipe uses a socketpair for communications More...
 
size_type write (const void *addr, size_type sz)
 wirte to pipe More...
 

Static Public Member Functions

static int debugflag ()
 return the current setting of the debug flag More...
 
static BidirMMapPipeflush (BidirMMapPipe &pipe)
 for usage a la "pipe << flush;" More...
 
static int poll (PollVector &pipes, int timeout)
 poll a set of pipes for events (ready to read from, ready to write to, error) More...
 
static BidirMMapPipepurge (BidirMMapPipe &pipe)
 for usage a la "pipe << purge;" More...
 
static void setDebugflag (int flag)
 set the debug flags More...
 

Private Types

enum  { TotPages = 16, PagesPerEnd = TotPages / 2, FlushThresh = (3 * PagesPerEnd) / 4 }
 tuning constants More...
 
typedef BidirMMapPipe_impl::Page Page
 convenience typedef for Page More...
 

Private Member Functions

 BidirMMapPipe (const BidirMMapPipe &)
 copy-construction forbidden More...
 
Pagebusypage ()
 get a busy page to read data from (may block) More...
 
Pagedirtypage ()
 get a dirty page to write data to (may block) More...
 
int doClose (bool force, bool holdlock=false)
 close the pipe (no flush if forced) More...
 
void doFlush (bool forcePartialPages=true)
 perform the flush More...
 
void feedPageLists (Page *plist)
 "feed" the busy and free lists with a list of pages More...
 
void markPageDirty (Page *p)
 put on dirty pages list More...
 
BidirMMapPipeoperator= (const BidirMMapPipe &)
 assignment forbidden More...
 
unsigned recvpages ()
 receive a pages from the other end (may block), queue them More...
 
unsigned recvpages_nonblock ()
 receive pages from other end (non-blocking) More...
 
void sendpages (Page *plist)
 send page(s) to the other end (may block) More...
 

Static Private Member Functions

static unsigned lenPageList (const Page *list)
 return length of a page list More...
 
static BidirMMapPipe_impl::PagePool & pagepool ()
 return page pool More...
 
static void teardownall (void)
 cleanup routine - at exit, we want our children to get a SIGTERM... More...
 
static size_type xferraw (int fd, void *addr, const size_type len, ssize_t(*xferfn)(int, const void *, std::size_t))
 transfer bytes through the pipe (reading, writing, may block) More...
 
static size_type xferraw (int fd, void *addr, size_type len, ssize_t(*xferfn)(int, void *, std::size_t))
 transfer bytes through the pipe (reading, writing, may block) More...
 

Private Attributes

Pagem_busylist
 linked list: busy pages (data to be read) More...
 
pid_t m_childPid
 pid of the child (zero if we're child) More...
 
Pagem_dirtylist
 linked list: dirty pages (data to be sent) More...
 
int m_flags
 flags (e.g. end of file) More...
 
Pagem_freelist
 linked list: free pages More...
 
int m_inpipe
 pipe end from which data may be read More...
 
int m_outpipe
 pipe end to which data may be written More...
 
BidirMMapPipe_impl::Pages m_pages
 mmapped pages More...
 
pid_t m_parentPid
 pid of the parent More...
 

Static Private Attributes

static int s_debugflag = 0
 debug flag More...
 
static std::list< BidirMMapPipe * > s_openpipes
 list of open BidirMMapPipes More...
 
static pthread_mutex_t s_openpipesmutex = PTHREAD_MUTEX_INITIALIZER
 protects s_openpipes More...
 
static BidirMMapPipe_impl::PagePool * s_pagepool = 0
 pool of mmapped pages More...
 
static unsigned s_pagepoolrefcnt = 0
 page pool reference counter More...
 

Friends

class BidirMMapPipe_impl::Page
 page is our friend More...
 

#include </home/sftnight/build/workspace/root-makedoc-master/rootspi/rdoc/src/master/roofit/roofitcore/src/BidirMMapPipe.h>

Member Typedef Documentation

◆ Exception

typedef BidirMMapPipe_impl::BidirMMapPipeException BidirMMapPipe::Exception

convenience typedef for BidirMMapPipeException

Definition at line 384 of file BidirMMapPipe.h.

◆ Page

typedef BidirMMapPipe_impl::Page BidirMMapPipe::Page
private

convenience typedef for Page

Definition at line 868 of file BidirMMapPipe.h.

◆ PollVector

typedef std::vector<PollEntry> BidirMMapPipe::PollVector

convenience typedef for poll() interface

Definition at line 535 of file BidirMMapPipe.h.

◆ size_type

typedef std::size_t BidirMMapPipe::size_type

type used to represent sizes

Definition at line 382 of file BidirMMapPipe.h.

Member Enumeration Documentation

◆ anonymous enum

anonymous enum

flag bits for partial C++ iostream compatibility

Enumerator
eofbit 

end of file reached

failbit 

logical failure (e.g. pipe closed)

rderrbit 

read error

wrerrbit 

write error

badbit 

general I/O error

exceptionsbit 

error reporting with exceptions

Definition at line 386 of file BidirMMapPipe.h.

◆ anonymous enum

anonymous enum
private

tuning constants

Enumerator
TotPages 

pages shared (child + parent)

PagesPerEnd 

pages per pipe end

FlushThresh 

flush threshold

Definition at line 871 of file BidirMMapPipe.h.

◆ PollFlags

condition flags for poll

Enumerator
None 

nothing special on this pipe

Readable 

pipe has data for reading

Writable 

pipe can be written to

ReadError 

pipe error read end

WriteError 

pipe error Write end

Error 

pipe error

ReadEndOfFile 

read pipe in end-of-file state

WriteEndOfFile 

write pipe in end-of-file state

EndOfFile 

end of file

ReadInvalid 

read end of pipe invalid

WriteInvalid 

write end of pipe invalid

Invalid 

invalid pipe

Definition at line 506 of file BidirMMapPipe.h.

Constructor & Destructor Documentation

◆ BidirMMapPipe() [1/2]

BidirMMapPipe::BidirMMapPipe ( bool  useExceptions = true,
bool  useSocketpair = false 
)

constructor (forks!)

Creates a bidirectional communications channel between this process and a child the constructor forks. On return from the constructor, isParent() and isChild() can be used to tell the parent end from the child end of the pipe. In the child, all other open BidirMMapPipes are closed.

Parameters
useExceptionsread()/write() error reporting also done using exceptions
useSocketpairuse a socketpair instead of a pair or pipes

Normally, exceptions are thrown for all serious I/O errors (apart from end of file). Setting useExceptions to false will force the read() and write() methods to only report serious I/O errors using flags.

When useSocketpair is true, use a pair of Unix domain sockets created using socketpair instead a pair of pipes. The advantage is that only one pair of file descriptors is needed instead of two pairs which are needed for the pipe pair. Performance should very similar on most platforms, especially if mmap works, since only very little data is sent through the pipe(s)/socketpair.

Definition at line 749 of file BidirMMapPipe.cxx.

◆ ~BidirMMapPipe()

BidirMMapPipe::~BidirMMapPipe ( )

destructor

closes this end of pipe

Definition at line 995 of file BidirMMapPipe.cxx.

◆ BidirMMapPipe() [2/2]

BidirMMapPipe::BidirMMapPipe ( const BidirMMapPipe )
private

copy-construction forbidden

Definition at line 738 of file BidirMMapPipe.cxx.

Member Function Documentation

◆ bad()

bool BidirMMapPipe::bad ( ) const
inline

true on I/O error

Returns
true on I/O error

Definition at line 723 of file BidirMMapPipe.h.

◆ busypage()

BidirMMapPipe::Page * BidirMMapPipe::busypage ( )
private

get a busy page to read data from (may block)

Definition at line 1240 of file BidirMMapPipe.cxx.

◆ bytesReadableNonBlocking()

BidirMMapPipe::size_type BidirMMapPipe::bytesReadableNonBlocking ( )

number of bytes that can be read without blocking

Returns
number of bytes that can be read without blocking

Definition at line 1305 of file BidirMMapPipe.cxx.

◆ bytesWritableNonBlocking()

BidirMMapPipe::size_type BidirMMapPipe::bytesWritableNonBlocking ( )

number of bytes that can be written without blocking

Returns
number of bytes that can be written without blocking

Definition at line 1316 of file BidirMMapPipe.cxx.

◆ close()

int BidirMMapPipe::close ( )

flush buffers, close pipe

Flush buffers, discard unread data, closes the pipe. If the pipe is in the parent process, it waits for the child.

Returns
exit code of child process in parent, zero in child

Definition at line 909 of file BidirMMapPipe.cxx.

◆ closed()

bool BidirMMapPipe::closed ( ) const
inline

true if closed

Returns
true if stream is closed

Definition at line 735 of file BidirMMapPipe.h.

◆ debugflag()

static int BidirMMapPipe::debugflag ( )
inlinestatic

return the current setting of the debug flag

Returns
an integer with the debug Setting

Definition at line 431 of file BidirMMapPipe.h.

◆ dirtypage()

BidirMMapPipe::Page * BidirMMapPipe::dirtypage ( )
private

get a dirty page to write data to (may block)

Definition at line 1251 of file BidirMMapPipe.cxx.

◆ doClose()

int BidirMMapPipe::doClose ( bool  force,
bool  holdlock = false 
)
private

close the pipe (no flush if forced)

Definition at line 915 of file BidirMMapPipe.cxx.

◆ doFlush()

void BidirMMapPipe::doFlush ( bool  forcePartialPages = true)
private

perform the flush

Definition at line 1269 of file BidirMMapPipe.cxx.

◆ eof()

bool BidirMMapPipe::eof ( ) const
inline

true if end-of-file

Returns
true if end-of-file

Definition at line 711 of file BidirMMapPipe.h.

◆ fail()

bool BidirMMapPipe::fail ( ) const
inline

logical failure (e.g.

I/O on closed BidirMMapPipe)

Returns
true in case of grave logical error (I/O on closed pipe,...)

Definition at line 717 of file BidirMMapPipe.h.

◆ feedPageLists()

void BidirMMapPipe::feedPageLists ( Page plist)
private

"feed" the busy and free lists with a list of pages

Parameters
plistlinked list of pages

goes through plist, puts free pages from plist onto the freelist (or sends them to the remote end if they belong there), and puts non-empty pages on plist onto the busy list

Definition at line 1130 of file BidirMMapPipe.cxx.

◆ flush() [1/2]

void BidirMMapPipe::flush ( )

flush buffers with unwritten data

This forces unwritten data to be written to the other end. The call will block until this has been done (or the attempt failed with an error).

Definition at line 1266 of file BidirMMapPipe.cxx.

◆ flush() [2/2]

static BidirMMapPipe& BidirMMapPipe::flush ( BidirMMapPipe pipe)
inlinestatic

for usage a la "pipe << flush;"

Definition at line 855 of file BidirMMapPipe.h.

◆ good()

bool BidirMMapPipe::good ( ) const
inline

status of stream is good

Returns
true if pipe is good (no errors, eof, ...)

Definition at line 729 of file BidirMMapPipe.h.

◆ isChild()

bool BidirMMapPipe::isChild ( ) const
inline

return if this end of the pipe is the child end

Returns
true if child end of pipe

Definition at line 687 of file BidirMMapPipe.h.

◆ isParent()

bool BidirMMapPipe::isParent ( ) const
inline

return if this end of the pipe is the parent end

Returns
true if parent end of pipe

Definition at line 681 of file BidirMMapPipe.h.

◆ lenPageList()

unsigned BidirMMapPipe::lenPageList ( const Page list)
staticprivate

return length of a page list

Definition at line 1123 of file BidirMMapPipe.cxx.

◆ markPageDirty()

void BidirMMapPipe::markPageDirty ( Page p)
private

put on dirty pages list

Definition at line 1226 of file BidirMMapPipe.cxx.

◆ operator bool()

BidirMMapPipe::operator bool ( ) const
inline

return true if not serious error (fail/bad)

Returns
true if stream is does not have serious error (fail/bad)

(if EOF, this is still true)

Definition at line 743 of file BidirMMapPipe.h.

◆ operator!()

bool BidirMMapPipe::operator! ( ) const
inline

return true if serious error (fail/bad)

Returns
true if stream has a serious error (fail/bad)

Definition at line 749 of file BidirMMapPipe.h.

◆ operator<<() [1/4]

BidirMMapPipe& BidirMMapPipe::operator<< ( BidirMMapPipe &(*)(BidirMMapPipe &)  manip)
inline

I/O manipulator support.

Parameters
manipmanipulator
Returns
pipe with manipulator applied

example:

Definition at line 838 of file BidirMMapPipe.h.

◆ operator<<() [2/4]

BidirMMapPipe & BidirMMapPipe::operator<< ( const char *  str)

write a C-style string

Parameters
strC-style string
Returns
pipe written to

Definition at line 1563 of file BidirMMapPipe.cxx.

◆ operator<<() [3/4]

BidirMMapPipe & BidirMMapPipe::operator<< ( const std::string &  str)

write a std::string object

Parameters
strstring to write
Returns
pipe written to

Definition at line 1584 of file BidirMMapPipe.cxx.

◆ operator<<() [4/4]

template<class T >
BidirMMapPipe& BidirMMapPipe::operator<< ( const T *  tptr)
inline

write raw pointer to T to other side

NOTE: This will not write the pointee! Only the value of the pointer is transferred.

Parameters
tptrpointer to be written
Returns
pipe written to

Definition at line 814 of file BidirMMapPipe.h.

◆ operator=()

BidirMMapPipe& BidirMMapPipe::operator= ( const BidirMMapPipe )
inlineprivate

assignment forbidden

Definition at line 863 of file BidirMMapPipe.h.

◆ operator>>() [1/4]

BidirMMapPipe& BidirMMapPipe::operator>> ( BidirMMapPipe &(*)(BidirMMapPipe &)  manip)
inline

I/O manipulator support.

Parameters
manipmanipulator
Returns
pipe with manipulator applied

example:

Definition at line 851 of file BidirMMapPipe.h.

◆ operator>>() [2/4]

BidirMMapPipe & BidirMMapPipe::operator>> ( char *&  str)

read a C-style string

Parameters
strpointer to string (space allocated with malloc!)
Returns
pipe read from

since this is for C-style strings, we use malloc/realloc/free for strings. passing in a NULL pointer is valid here, and the routine will use realloc to allocate a chunk of memory of the right size.

Definition at line 1571 of file BidirMMapPipe.cxx.

◆ operator>>() [3/4]

BidirMMapPipe & BidirMMapPipe::operator>> ( std::string &  str)

read a std::string object

Parameters
strstring to be read
Returns
pipe read from

Definition at line 1592 of file BidirMMapPipe.cxx.

◆ operator>>() [4/4]

template<class T >
BidirMMapPipe& BidirMMapPipe::operator>> ( T *&  tptr)
inline

read raw pointer to T from other side

NOTE: This will not read the pointee! Only the value of the pointer is transferred.

Parameters
tptrpointer to be read
Returns
pipe read from

Definition at line 825 of file BidirMMapPipe.h.

◆ pagepool()

BidirMMapPipe_impl::PagePool & BidirMMapPipe::pagepool ( )
staticprivate

return page pool

Definition at line 718 of file BidirMMapPipe.cxx.

◆ pidOtherEnd()

pid_t BidirMMapPipe::pidOtherEnd ( ) const
inline

return PID of the process on the other end of the pipe

Returns
PID of the process running on the remote end

Definition at line 502 of file BidirMMapPipe.h.

◆ poll()

int BidirMMapPipe::poll ( BidirMMapPipe::PollVector pipes,
int  timeout 
)
static

poll a set of pipes for events (ready to read from, ready to write to, error)

Parameters
pipesset of pipes to check
timeouttimeout in milliseconds
Returns
positive number: number of pipes which have status changes, 0: timeout, or no pipes with status changed, -1 on error

Timeout can be zero (check for specified events, and return), finite (wait at most timeout milliseconds before returning), or -1 (infinite). The poll method returns when the timeout has elapsed, or if an event occurs on one of the pipes being polled, whichever happens earlier.

Pipes is a vector of one or more PollEntries, which each list a pipe and events to poll for. If events is left empty (zero), all conditions are polled for, otherwise only the indicated ones. On return, the revents fields contain the events that occurred for each pipe; error Error, EndOfFile or Invalid events are always set, regardless of wether they were in the set of requested events.

poll may block slightly longer than specified by timeout due to OS timer granularity and OS scheduling. Due to its implementation, the poll call can also return early if the remote end of the page sends a free page while polling (which is put on that pipe's freelist), while that pipe is polled for e.g Reading. The status of the pipe is indicated correctly in revents, and the caller can simply poll again. (The reason this is done this way is because it helps to replenish the pool of free pages and queue busy pages without blocking.)

Here's a piece of example code waiting on two pipes; if they become readable they are read:

#include <unistd.h>
#include <cstdlib>
#include <string>
#include <sstream>
#include <iostream>
#include "BidirMMapPipe.h"
// what to execute in the child
int randomchild(BidirMMapPipe& pipe)
{
::srand48(::getpid());
for (int i = 0; i < 5; ++i) {
// sleep a random time between 0 and .9 seconds
::usleep(int(1e6 * ::drand48()));
std::ostringstream buf;
buf << "child pid " << ::getpid() << " sends message " << i;
std::cout << "[CHILD] : " << buf.str() << std::endl;
pipe << buf.str() << BidirMMapPipe::flush;
if (!pipe) return -1;
if (pipe.eof()) break;
}
// tell parent we're done
pipe << "" << BidirMMapPipe::flush;
// wait for parent to acknowledge
std::string s;
pipe >> s;
pipe.close();
return 0;
}
// function to spawn a child
BidirMMapPipe* spawnChild(int (*childexec)(BidirMMapPipe&))
{
if (p->isChild()) {
int retVal = childexec(*p);
delete p;
std::exit(retVal);
}
return p;
}
int main()
{
typedef BidirMMapPipe::PollEntry PollEntry;
// poll data structure
pipes.reserve(3);
// spawn children
for (int i = 0; i < 3; ++i) {
pipes.push_back(PollEntry(spawnChild(randomchild),
}
// while at least some children alive
while (!pipes.empty()) {
// poll, wait until status change (infinite timeout)
int npipes = BidirMMapPipe::poll(pipes, -1);
// scan for pipes with changed status
for (std::vector<PollEntry>::iterator it = pipes.begin();
npipes && pipes.end() != it; ) {
if (!it->revents) {
// unchanged, next one
++it;
continue;
}
--npipes; // maybe we can stop early...
// read from pipes which are readable
if (it->revents & BidirMMapPipe::Readable) {
std::string s;
*(it->pipe) >> s;
if (!s.empty()) {
std::cout << "[PARENT]: Read from pipe " <<
it->pipe << ": " << s << std::endl;
++it;
continue;
} else {
// child is shutting down...
*(it->pipe) << "" << BidirMMapPipe::flush;
goto childcloses;
}
}
// retire pipes with error or end-of-file condition
if (it->revents & (BidirMMapPipe::Error |
std::cout << "[PARENT]: Error on pipe " <<
it->pipe << " revents " << it->revents <<
std::endl;
childcloses:
std::cout << "[PARENT]:\tchild exit status: " <<
it->pipe->close() << std::endl;
if (retVal) return retVal;
delete it->pipe;
it = pipes.erase(it);
continue;
}
}
}
return 0;
}

Definition at line 1433 of file BidirMMapPipe.cxx.

◆ purge() [1/2]

void BidirMMapPipe::purge ( )

purge buffered data waiting to be read and/or written

Discards all internal buffers.

Definition at line 1288 of file BidirMMapPipe.cxx.

◆ purge() [2/2]

static BidirMMapPipe& BidirMMapPipe::purge ( BidirMMapPipe pipe)
inlinestatic

for usage a la "pipe << purge;"

Definition at line 857 of file BidirMMapPipe.h.

◆ rdstate()

int BidirMMapPipe::rdstate ( ) const
inline

return flags (end of file, BidirMMapPipe closed, ...)

Returns
flags (end of file, BidirMMapPipe closed, ...)

Definition at line 705 of file BidirMMapPipe.h.

◆ read()

BidirMMapPipe::size_type BidirMMapPipe::read ( void addr,
size_type  sz 
)

read from pipe

Parameters
addrwhere to put read data
szsize of data to read (in bytes)
Returns
size of data read, or 0 in case of end-of-file

read may block until data from other end is available. It will return 0 if the other end closed the pipe.

Definition at line 1362 of file BidirMMapPipe.cxx.

◆ recvpages()

unsigned BidirMMapPipe::recvpages ( )
private

receive a pages from the other end (may block), queue them

Returns
number of pages received

this is an application-level scatter read, which gets the list of pages to read from the pipe. if mmap works, it needs only one read call (to get the head of the list of pages transferred). if we need to copy pages through the pipe, we need to add one read for each empty page, and two reads for each non-empty page.

Definition at line 1065 of file BidirMMapPipe.cxx.

◆ recvpages_nonblock()

unsigned BidirMMapPipe::recvpages_nonblock ( )
private

receive pages from other end (non-blocking)

Returns
number of pages received

like recvpages(), but does not block if nothing is available for reading

Definition at line 1098 of file BidirMMapPipe.cxx.

◆ sendpages()

void BidirMMapPipe::sendpages ( Page plist)
private

send page(s) to the other end (may block)

Parameters
plistlinked list of pages to send

the implementation gathers the different write(s) whereever possible; if mmap works, this results in a single write to transfer the list of pages sent, if we need to copy things through the pipe, we have one write to transfer which pages are sent, and then one write per page.

Definition at line 1043 of file BidirMMapPipe.cxx.

◆ setDebugflag()

static void BidirMMapPipe::setDebugflag ( int  flag)
inlinestatic

set the debug flags

Parameters
flagdebug flags (if zero, no messages are printed)

Definition at line 437 of file BidirMMapPipe.h.

◆ STREAMOP() [1/13]

BidirMMapPipe::STREAMOP ( bool  )

C++ style stream operators for bool.

◆ STREAMOP() [2/13]

BidirMMapPipe::STREAMOP ( char  )

C++ style stream operators for char.

◆ STREAMOP() [3/13]

BidirMMapPipe::STREAMOP ( double  )

C++ style stream operators for double.

◆ STREAMOP() [4/13]

BidirMMapPipe::STREAMOP ( float  )

C++ style stream operators for float.

◆ STREAMOP() [5/13]

BidirMMapPipe::STREAMOP ( int  )

C++ style stream operators for int.

◆ STREAMOP() [6/13]

BidirMMapPipe::STREAMOP ( long long  )

C++ style stream operators for long long.

◆ STREAMOP() [7/13]

BidirMMapPipe::STREAMOP ( long  )

C++ style stream operators for long.

◆ STREAMOP() [8/13]

BidirMMapPipe::STREAMOP ( short  )

C++ style stream operators for short.

◆ STREAMOP() [9/13]

BidirMMapPipe::STREAMOP ( unsigned char  )

C++ style stream operators for unsigned char.

◆ STREAMOP() [10/13]

BidirMMapPipe::STREAMOP ( unsigned int  )

C++ style stream operators for unsigned int.

◆ STREAMOP() [11/13]

BidirMMapPipe::STREAMOP ( unsigned long long  )

C++ style stream operators for unsigned long long.

◆ STREAMOP() [12/13]

BidirMMapPipe::STREAMOP ( unsigned long  )

C++ style stream operators for unsigned long.

◆ STREAMOP() [13/13]

BidirMMapPipe::STREAMOP ( unsigned short  )

C++ style stream operators for unsigned short.

◆ teardownall()

void BidirMMapPipe::teardownall ( void  )
staticprivate

cleanup routine - at exit, we want our children to get a SIGTERM...

Definition at line 725 of file BidirMMapPipe.cxx.

◆ usesPipepair()

bool BidirMMapPipe::usesPipepair ( ) const
inline

if BidirMMapPipe uses a pipe pair for communications

Returns
true if BidirMMapPipe uses a pipe pair for communications

Definition at line 699 of file BidirMMapPipe.h.

◆ usesSocketpair()

bool BidirMMapPipe::usesSocketpair ( ) const
inline

if BidirMMapPipe uses a socketpair for communications

Returns
true if BidirMMapPipe uses a socketpair for communications

Definition at line 693 of file BidirMMapPipe.h.

◆ write()

BidirMMapPipe::size_type BidirMMapPipe::write ( const void addr,
size_type  sz 
)

wirte to pipe

Parameters
addrwhere to get data to write from
szsize of data to write (in bytes)
Returns
size of data written, or 0 in case of end-of-file

write may block until data can be written to other end (depends a bit on available buffer space). It will return 0 if the other end closed the pipe. The data is queued to be written on the next convenient occasion, or it can be forced out with flush().

Definition at line 1398 of file BidirMMapPipe.cxx.

◆ xferraw() [1/2]

static size_type BidirMMapPipe::xferraw ( int  fd,
void addr,
const size_type  len,
ssize_t(*)(int, const void *, std::size_t)  xferfn 
)
inlinestaticprivate

transfer bytes through the pipe (reading, writing, may block)

Definition at line 932 of file BidirMMapPipe.h.

◆ xferraw() [2/2]

BidirMMapPipe::size_type BidirMMapPipe::xferraw ( int  fd,
void addr,
size_type  len,
ssize_t(*)(int, void *, std::size_t)  xferfn 
)
staticprivate

transfer bytes through the pipe (reading, writing, may block)

Definition at line 998 of file BidirMMapPipe.cxx.

Friends And Related Function Documentation

◆ BidirMMapPipe_impl::Page

friend class BidirMMapPipe_impl::Page
friend

page is our friend

Definition at line 866 of file BidirMMapPipe.h.

Member Data Documentation

◆ m_busylist

Page* BidirMMapPipe::m_busylist
private

linked list: busy pages (data to be read)

Definition at line 900 of file BidirMMapPipe.h.

◆ m_childPid

pid_t BidirMMapPipe::m_childPid
private

pid of the child (zero if we're child)

Definition at line 906 of file BidirMMapPipe.h.

◆ m_dirtylist

Page* BidirMMapPipe::m_dirtylist
private

linked list: dirty pages (data to be sent)

Definition at line 902 of file BidirMMapPipe.h.

◆ m_flags

int BidirMMapPipe::m_flags
private

flags (e.g. end of file)

Definition at line 905 of file BidirMMapPipe.h.

◆ m_freelist

Page* BidirMMapPipe::m_freelist
private

linked list: free pages

Definition at line 901 of file BidirMMapPipe.h.

◆ m_inpipe

int BidirMMapPipe::m_inpipe
private

pipe end from which data may be read

Definition at line 903 of file BidirMMapPipe.h.

◆ m_outpipe

int BidirMMapPipe::m_outpipe
private

pipe end to which data may be written

Definition at line 904 of file BidirMMapPipe.h.

◆ m_pages

BidirMMapPipe_impl::Pages BidirMMapPipe::m_pages
private

mmapped pages

Definition at line 899 of file BidirMMapPipe.h.

◆ m_parentPid

pid_t BidirMMapPipe::m_parentPid
private

pid of the parent

Definition at line 907 of file BidirMMapPipe.h.

◆ s_debugflag

int BidirMMapPipe::s_debugflag = 0
staticprivate

debug flag

Definition at line 893 of file BidirMMapPipe.h.

◆ s_openpipes

std::list< BidirMMapPipe * > BidirMMapPipe::s_openpipes
staticprivate

list of open BidirMMapPipes

Definition at line 887 of file BidirMMapPipe.h.

◆ s_openpipesmutex

pthread_mutex_t BidirMMapPipe::s_openpipesmutex = PTHREAD_MUTEX_INITIALIZER
staticprivate

protects s_openpipes

Definition at line 885 of file BidirMMapPipe.h.

◆ s_pagepool

BidirMMapPipe_impl::PagePool * BidirMMapPipe::s_pagepool = 0
staticprivate

pool of mmapped pages

Definition at line 889 of file BidirMMapPipe.h.

◆ s_pagepoolrefcnt

unsigned BidirMMapPipe::s_pagepoolrefcnt = 0
staticprivate

page pool reference counter

Definition at line 891 of file BidirMMapPipe.h.


The documentation for this class was generated from the following files:
BidirMMapPipe
BidirMMapPipe creates a bidirectional channel between the current process and a child it forks.
Definition: BidirMMapPipe.h:378
TGeant4Unit::s
static constexpr double s
Definition: TGeant4SystemOfUnits.h:168
BidirMMapPipe::eof
bool eof() const
true if end-of-file
Definition: BidirMMapPipe.h:711
BidirMMapPipe::isChild
bool isChild() const
return if this end of the pipe is the child end
Definition: BidirMMapPipe.h:687
BidirMMapPipe::PollEntry
for poll() interface
Definition: BidirMMapPipe.h:522
BidirMMapPipe::PollVector
std::vector< PollEntry > PollVector
convenience typedef for poll() interface
Definition: BidirMMapPipe.h:535
BidirMMapPipe::poll
static int poll(PollVector &pipes, int timeout)
poll a set of pipes for events (ready to read from, ready to write to, error)
Definition: BidirMMapPipe.cxx:1433
BidirMMapPipe::purge
void purge()
purge buffered data waiting to be read and/or written
Definition: BidirMMapPipe.cxx:1288
BidirMMapPipe::Readable
@ Readable
pipe has data for reading
Definition: BidirMMapPipe.h:508
BidirMMapPipe::good
bool good() const
status of stream is good
Definition: BidirMMapPipe.h:729
BidirMMapPipe::Invalid
@ Invalid
invalid pipe
Definition: BidirMMapPipe.h:518
BidirMMapPipe::Error
@ Error
pipe error
Definition: BidirMMapPipe.h:512
main
int main(int argc, char **argv)
Definition: histspeedtest.cxx:751
BidirMMapPipe::BidirMMapPipe
BidirMMapPipe(bool useExceptions=true, bool useSocketpair=false)
constructor (forks!)
Definition: BidirMMapPipe.cxx:749
BidirMMapPipe::flush
void flush()
flush buffers with unwritten data
Definition: BidirMMapPipe.cxx:1266
BidirMMapPipe::EndOfFile
@ EndOfFile
end of file
Definition: BidirMMapPipe.h:515
BidirMMapPipe::close
int close()
flush buffers, close pipe
Definition: BidirMMapPipe.cxx:909
BidirMMapPipe.h