% \iffalse meta-comment % Copyright (C) 2022 by Martin Vassor % This file may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either % version 1.3 of this license or (at your option) any later % version. The latest version of this license is in: % % http://www.latex-project.org/lppl.txt % % and version 1.3 or later is part of all distributions of % LaTeX version 2005/12/01 or later. % % \fi % \iffalse % \NeedsTeXFormat{LaTeX2e} % \ProvidesPackage{messagepassing}[2023/12/13 v1.2 A package to draw message passing diagrams] % \RequirePackage{tikz} % \usetikzlibrary{quotes, calc, arrows.meta} % \RequirePackage{xparse} % \RequirePackage{float} % %<*driver> \documentclass{ltxdoc} \usepackage{messagepassing} \usepackage[hidelinks]{hyperref} \usepackage{xspace} \usepackage[super]{nth} \usepackage{subcaption} \usepackage{listings} \lstset{ language=[LaTeX]{TeX}, } \EnableCrossrefs \CodelineIndex \RecordChanges \begin{document} \DocInput{messagepassing.dtx} \end{document} % % \fi % \CheckSum{0} % % \CharacterTable % {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z % Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z % Digits \0\1\2\3\4\5\6\7\8\9 % Exclamation \! Double quote \" Hash (number) \# % Dollar \$ Percent \% Ampersand \& % Acute accent \' Left paren \( Right paren \) % Asterisk \* Plus \+ Comma \, % Minus \- Point \. Solidus \/ % Colon \: Semicolon \; Less than \< % Equals \= Greater than \> Question mark \? % Commercial at \@ Left bracket \[ Backslash \\ % Right bracket \] Circumflex \^ Underscore \_ % Grave accent \` Left brace \{ Vertical bar \| % Right brace \} Tilde \~} % % % \changes{v1.2}{2023/12/13}{Add optional display names in processes and message node options} % \changes{v1.1}{2022/07/20}{Consistent spelling of "colour"} % \changes{v1.0}{2022/02/18}{Initial version for publication} % % \GetFileInfo{messagepassing.sty} % % \title{The \textsf{messagepassing} package\thanks{This document % corresponds to \textsf{messagepassing}~\fileversion, % dated \filedate.}} % \author{Martin Vassor\\ \texttt{bromind+ctan@gresille.org}} % % % \maketitle % \tableofcontents % \newcommand{\TikZ}{Ti\textit{k}Z\xspace} % \section{Introduction} % This package provides an environment and associated macros to easily draw % message passing diagrams. For instance, Execution.~\ref{mp:ex1} shows the capabilities offered % by the package. % % \begin{messagepassing}[][An example of message passing][h][mp:ex1] % \newprocesswithlength{p}{9} % \newprocesswithlength{q}{9} % \newprocesswithlength{r}{5} % \crash{r}{5}{k} % % \checkpoint{p}{0}{c_p^0} % \checkpoint{q}{0}{c_q^0} % \checkpoint{r}{0}{c_r^0} % \checkpoint{p}{4}{c_p^1} % % \stateinterval{p}{0}{si_p^0} % \stateinterval{q}{0}{si_q^0} % \stateinterval{r}{0}{si_r^0} % % \sendwithstateinterval{p}{1}{q}{2}{si_q^1} % \sendwithstateinterval{r}{3}{q}{4}{si_q^2} % \sendwithstateintervalandname{q}{5}{p}{6}{si_p^1}{\(m\)} % \sendoutofband{q}{5}{r}{6}{\(m_\mathrm{copy}\)} % \stateinterval{r}{6}{si_r^0} % \restart{r}{6}{3} % % \annotate{r}{8}{restart} % \annotatexplicit{p}{8}{\(1+1=2\)}{note} % % \colouredbox{p}{q}{7}{9}{Protocol} % % \drawtimeline{9} % \end{messagepassing} % % \section{Usage} % \subsection{Loading the package} % The package accepts two options: \verb+vertical+ and \verb+annotatevertical+. % If the former is set, executions will be drawn with time going from top to % bottom, instead of from left to right. Doing so, almost all % labels\footnote{Annotations are not rotated, unless explicitly asked.} are % rotated as well. If, \emph{in addition}, \verb+annotatevertical+ is set, then % annotations (including names of colouredboxes) are rotated as well. % \subsection{Basic usage} % \subsubsection{Creating a diagram.} % \DescribeEnv{messagepassing} A diagram can easily be created using the % |messagepassing| environment. The syntax is: % |\begin{messagepassing}| \oarg{tikz} \oarg{caption} \oarg{placement} % \oarg{label}. % The first optional argument (\emph{tikz}) contains arguments that are passed % to the underlying tikz environment. The second argument (\emph{caption}) has % two effect: if set, it turns the diagram into a floating figure, and the % content of the argument is the caption of the floating figure. The third % argument (\emph{placement}) is the placement option of the figure, the default % is |p|. Finally, the fourth option (\emph{label}) is the label used to % reference the figure. % % For instance, the diagram in Figure~\ref{mp:ex1} is created with the following % commands: % \begin{verbatim} % \begin{messagepassing}[][An example of message passing][h][mp:ex1] % % ... % \end{messagepassing} % \end{verbatim} % \paragraph{Setting up the diagram.} % When created, the diagram is empty. Before actually writing the message % exchanges, we have to set up a few things: set whether we want a timeline (and % if it is the case, of which length), and set the number of processes with % their names, etc. % \subparagraph{Creating a new process.} % Each process is characterised by its name. % \DescribeMacro{\newprocess} The simplest macro to create a new process is then % |\newprocess| \marg{name} \oarg{display name}, where \marg{name} is the name % of the process (resp. \(p\), \(q\), and \(r\) in Figure~\ref{mp:ex1}). If % \oarg{display name} is provided, it is used as the name when rendering the % figure, while \marg{name} is used internally to refer to the process. This % allows you to use names that can not be used internally (e.g.\ with maths or % things like that). % % In addition, we often draw a horizontal\footnote{By default, the line is vertical if % the option |vertical| is used.} line that represent the running process. % Although this line can be manually % added\footnote{|processlength|\marg{process}\marg{length} % creates a line of length \emph{length} for process \emph{process}.}, we also % provide a simple macro that performs both actions: % \DescribeMacro{\newprocesswithlength} % |\newprocesswithlength|\marg{name}\oarg{display name}\marg{length}. % % An other alternative is to name the state in which the process starts (in % Fig~\ref{mp:ex1}, we call those states \(si\) as \emph{state intervals}). % Again, this can be achieved using individual commands, but we also provide % \DescribeMacro{\newprocesswithstateinterval} % |\newprocesswithstateinterval|\marg{name}\oarg{display name}\marg{state name}. % % Finally, an other way to create a process is to create a process that % (eventually) fails, which is represented by the process' line terminating % early with a cross. For that, we provide \DescribeMacro{\newprocesswithcrash} % |\newprocesswithcrash|\marg{name}\oarg{display name}\marg{length}\marg{crash coordinate name}. % The first arguments are similar to |\newprocesswithlength|, and the last one % is used to provide a name for the coordinate where the crash occurs. This name % can later be used to place nodes. % % Of course, we can imagine other combinations (e.g. a process with a length and % a state interval). We do not provide individual commands for each combination, % but the can be easily achieved using separate commands. % % As an example, the processes of Fig.~\ref{mp:ex1} are created as follows. % \begin{verbatim} % \newprocesswithlength{p}{9} % \newprocesswithlength{q}{9} % \newprocesswithlength{r}{5} % \end{verbatim} % % \subparagraph{Setting up a timeline.} % An other setup action consists in setting up (if wanted) the timeline. Notice % that this can be done \emph{at any place} in the diagram. To do so, simply use % the command \DescribeMacro{\drawtimeline}|\drawtimeline|\marg{length}, where % \emph{length} is the length of the desired timeline. % \subsubsection{Populating the run.} % Now that we have some processes, we have to populate the diagram with some % actions. % % \paragraph{Basic message.} % The most basic action is to send a message. For that, we provide the command % \DescribeMacro{\send} |\send|\marg{sender}\marg{send % time}\marg{receiver}\marg{receive time}. The sender and receiver are % identified with their names, and the sending and receiving times are given % according to their timestamp\footnote{Notice that nothing prevents sending % messages in the past, simply set a receiving time before the sending time.}. % % For instance, in Figure~\ref{fig:ex_msg}, we use |\send{p}{1}{q}{2}|. % % In addition, we can label the arrow with the message that is sent with % \DescribeMacro{\sendwithname} % |\sendwithname|\marg{sender}\marg{send time}\marg{receiver}\marg{receive % time}\marg{label}\oarg{label options}. The \marg{label} contains the label % that should be displayed. The package provides default positioning options for % the label, which should be acceptable for most cases. Those positioning % options can be overridden by \oarg{label options}, which should be \TikZ node % options. % % Finally, we sometimes distinguish \emph{out-of-band} messages, e.g. messages % that do not carry informations, but that are for instance used for metadata, % etc.. We provide the macro % \DescribeMacro{\sendoutofband}|\sendoutofband|\marg{sender}\marg{send time}\marg{receiver}\marg{receive % time}\marg{label}\oarg{label options}, which behaves similarly to |\sendwithname|, but prints the % message in an other colour. % % \begin{figure} % \centering % \begin{minipage}{.35\textwidth} % \begin{messagepassing} % \newprocesswithlength{p}{4} % \newprocesswithlength{q}{4} % \send{p}{1}{q}{2} % \sendwithname{p}{2}{q}{3}{msg} % \end{messagepassing} % \end{minipage} % ~ % \begin{minipage}{.60\textwidth} % \iffalse %<*example> % \fi % \begin{lstlisting} \begin{messagepassing} \newprocesswithlength{p}{4} \newprocesswithlength{q}{4} \send{p}{1}{q}{2} \sendwithname{p}{2}{q}{3}{msg} \end{messagepassing} \end{lstlisting} % \iffalse % % \fi % \end{minipage} % \caption{A very simple protocol with a single message exchanged.} % \label{fig:ex_msg} % \end{figure} % % % \paragraph{Process crash and restore.} % The crash of a process can be represented using % \DescribeMacro{\crash} % |\crash|\marg{process name}\marg{time}\marg{crash name}. The argument \emph{process name} % is the name of the process that crashes, and \emph{crash name} is used to give % a name to the crash. Naming the crash is useful for coordinates (see below). % Finally, \emph{time} specifies when the crash occurs. Notice that this does % not modify the timeline: it simply adds a crash token at the specified % coordinate. This means that (i) then timeline has to stop at the crash's time; % and (ii) it has to be restarted after. To stop the timeline, simply take the % crash into account when setting the initial timeline. To restart the timeline, % we provide the command % \DescribeMacro{\restart}|\restart|\marg{name}\marg{date}\marg{duration}. % \emph{name} specifies which process is to be restarted; \emph{date} specifies % when the process should be restarted, and \emph{duration} specifies how long % the process shoud be alive (i.e. what is the length of the timeline) after the % restart. % \begin{figure} % \centering % \begin{minipage}{.35\textwidth} % \begin{messagepassing} % \newprocesswithlength{p}{4} % \newprocesswithlength{q}{2} % \send{p}{1}{q}{2} % \crash{q}{2}{crash} % \restart{q}{3}{1} % \end{messagepassing} % \end{minipage} % ~ % \begin{minipage}{.60\textwidth} % \iffalse %<*example> % \fi % \begin{lstlisting} \begin{messagepassing} \newprocesswithlength{p}{4} \newprocesswithlength{q}{2} \send{p}{1}{q}{2} \crash{q}{2}{crash} \restart{q}{3}{1} \end{messagepassing} \end{lstlisting} % \iffalse % % \fi % \end{minipage} % \caption{A protocol with a crashed process.} % \end{figure} % % \paragraph{Tokens on the run} % % The package also proposes two kinds of tokens that can be added on protocols' % lines. The first one is a \emph{checkpoint} (i.e. a state that is saved % somewhere) and the second is used to denote the begining of a \emph{state % interval} (a state interval denotes a period in which a process only performs % deterministic events). The former are denoted with a small black rectangle, % while the later is denoted with a vertical line. Although those two tokens are % intended for the usage mentionned above, we encourage users to use them for % other usages if need be. % % A checkpoint can be added with % \DescribeMacro{\checkpoint}|\checkpoint|\marg{process}\marg{time}\marg{name}, % where \emph{process} is the name of the process which takes a checkpoint, % \emph{time} is the time at which the checkpoint is taken, and \emph{name} % is the name of the checkpoint, that is printed next to it, and can be used as % a coordinate. Notice that the name is printed in a math environment, as we % expect most checkpoints names to be indexed, e.g.\(c_1\), \(c_2\), etc. % To have more control on the printed name, or if the proposed name is not a % valid coordinate name, we offer a variant % \DescribeMacro{\checkpointspecial}|\checkpointspecial|\marg{process}\marg{time}\marg{name}\marg{label}, % where \emph{name} is the name of the coordinate of the checkpoint, and % \emph{label} is the label to be printed. Notice that, in that case, the label % is printed as is, i.e. not typeset as maths. % % A state interval can be added similarly with the command % \DescribeMacro{\stateinterval}|\stateinterval| % \marg{process}\marg{time}\marg{name}. % % For the sake of completeness, if you need the name of the coordinate and the % displayed label to be different (e.g. if the label can not be the name of a % coordinate, for whatever reason), we also provide the command % \DescribeMacro{\stateintervalspecial} % |\stateintervalspecial|\marg{process}\marg{time}\marg{name}\marg{label}, in % which \emph{name} is the name of the created coordinate, and \emph{label} is % the label attached to the state interval. % \begin{figure} % \centering % \begin{minipage}{.35\textwidth} % \begin{messagepassing} % \newprocesswithlength{q}{2} % \checkpoint{q}{1}{c_1} % \crash{q}{2}{crash} % \restart{q}{3}{1} % \end{messagepassing} % \end{minipage} % ~ % \begin{minipage}{.60\textwidth} % \iffalse %<*example> % \fi % \begin{lstlisting} \begin{messagepassing} \newprocesswithlength{q}{2} \checkpoint{q}{1}{c_1} \crash{q}{2}{crash} \restart{q}{3}{1} \end{messagepassing} \end{lstlisting} % \iffalse % % \fi % \end{minipage} % \caption{A protocol with a checkpoint.} % \end{figure} % \paragraph{Grey boxes} % % In Execution~\ref{mp:ex1}, we created a light-red box between processes \(p\) % and \(q\), from time \(7\) to \(9\), to indicate that they perform a given % protocol that we don't detail further. We call such boxes (which can be used for a lot % of other purposes) \emph{colouredboxes}, and they % can be added with \DescribeMacro{\colouredbox} |\colouredbox|\marg{first % process}\marg{second process}\marg{start time}\marg{end time}\marg{label}. % This creates a box that spans between \emph{first process} and \emph{second % process}, from \emph{start time} to \emph{end time}, with the label % \emph{label} printed. % % Notice that there are no technical restrictions to adding messages on top of a % box, typically to highlight a specific part of a larger execution. % \paragraph{Annotations} % Finally, it is possible to add annotations on the diagram. To do so, we % provide the macro % \DescribeMacro{\annotate}|\annotate|\marg{process}\marg{time}\marg{text} which % adds an annotation with \emph{text} over the timeline of the given % \emph{process} at time \emph{time}. This also creates a coordinate at the % annotation time, which name is the content of the annotation (i.e.\ % \emph{text}). If \emph{text} is not a valid coordinate name, then the % alternative \DescribeMacro{\annotatexplicit} % |\annotatexplicit|\marg{process}\marg{time}\marg{text}\marg{name} behaves % similarly, except that the coordinate name is explicitly given in argument % \emph{name}. % \subsubsection{Combined commands} % The above commands are sufficient to use all primitives offered by the % package. In addition, we provide a lot of \emph{combined commands}, which, as % the name suggest, have the effect of multiple \emph{simple} commands. % % \begin{itemize} % \item |\newprocesswithlength|\marg{name}\marg{lifetime}: combination of % |\newprocess|\marg{name} and |\processlength|\marg{name}\marg{lifetime} % \item |\newprocesswithstateinterval|\marg{process name}\marg{state interval % name}: combination of |\newprocess|\marg{process name} and % |\stateinterval|\marg{process name}\marg{0}\marg{state interval name} % \item |\newprocesswithcrash|\marg{process name}\marg{crash time}\marg{crash % name}: creates a process \emph{process name} that runs until \emph{crash % time}. The crash is named \emph{crash name}. % \item |\sendwithstateinterval|\marg{sender}\marg{send % time}\marg{receiver}\marg{receive time}\marg{si name}: combines |\send| and % |\stateinterval|. % \item |\sendwithstateintervalandname|\marg{sender}\marg{send % time}\marg{receiver}\marg{receive time}\marg{si name}\marg{message name}: % combines |\sendwithname| and |\stateinterval| % \end{itemize} % \subsection{Advanced usage} % \subsubsection{Customising colours} % % Two parts of the package use colours: colouredboxes and out-of-band messages. By % default both are shades of red. We provide commands to change that if desired. % % \DescribeMacro{\colouredboxcolour}|\colouredboxcolour|\marg{colour} changes the colour % used for colouredboxes. Notice that this sets both the background colour (which is % a light variant of the provided colour) and the text colour (which uses the % provided colour). % % \DescribeMacro{\oobcolour}|\oobcolour|\marg{colour} changes the colour used for % out-of-band messages. % % \subsubsection{Coordinates} % % \paragraph{\TikZ coordinates.} % Message passing diagrams are drawn using \TikZ, which means that one can add % arbitrary commands to a diagram. In addition, the package defines useful % coordinates to refer to. Execution~\ref{mp:ex2} shows the \TikZ coordinate plan % overlayed on top of Execution~\ref{mp:ex1}. % % On \TikZ \(y\)-axis processes are instanciated one unit apart from each other, % in their declaration order. % To keep the coordinate system simple, processes expand in the negative (e.g. % the first process declared is at coordinate \((0, -1)\), the second at \((0, % -2)\), etc.). % % The \TikZ \(x\)-axis corresponds to the time axis of the diagram. Therefore, % e.g. coordinate \((3, -4)\) corresponds to the \nth{3} time step of the % \nth{4} process. % % \paragraph{Named coordinates.} % In addition to explicit coordinates explained above, the package names most of % the points of interest in the diagram. % % \subparagraph{Coordinates of processes.} % At each process declaration, a coordinate named after the name of the process % is created. The coordinate corresponds to the beginning of the corresponding % process' timeline (for instance, in Execution~\ref{mp:ex2}, we show coordinate % \((\texttt{q})\), that corresponds to the process \(q\)). % % \subparagraph{Coordinate of states intervals (resp. checkpoints, resp. crashes).} % Similarly to processes, each state interval (resp. checkpoint, resp. crashes) creates a % coordinate, named after the name of the state interval (resp. checkpoint, % resp. crashes), is created. The coordinates refers to the place of the state % interval (resp. checkpoint, resp. crashes). For instance, in % Execution~\ref{mp:ex2}, we show the coordinates \((\texttt{si\_q\^{}1})\), % \((\texttt{c\_p\^{}1})\) and \((\texttt{k})\), that respectively correspond to the state interval % \(si_q^1\), the checkpoint \(c_p^1\) and the crash\footnote{The names of % crashes are not printed on the figure, although they are internally defined.} \(k\). % % \subparagraph{Coordinates of annotations.} % When an annotation is created, a coordinate is created at the same place, on % the process' timeline\footnote{Notice that, using the explicit variant of |annotate| % (|annotatexplicit|), the name of the annotation has to be explicitly given.} % For instance, in Execution~\ref{mp:ex1}, the annotation \(1+1=2\) is created % with the explicit name ``\texttt{note}''. We show the corresponding coordinate in % Execution~\ref{mp:ex2}. % % % \begin{messagepassing}[][Showing \TikZ coordinates][h][mp:ex2] % \newprocesswithlength{p}{9} % \newprocesswithlength{q}{9} % \newprocesswithlength{r}{5} % \crash{r}{5}{k} % % \checkpoint{p}{0}{c_p^0} % \checkpoint{q}{0}{c_q^0} % \checkpoint{r}{0}{c_r^0} % \checkpoint{p}{4}{c_p^1} % % \stateinterval{p}{0}{si_p^0} % \stateinterval{q}{0}{si_q^0} % \stateinterval{r}{0}{si_r^0} % % \sendwithstateinterval{p}{1}{q}{2}{si_q^1} % \sendwithstateinterval{r}{3}{q}{4}{si_q^2} % \sendwithstateintervalandname{q}{5}{p}{6}{si_p^1}{\(m\)} % \sendoutofband{q}{5}{r}{6}{\(m_\mathrm{copy}\)} % \stateinterval{r}{6}{si_r^0} % \restart{r}{6}{3} % % \annotate{r}{8}{restart} % \annotatexplicit{p}{8}{\(1+1=2\)}{note} % % \colouredbox{p}{q}{7}{9}{Protocol} % \drawtimeline{9} % % % \fill[fill=white, opacity=0.8] (-1, 0) rectangle (10, -5); % % \draw[dotted, gray] (-1,0) grid (10,-5); % \draw[->, thick, red] (0, 0) -- (1, 0) node [anchor=south, text=black] {\((1, 0)\)}; % \draw[->, thick, red] (0, 0) -- (0, -1) node [anchor=east, text=black] {\((0, -1)\)}; % % \draw[fill] (q) circle [radius=.5mm]; % \node[anchor=east] at (q) {\((\texttt{q})\)}; % % \draw[fill] (si_q^1) circle [radius=.5mm]; % \node[anchor=east] at (si_q^1) {\((\texttt{si\_q\^{}1})\)}; % % \draw[fill] (c_p^1) circle [radius=.5mm]; % \node[anchor=east] at (c_p^1) {\((\texttt{c\_p\^{}1})\)}; % % \draw[fill] (k) circle [radius=.5mm]; % \node[anchor=east] at (k) {\((\texttt{k})\)}; % % \draw[fill] (note) circle [radius=.5mm]; % \node[anchor=east] at (note) {\((\texttt{note})\)}; % % \end{messagepassing} % \StopEventually{} % % \section{Implementation} % \begin{macrocode} \newcounter{processnb} \setcounter{processnb}{0} \newcounter{maxtime} \pgfdeclarelayer{background} \pgfsetlayers{background,main} \newfloat{float_messagepassing}{t b h p}{.mp} \floatname{float_messagepassing}{Execution} \newif\ifmp@vertical\mp@verticalfalse \DeclareOption{vertical}{ \mp@verticaltrue } \newif\ifmp@annotatevertical\mp@annotateverticalfalse \DeclareOption{annotatevertical}{ \mp@annotateverticaltrue } \ProcessOptions\relax \ifmp@vertical \newcommand{\mp@processnameanchor}{south} \newcommand{\mp@timeticksanchor}{east} \newcommand{\mp@messagelabelanchor}{south} \newcommand{\mp@stateintervalanchor}{north west} \newcommand{\mp@checkpointanchor}{east} \newcommand{\mp@verticalrotation}{270} \ifmp@annotatevertical \newcommand{\mp@annotaterotation}{270} \else \newcommand{\mp@annotaterotation}{0} \fi \else \newcommand{\mp@processnameanchor}{east} \newcommand{\mp@timeticksanchor}{north} \newcommand{\mp@messagelabelanchor}{west} \newcommand{\mp@stateintervalanchor}{south west} \newcommand{\mp@checkpointanchor}{north} \newcommand{\mp@verticalrotation}{0} \newcommand{\mp@annotaterotation}{0} \fi \newcommand{\mp@oobcolour}{red} \newcommand{\oobcolour}[1]{ \renewcommand\mp@oobcolour{#1} } \newcommand{\mp@colouredboxcolour}{red} \newcommand{\colouredboxcolour}[1]{ \renewcommand\mp@colouredboxcolour{#1} } \newif\iftimeline % \end{macrocode} % %\begin{environment}{messagepassing} % \begin{macrocode} \ExplSyntaxOn %% 1st argument: tikz arguments %% 2nd argument: Float caption (turns in floating) %% 3rd argument: Float placement (`p` by default) %% 4th argument: Float label \NewDocumentEnvironment{messagepassing} {o o o o} { \timelinefalse \setcounter{processnb}{0} \IfNoValueTF{#2} { }{ \IfNoValueTF{#3}{ \begin{float_messagepassing}[p] } { \begin{float_messagepassing}[#3] } \begin{center} } \IfNoValueTF{#1}{ \begin{tikzpicture}[rotate=\mp@verticalrotation] } { \begin{tikzpicture}[rotate=\mp@verticalrotation, #1] } }{ %% Draw timeline if boolean is true \iftimeline \begin{pgfonlayer}{background} \setcounter{maxtime}{\@maxtime} \addtocounter{maxtime}{-1} \coordinate (maxtime) at (\@maxtime, 0); \addtocounter{processnb}{1} \coordinate (timeline) at (0, -\value{processnb}); \draw (timeline) node [anchor=\mp@processnameanchor] {{\it time}}; \draw[->] (timeline) -- ($(timeline) + (maxtime)$); \foreach \i in {0,...,\value{maxtime}} { \draw ($(timeline) + (\i, 0) + (0, 0.1)$) -- ($(timeline) + (\i, 0) + (0, -0.1)$) node [anchor=\mp@timeticksanchor] {$\i$}; } \end{pgfonlayer} \else \fi \end{tikzpicture} \IfNoValueTF{#2} { \linebreak } { \end{center} \caption{#2} \IfNoValueTF{#4} { }{ \label{#4} } \end{float_messagepassing} } } \ExplSyntaxOff % \end{macrocode} % \end{environment} % % \begin{macrocode} %% #1: name %% #2: display name \NewDocumentCommand{\newprocess}{m o}{ \addtocounter{processnb}{1} \coordinate (#1) at (0, -\value{processnb}); \draw (#1) node[anchor=\mp@processnameanchor] {\IfValueTF{#2}{#2}{$#1$}}; } % \end{macrocode} % % \begin{macrocode} %% #1: name %% #2: display name %% #3: width \NewDocumentCommand{\newprocesswithlength}{m o m}{ \newprocess{#1}[#2] \processlength{#1}{#3} } % \end{macrocode} % % \begin{macrocode} %% #1: name %% #2: display name %% #3: state interval name \NewDocumentCommand{\newprocesswithstateinterval}{m o m}{ \newprocess{#1}[#2] \stateinterval{#1}{0}{#3} } % \end{macrocode} % % \begin{macrocode} %% #1: name %% #2: display name %% #3: width %% #4: crash name \NewDocumentCommand{\newprocesswithcrash}{m o m m}{ \newprocess{#1}[#2]{#3} \crash{#1}{#3}{#4} } % \end{macrocode} % % \begin{macrocode} %% #1: sender's name %% #2: send date %% #3: receiver's name %% #4: receive date \newcommand{\send}[4]{ \draw[->] (#1) +(#2, 0) -- ($ (#3) +(#4, 0) $); } % \end{macrocode} % % \begin{macrocode} %% #1: sender's name %% #2: send date %% #3: receiver's name %% #4: receive date %% #5: message name %% #6: message name display options \NewDocumentCommand{\sendwithname}{m m m m m o}{ \IfValueTF{#6}{ \draw[->] (#1) +(#2, 0) -- ($ (#3) +(#4, 0) $) node[anchor=\mp@messagelabelanchor, pos=0.3, #6] {#5}; }{ \draw[->] (#1) +(#2, 0) -- ($ (#3) +(#4, 0) $) node[anchor=\mp@messagelabelanchor, pos=0.3] {#5}; } } % \end{macrocode} % % \begin{macrocode} %% #1: process name %% #2: process width \newcommand{\processlength}[2]{ \draw (#1) -- +(#2, 0); } % \end{macrocode} % % \begin{macrocode} %% #1: sender's name %% #2: send date %% #3: receiver's name %% #4: receive date %% #5: state interval name \newcommand{\sendwithstateinterval}[5] { \send{#1}{#2}{#3}{#4} \stateinterval{#3}{#4}{#5} } % \end{macrocode} % % \begin{macrocode} %% #1: sender's name %% #2: send date %% #3: receiver's name %% #4: receive date %% #5: state interval name %% #6: message name %% #7: message name display options \NewDocumentCommand{\sendwithstateintervalandname}{m m m m m m o} { \sendwithname{#1}{#2}{#3}{#4}{#6}[#7] \stateinterval{#3}{#4}{#5} } % \end{macrocode} % % \begin{macrocode} %% #1: sender's name %% #2: send date %% #3: receiver's name %% #4: receive date %% #5: OoB message name %% #6: OoB message name display options \NewDocumentCommand{\sendoutofband}{m m m m m o}{ \IfValueTF{#6}{ \draw[->, color=\mp@oobcolour] (#1) +(#2, 0) -- ($ (#3) +(#4, 0) $) node[anchor=\mp@messagelabelanchor, pos=0.3, #6] {#5}; }{ \draw[->, color=\mp@oobcolour] (#1) +(#2, 0) -- ($ (#3) +(#4, 0) $) node[anchor=\mp@messagelabelanchor, pos=0.3] {#5}; } } % \end{macrocode} % % \begin{macrocode} %% #1: process's name %% #2: state interval date %% #3: state interval name \newcommand{\stateinterval}[3] { \stateintervalspecial{#1}{#2}{#3}{#3} } % \end{macrocode} % % \begin{macrocode} %% #1: process's name %% #2: state interval date %% #3: coordinate name %% #4: state interval label \newcommand{\stateintervalspecial}[4] { \coordinate (#3) at ($ (#1) +(#2, 0) $); \draw (#3) + (0, 0.1) -- +(0, -0.1) node[anchor=\mp@stateintervalanchor] {$#4$}; } % \end{macrocode} % % \begin{macrocode} %% #1: process's name %% #2: checkpoint date %% #3: checkpoint name \newcommand{\checkpoint}[3]{ \coordinate (#3) at ($ (#1) + (#2, 0) $); \fill (#3) + (-0.05, 0.1) rectangle +(0.05, -0.1); \draw (#3) + (0, -0.1) node[anchor=\mp@checkpointanchor] {$#3$}; } % \end{macrocode} % % \begin{macrocode} %% #1: process's name %% #2: checkpoint date %% #3: checkpoint coordinate name %% #4: checkpoint label \newcommand{\checkpointspecial}[4]{ \coordinate (#3) at ($ (#1) + (#2, 0) $); \fill (#3) + (-0.05, 0.1) rectangle +(0.05, -0.1); \draw (#3) + (0, -0.1) node[anchor=\mp@checkpointanchor] {#4}; } % \end{macrocode} % % \begin{macrocode} %% #1: process's name %% #2: crash date %% #3: crash name \newcommand{\crash}[3]{ \coordinate (#3) at ($ (#1) + (#2, 0) $); \draw (#3) + (-0.1, -0.1) -- +(0.1, 0.1); \draw (#3) + (0.1, -0.1) -- +(-0.1, 0.1); } % \end{macrocode} % % \begin{macrocode} %% #1: process's name %% #2: restart date %% #3: restart length \newcommand{\restart}[3]{ \draw (#1) + (#2, 0) -- ($ (#1) + (#2, 0) + (#3, 0) $); } % \end{macrocode} % % \begin{macrocode} %% #1: first process's name %% #2: second process's name %% #3: begining of the grey box %% #4: end of the grey box %% #5: caption \newcommand{\colouredbox}[5]{ \begin{pgfonlayer}{background} \fill[color=\mp@colouredboxcolour!20] ($(#1) + (#3, 0)$) rectangle ($(#2) + (#4, 0)$) node[midway, color = \mp@colouredboxcolour, rotate=\mp@annotaterotation]{#5}; \end{pgfonlayer} } % \end{macrocode} % % \begin{macrocode} %% #1: Timeline length \newcommand{\drawtimeline}[1]{ \timelinetrue \def\@maxtime{#1} } % \end{macrocode} % % \begin{macrocode} %% #1: process's name %% #2: annotation date %% #3: annotation \newcommand{\annotate}[3]{ \annotatexplicit{#1}{#2}{#3}{#3} } % \end{macrocode} % % \begin{macrocode} %% Same than annotate, but with the coordinate name provided explicitly %% #1: process's name %% #2: annotation date %% #3: annotation %% #4: coordinate name \newcommand{\annotatexplicit}[4]{ \coordinate (#4) at ($ (#1) +(#2, 0.1) $); \draw (#4) node[rotate=\mp@annotaterotation, anchor=south] {#3}; } % \end{macrocode}