2009-07-29 12:07:54 +02:00
|
|
|
/*
|
2014-01-02 12:00:57 +01:00
|
|
|
Copyright (c) 2007-2014 Contributors as noted in the AUTHORS file
|
2009-07-29 12:07:54 +02:00
|
|
|
|
|
|
|
This file is part of 0MQ.
|
|
|
|
|
|
|
|
0MQ is free software; you can redistribute it and/or modify it under
|
2010-10-30 15:08:28 +02:00
|
|
|
the terms of the GNU Lesser General Public License as published by
|
2009-07-29 12:07:54 +02:00
|
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
0MQ is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2010-10-30 15:08:28 +02:00
|
|
|
GNU Lesser General Public License for more details.
|
2009-07-29 12:07:54 +02:00
|
|
|
|
2010-10-30 15:08:28 +02:00
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
2009-07-29 12:07:54 +02:00
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2009-08-03 11:30:13 +02:00
|
|
|
#ifndef __ZMQ_PIPE_HPP_INCLUDED__
|
|
|
|
#define __ZMQ_PIPE_HPP_INCLUDED__
|
2009-07-29 12:07:54 +02:00
|
|
|
|
2011-04-21 22:27:48 +02:00
|
|
|
#include "msg.hpp"
|
2013-08-17 22:08:07 +02:00
|
|
|
#include "ypipe_base.hpp"
|
2009-07-29 12:07:54 +02:00
|
|
|
#include "config.hpp"
|
2009-08-27 10:54:28 +02:00
|
|
|
#include "object.hpp"
|
2011-06-22 16:51:40 +02:00
|
|
|
#include "stdint.hpp"
|
2011-05-22 17:26:53 +02:00
|
|
|
#include "array.hpp"
|
2011-11-04 08:00:47 +01:00
|
|
|
#include "blob.hpp"
|
2014-04-30 15:34:55 +02:00
|
|
|
#include "fd.hpp"
|
2009-07-29 12:07:54 +02:00
|
|
|
|
2009-08-03 11:30:13 +02:00
|
|
|
namespace zmq
|
2009-07-29 12:07:54 +02:00
|
|
|
{
|
|
|
|
|
2011-11-09 15:22:20 +01:00
|
|
|
class object_t;
|
|
|
|
class pipe_t;
|
|
|
|
|
2011-05-22 17:26:53 +02:00
|
|
|
// Create a pipepair for bi-directional transfer of messages.
|
|
|
|
// First HWM is for messages passed from first pipe to the second pipe.
|
|
|
|
// Second HWM is for messages passed from second pipe to the first pipe.
|
2011-06-23 07:57:47 +02:00
|
|
|
// Delay specifies how the pipe behaves when the peer terminates. If true
|
|
|
|
// pipe receives all the pending messages before terminating, otherwise it
|
|
|
|
// terminates straight away.
|
2013-08-17 22:08:07 +02:00
|
|
|
// If conflate is true, only the most recently arrived message could be
|
|
|
|
// read (older messages are discarded)
|
2011-11-09 15:22:20 +01:00
|
|
|
int pipepair (zmq::object_t *parents_ [2], zmq::pipe_t* pipes_ [2],
|
2013-08-20 23:48:04 +02:00
|
|
|
int hwms_ [2], bool conflate_ [2]);
|
2010-08-06 17:49:37 +02:00
|
|
|
|
2011-05-22 17:26:53 +02:00
|
|
|
struct i_pipe_events
|
2010-08-06 17:49:37 +02:00
|
|
|
{
|
2011-05-22 17:26:53 +02:00
|
|
|
virtual ~i_pipe_events () {}
|
2010-09-07 17:06:33 +02:00
|
|
|
|
2011-11-09 15:22:20 +01:00
|
|
|
virtual void read_activated (zmq::pipe_t *pipe_) = 0;
|
|
|
|
virtual void write_activated (zmq::pipe_t *pipe_) = 0;
|
|
|
|
virtual void hiccuped (zmq::pipe_t *pipe_) = 0;
|
2013-05-28 16:49:24 +02:00
|
|
|
virtual void pipe_terminated (zmq::pipe_t *pipe_) = 0;
|
2010-08-06 17:49:37 +02:00
|
|
|
};
|
|
|
|
|
2011-05-23 21:36:00 +02:00
|
|
|
// Note that pipe can be stored in three different arrays.
|
|
|
|
// The array of inbound pipes (1), the array of outbound pipes (2) and
|
|
|
|
// the generic array of pipes to deallocate (3).
|
|
|
|
|
2011-05-22 17:26:53 +02:00
|
|
|
class pipe_t :
|
|
|
|
public object_t,
|
2011-05-23 21:36:00 +02:00
|
|
|
public array_item_t <1>,
|
|
|
|
public array_item_t <2>,
|
|
|
|
public array_item_t <3>
|
2009-08-27 10:54:28 +02:00
|
|
|
{
|
2011-05-22 17:26:53 +02:00
|
|
|
// This allows pipepair to create pipe objects.
|
2013-08-20 23:48:04 +02:00
|
|
|
friend int pipepair (zmq::object_t *parents_ [2], zmq::pipe_t* pipes_ [2],
|
|
|
|
int hwms_ [2], bool conflate_ [2]);
|
2014-08-12 09:31:19 +02:00
|
|
|
|
2010-08-06 17:49:37 +02:00
|
|
|
public:
|
2009-08-27 10:54:28 +02:00
|
|
|
|
2011-05-22 17:26:53 +02:00
|
|
|
// Specifies the object to send events to.
|
|
|
|
void set_event_sink (i_pipe_events *sink_);
|
2009-08-28 16:51:46 +02:00
|
|
|
|
2011-06-22 16:51:40 +02:00
|
|
|
// Pipe endpoint can store an opaque ID to be used by its clients.
|
2011-11-04 08:00:47 +01:00
|
|
|
void set_identity (const blob_t &identity_);
|
|
|
|
blob_t get_identity ();
|
2011-06-22 16:51:40 +02:00
|
|
|
|
2014-01-12 21:58:36 +01:00
|
|
|
blob_t get_credential () const;
|
|
|
|
|
2009-09-30 10:08:35 +02:00
|
|
|
// Returns true if there is at least one message to read in the pipe.
|
|
|
|
bool check_read ();
|
|
|
|
|
2009-08-27 10:54:28 +02:00
|
|
|
// Reads a message to the underlying pipe.
|
2011-04-21 22:27:48 +02:00
|
|
|
bool read (msg_t *msg_);
|
2009-08-27 10:54:28 +02:00
|
|
|
|
2011-05-22 17:26:53 +02:00
|
|
|
// Checks whether messages can be written to the pipe. If writing
|
|
|
|
// the message would cause high watermark the function returns false.
|
2012-03-28 06:38:25 +02:00
|
|
|
bool check_write ();
|
2009-08-27 10:54:28 +02:00
|
|
|
|
|
|
|
// Writes a message to the underlying pipe. Returns false if the
|
|
|
|
// message cannot be written because high watermark was reached.
|
2011-04-21 22:27:48 +02:00
|
|
|
bool write (msg_t *msg_);
|
2009-08-27 10:54:28 +02:00
|
|
|
|
2011-05-22 17:26:53 +02:00
|
|
|
// Remove unfinished parts of the outbound message from the pipe.
|
2010-03-09 08:43:20 +01:00
|
|
|
void rollback ();
|
|
|
|
|
2009-08-27 10:54:28 +02:00
|
|
|
// Flush the messages downsteam.
|
|
|
|
void flush ();
|
|
|
|
|
2011-05-30 10:07:34 +02:00
|
|
|
// Temporaraily disconnects the inbound message stream and drops
|
|
|
|
// all the messages on the fly. Causes 'hiccuped' event to be generated
|
|
|
|
// in the peer.
|
|
|
|
void hiccup ();
|
2014-08-12 09:31:19 +02:00
|
|
|
|
2013-08-18 12:16:21 +02:00
|
|
|
// Ensure the pipe wont block on receiving pipe_term.
|
|
|
|
void set_nodelay ();
|
2011-05-30 10:07:34 +02:00
|
|
|
|
2011-05-22 17:26:53 +02:00
|
|
|
// Ask pipe to terminate. The termination will happen asynchronously
|
|
|
|
// and user will be notified about actual deallocation by 'terminated'
|
2011-05-31 14:36:51 +02:00
|
|
|
// event. If delay is true, the pending messages will be processed
|
|
|
|
// before actual shutdown.
|
|
|
|
void terminate (bool delay_);
|
2009-08-28 16:51:46 +02:00
|
|
|
|
2013-09-14 18:27:18 +02:00
|
|
|
// set the high water marks.
|
|
|
|
void set_hwms (int inhwm_, int outhwm_);
|
|
|
|
|
2014-08-08 19:36:00 +02:00
|
|
|
// check HWM
|
2014-08-12 09:31:19 +02:00
|
|
|
bool check_hwm () const;
|
2014-04-30 15:34:55 +02:00
|
|
|
// provide a way to link pipe to engine fd. Set on session initialization
|
|
|
|
fd_t assoc_fd; //=retired_fd
|
2009-08-27 10:54:28 +02:00
|
|
|
private:
|
|
|
|
|
2011-05-30 10:07:34 +02:00
|
|
|
// Type of the underlying lock-free pipe.
|
2014-01-06 11:19:56 +01:00
|
|
|
typedef ypipe_base_t <msg_t> upipe_t;
|
2011-05-30 10:07:34 +02:00
|
|
|
|
2009-08-28 16:51:46 +02:00
|
|
|
// Command handlers.
|
2011-05-22 17:26:53 +02:00
|
|
|
void process_activate_read ();
|
|
|
|
void process_activate_write (uint64_t msgs_read_);
|
2011-05-30 10:07:34 +02:00
|
|
|
void process_hiccup (void *pipe_);
|
2009-08-28 16:51:46 +02:00
|
|
|
void process_pipe_term ();
|
2011-05-22 17:26:53 +02:00
|
|
|
void process_pipe_term_ack ();
|
|
|
|
|
2011-05-25 10:25:51 +02:00
|
|
|
// Handler for delimiter read from the pipe.
|
2013-06-22 13:40:32 +02:00
|
|
|
void process_delimiter ();
|
2011-05-25 10:25:51 +02:00
|
|
|
|
2011-05-22 17:26:53 +02:00
|
|
|
// Constructor is private. Pipe can only be created using
|
|
|
|
// pipepair function.
|
|
|
|
pipe_t (object_t *parent_, upipe_t *inpipe_, upipe_t *outpipe_,
|
2013-08-20 23:48:04 +02:00
|
|
|
int inhwm_, int outhwm_, bool conflate_);
|
2010-03-01 10:13:26 +01:00
|
|
|
|
2011-05-22 17:26:53 +02:00
|
|
|
// Pipepair uses this function to let us know about
|
|
|
|
// the peer pipe object.
|
|
|
|
void set_peer (pipe_t *pipe_);
|
2010-06-21 15:06:51 +02:00
|
|
|
|
2011-05-22 17:26:53 +02:00
|
|
|
// Destructor is private. Pipe objects destroy themselves.
|
|
|
|
~pipe_t ();
|
2009-08-27 10:54:28 +02:00
|
|
|
|
2011-05-22 17:26:53 +02:00
|
|
|
// Underlying pipes for both directions.
|
|
|
|
upipe_t *inpipe;
|
|
|
|
upipe_t *outpipe;
|
2009-08-27 10:54:28 +02:00
|
|
|
|
2011-05-22 17:26:53 +02:00
|
|
|
// Can the pipe be read from / written to?
|
|
|
|
bool in_active;
|
|
|
|
bool out_active;
|
|
|
|
|
|
|
|
// High watermark for the outbound pipe.
|
2011-03-24 15:43:03 +01:00
|
|
|
int hwm;
|
2009-08-27 10:54:28 +02:00
|
|
|
|
2011-05-22 17:26:53 +02:00
|
|
|
// Low watermark for the inbound pipe.
|
|
|
|
int lwm;
|
2010-03-01 10:13:26 +01:00
|
|
|
|
2011-05-22 17:26:53 +02:00
|
|
|
// Number of messages read and written so far.
|
|
|
|
uint64_t msgs_read;
|
2010-03-01 10:13:26 +01:00
|
|
|
uint64_t msgs_written;
|
|
|
|
|
2011-05-22 17:26:53 +02:00
|
|
|
// Last received peer's msgs_read. The actual number in the peer
|
|
|
|
// can be higher at the moment.
|
|
|
|
uint64_t peers_msgs_read;
|
2010-06-21 15:06:51 +02:00
|
|
|
|
2011-05-22 17:26:53 +02:00
|
|
|
// The pipe object on the other side of the pipepair.
|
|
|
|
pipe_t *peer;
|
|
|
|
|
|
|
|
// Sink to send events to.
|
|
|
|
i_pipe_events *sink;
|
|
|
|
|
2013-05-28 13:18:19 +02:00
|
|
|
// States of the pipe endpoint:
|
|
|
|
// active: common state before any termination begins,
|
|
|
|
// delimiter_received: delimiter was read from pipe before
|
|
|
|
// term command was received,
|
|
|
|
// waiting_fo_delimiter: term command was already received
|
|
|
|
// from the peer but there are still pending messages to read,
|
|
|
|
// term_ack_sent: all pending messages were already read and
|
|
|
|
// all we are waiting for is ack from the peer,
|
|
|
|
// term_req_sent1: 'terminate' was explicitly called by the user,
|
|
|
|
// term_req_sent2: user called 'terminate' and then we've got
|
|
|
|
// term command from the peer as well.
|
2011-05-25 10:25:51 +02:00
|
|
|
enum {
|
|
|
|
active,
|
2013-05-28 13:18:19 +02:00
|
|
|
delimiter_received,
|
|
|
|
waiting_for_delimiter,
|
|
|
|
term_ack_sent,
|
|
|
|
term_req_sent1,
|
|
|
|
term_req_sent2
|
2011-05-25 10:25:51 +02:00
|
|
|
} state;
|
2011-05-22 17:26:53 +02:00
|
|
|
|
|
|
|
// If true, we receive all the pending inbound messages before
|
|
|
|
// terminating. If false, we terminate immediately when the peer
|
|
|
|
// asks us to.
|
|
|
|
bool delay;
|
|
|
|
|
2011-11-04 08:00:47 +01:00
|
|
|
// Identity of the writer. Used uniquely by the reader side.
|
|
|
|
blob_t identity;
|
2011-06-22 16:51:40 +02:00
|
|
|
|
2014-01-12 21:58:36 +01:00
|
|
|
// Pipe's credential.
|
|
|
|
blob_t credential;
|
|
|
|
|
2011-05-22 17:26:53 +02:00
|
|
|
// Returns true if the message is delimiter; false otherwise.
|
2014-01-08 07:49:02 +01:00
|
|
|
static bool is_delimiter (const msg_t &msg_);
|
2011-05-22 17:26:53 +02:00
|
|
|
|
|
|
|
// Computes appropriate low watermark from the given high watermark.
|
|
|
|
static int compute_lwm (int hwm_);
|
|
|
|
|
2014-08-14 08:56:48 +02:00
|
|
|
const bool conflate;
|
2013-08-17 22:08:07 +02:00
|
|
|
|
2011-05-22 17:26:53 +02:00
|
|
|
// Disable copying.
|
|
|
|
pipe_t (const pipe_t&);
|
|
|
|
const pipe_t &operator = (const pipe_t&);
|
2009-08-27 10:54:28 +02:00
|
|
|
};
|
|
|
|
|
2009-07-29 12:07:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|