/usr/include/zmqpp/actor.hpp is in libzmqpp-dev 4.1.2-0ubuntu2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | /*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file is part of zmqpp.
* Copyright (c) 2011-2015 Contributors as noted in the AUTHORS file.
*/
#pragma once
#include <thread>
#include <functional>
#include "socket.hpp"
namespace zmqpp
{
/**
* An actor is a thread with a pair socket connected to its parent.
* It aims to be similar to CMZQ's zactor.
*
* From the parent thread, instancing an actor will spawn a new thread, and install
* a pipe between those two threads.
* 1. The parent's end of the pipe can be retrieved by calling pipe() on the actor.
* 2. The child's end is passed as a parameter to the routine executed in the child's thread.
*
* You don't have to manage the 2 PAIR sockets. The parent's one will be destroyed
* when the actor dies, and the child's end is taken care of when the user routine ends.
*
* @note
* About user-supplied routine return value:
* 1. If the supplied routine returns true, signal::ok will be send to the parent.
* 2. If it returns false, signal::ko is send instead.
*
* @note
* There is a simple protocol between actor and parent to avoid synchronization problem:
* 1. The actor constructor expect to receive either signal::ok or signal::ko before it returns.
* 2. When sending signal::stop (actor destruction or by calling stop()), we expect a response:
* (either signal::ko or signal::ok). This response is used to determine if stop() will return
* true or false when in blocking mode.
*/
class actor
{
public:
/**
* The user defined function type.
*/
typedef std::function<bool (socket *pipe) > ActorStartRoutine;
/**
* Create a new actor. This will effectively create a new thread and runs the user supplied routine.
* The constructor expect a signal from the routine before returning.
*
* Expect to receive either signal::ko or signal::ok before returning.
* If it receives signal::ko, it will throw.
* @param routine to be executed.
*/
actor(ActorStartRoutine routine);
actor(const actor&) = delete;
/**
* Move constructor. The other actor will not be usable anymore.
* Its pipe() method shall return null, and stop() will do nothing.
*/
actor(actor &&o);
/**
* Move-assignment operator.
* @see move constructor.
*/
actor &operator=(actor &&o);
virtual ~actor();
/**
* @return pointer to the parent's end of the pipe
*/
socket *pipe();
/**
* @return const pointer to the parent's end of the pipe
*/
const socket *pipe() const;
/**
* Sends signal::stop to the actor thread.
* The actor thread shall stop as soon as possible.
* The return value is only relevant when block is true. If block is false (the default), this method
* will return true.
*
* It is safe to call stop() multiple time (to ask the actor to shutdown, and then a bit
* later call stop(true) to make sure it is really stopped)
*
* @note calling this method on an "empty" actor (after it was moved) will return
* false and nothing will happen.
* @param block whether or not we wait until the actor thread stops.
* @return a boolean indicating whether or not the actor successfully shutdown.
*/
bool stop(bool block = false);
private:
/**
* Call a user defined function and performs cleanup once it returns.
* We use a copy of child_pipe_ here; this is to avoid a race condition where the
* destructor would be called before start_routine finishes but after it sent signal::ok / signal::ko.
* The actor object would be invalid (because already destroyed).
*
* @param child a copy of child_pipe_.
* @param routine user routine that will be called
*/
void start_routine(socket *child, ActorStartRoutine routine);
/**
* Bind the parent socket and return the endpoint used.
* Since endpoint are generated and have to be tested for availability
* this method is reponsible for finding a valid endpoint to bind to.
*/
std::string bind_parent();
/**
* The parent thread socket.
* This socket will be closed and freed by the actor destructor.
*/
socket *parent_pipe_;
/**
* The child end of the pipe.
* It is closed and freed when the routine ran by the actor ends.
*/
socket *child_pipe_;
/**
* This static, per process zmqpp::context, is used to connect PAIR socket
* between Actor and their parent thread.
*/
static context actor_pipe_ctx_;
/**
* Keeps track of the status of the actor thread.
*/
bool stopped_;
bool retval_;
};
}
|