% flag to use fancy fonts / graphics
\newif\ifjnf\jnftrue

\documentclass[11pt]{article}

\usepackage{tikz}
\usetikzlibrary{arrows}
\usepackage{cmtt}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{amsthm}
\usepackage{url}
\usepackage[margin=1in]{geometry}

\usepackage{csnotes}

\newcommand\SB[2][]{\ensuremath{\mathcal{#1}[\kern-1.5pt[\kern1pt{#2}\kern1pt]\kern-1.5pt]}}

\begin{document}

\header{29 November 2011}{Jean-Baptiste Jeannin}

\section{Readings}
The readings for today were:
\begin{itemize}
\item \emph{Eventually Consistent Transactions}, by Sebastian
  Burckhardt,
  Manuel F\"ahndrich, Daan Leijen and Mooly Sagiv, available at\\
  \url{http://research.microsoft.com/pubs/155638/msr-tr-2011-117.pdf}
\item \emph{Transactional Boosting: A Methodology for
    Highly-Concurrent
    Transactional Objects}, by Maurice Herlihy and Eric Kosniken, available at\\
  \url{http://www.cl.cam.ac.uk/~ejk39/papers/boosting-ppopp08.pdf}
\item \emph{Coarse-Grained Transactions}, by Eric Koskinen, Matthew Parkinson
and Maurice Herlihy, available at
\url{http://www.cl.cam.ac.uk/~ejk39/papers/cgt.pdf}\\
Most of the discussion was based on this last paper.
\end{itemize}

\section{Skew heaps}

\subsection{Definitions}

Let us start with an example: parallelizing insertions in skew heaps.
 
A skew heap (\url{http://en.wikipedia.org/wiki/Skew_heap}) is a heap
data structure implemented as a binary tree. It is defined recursively
as:
\begin{itemize}
\item A heap with only one element is a skew heap;
\item The result of skew merging two skew heaps is also a skew heap.
\end{itemize}

Let us just describe how to insert one element $e$ into a skew heap
$h$ with root $p$, whose subtrees are $l$ on the left and $r$ on the
right; the general merge of two heaps can be found on Wikipedia:
\begin{center}
\begin{tikzpicture}[grow=down,d/.style={circle,draw}]
\hspace{-2.5cm}
\node[d] {$e$};
\hspace{5cm}
\node[d] {$p$}
  child {
    node[d] {$l$}
    edge from parent [->]
  }
  child {
    node[d] {$r$}
    edge from parent [->]
  };
\end{tikzpicture}
\end{center}

\begin{itemize}
\item inserting $e$ into an empty heap just results in the heap with
  just that element;
\item if $e>p$, the resulting heap has root $p$, its left subtree is
  the result of recursively inserting $e$ in $r$, and its right
  subtree is $l$. Note how we swapped $r$ and $l$ in the process;
\begin{center}
\begin{tikzpicture}[grow=down,d/.style={circle,draw}]
\node[d] {$p$}
  child {
    node[d] {insert($e$,$r$)}
    edge from parent [->]
  }
  child {
    node[d] {$l$}
    edge from parent [->]
  };
\end{tikzpicture}
\end{center}
\item if $e<p$, the resulting heap has $e$ as a root, its left subtree
  is the result of inserting $p$ in $r$ and its right subtree is $l$.
\begin{center}
\begin{tikzpicture}[grow=down,d/.style={circle,draw}]
\node[d] {$e$}
  child {
    node[d] {insert($p$,$r$)}
    edge from parent [->]
  }
  child {
    node[d] {$l$}
    edge from parent [->]
  };
\end{tikzpicture}
\end{center}
\paragraph{Remark:} 
What we said in class does not seem to match the Wikipedia article.
For wikipedia, the resulting heap has root $e$, with the original heap
$h$ as its left subtree and an empty right subtree.
\begin{center}
\begin{tikzpicture}[grow=down,d/.style={circle,draw}]
\node[d] {$e$}
  child {
    node[d] {$p$}
    edge from parent [->]
    child {
      node[d] {$l$}
      edge from parent [->]
    }
    child {
      node[d] {$r$}
      edge from parent [->]
    }
  }
  child {
    edge from parent [->]
  }
;
\end{tikzpicture}
\end{center} 
\end{itemize}

Now suppose we have the following heap and two concurrent threads, $A$
adding $2$ to it, and $B$ adding $6$ to it. Several solutions are
possible.

\begin{center}
\begin{tikzpicture}[grow=down,d/.style={circle,draw}]
\node[d] {0}
  child {
    node[d] {1}
    edge from parent [->]
  }
  child {
    node[d] {3}
    edge from parent [->]
    child {
      node[d] {4}
      edge from parent [->]
    }
    child {
      node[d] {5}
      edge from parent [->]
    }
  };
\end{tikzpicture}
\end{center}

\subsection{Global lock}
The first solution is to use a global lock on the heap.  This is not
so nice because it is slow: you have to wait for one insertion to
complete before the next one can start.

\subsection{Local locks} The second solution is to use a fine grain
locking procedure: use one lock per node, and acquire and release the
locks as we traverse the tree.  Here is an example of an execution
using such a procedure:
\begin{center}
\begin{tabular}{ll}
Thread $A$ & Thread $B$\\
-- Acquire lock for node $0$\\
-- Swap children of $0$\\
\begin{tikzpicture}[grow=down,d/.style={circle,draw}]
\node[d] {0}
  child {
    node[d] {3}
    edge from parent [->]
    child {
      node[d] {4}
      edge from parent [->]
    }
    child {
      node[d] {5}
      edge from parent [->]
    }
  }
  child {
    node[d] {1}
    edge from parent [->]
  };
\end{tikzpicture}\\
-- Release lock for node $0$\\
-- Acquire lock for node $1$ & -- Acquire lock for node $0$\\
-- Insert $2$ into $1$       & -- Swap left and right children of $0$\\
  & \begin{tikzpicture}[grow=down,d/.style={circle,draw}]
\node[d] {0} 
  child {
    node[d] {1}
    edge from parent [->]
    child {
      node[d] {2}
      edge from parent [->]
    }
  }
  child {
    node[d] {3}
    edge from parent [->]
    child {
      node[d] {4}
      edge from parent [->]
    }
    child {
      node[d] {5}
      edge from parent [->]
    }
  };
\end{tikzpicture}\\
 & -- Insert 6 into 3\\
 & \begin{tikzpicture}[grow=down,d/.style={circle,draw}]
\node[d] {0} 
  child {
    node[d] {1}
    edge from parent [->]
    child {
      node[d] {2}
      edge from parent [->]
    }
  }
  child {
    node[d] {3}
    edge from parent [->]
    child {
      node[d] {5}
      edge from parent [->]
      child {
        node[d] {6}
        edge from parent [->]
      }
    }
    child {
      node[d] {4}
      edge from parent [->]
    }
  };
\end{tikzpicture}\\
\end{tabular}
\end{center}
This performs relatively well, but it is hard to write and get right.

\subsection{Transactions}
We could also use transactions, but in the previous examples, here is
what would happen:
\begin{center}
\begin{tabular}{ll}
Thread $A$ & Thread $B$\\
-- Read $0$ & -- Read $0$\\
-- Write $0.\{L,R\}$ & -- Write $0.\{L,R\}$\\
$\vdots$ & $\vdots$
\end{tabular}
\end{center}

We will get a conflict when committing, and one of the threads will
have to be rolled back. It hinders concurrency, even though it is
efficient for the programmer.

Here is one more example: imagine trying to insert a few single-digit
numbers and 6000 into a huge heap. The insert of a single-digit number
has a short log, and will always try to commit first. The insert of
6000, on the other hand, will always get rolled back. If trying to
parallelize it with several insertions of single-digit numbers, it
will only actually happen at the very end.

\section{Coarse-Grained Transaction}
We now focus on Maurice Herlihy and Eric Koskinen's work, and
especially their POPL'10 paper \emph{Coarse-Grained Transactions}.

The basic idea is to have a transaction mechanism that is convenient
to programmers but does not have the big conflicts that normal
transactions generate.

\begin{example}
\begin{verbatim}

global SkipList Set;
T1 : atomic {
  Set.add(5);
  Set.remove(3);
}
T2 : atomic {
  if(Set.contains(6)){
    Set.remove(7);
  }
}
\end{verbatim}
  In this example using a fine-grained synchronization technique would
  produce a conflict, because adding 5 and removing 7 will read or
  write the same memory locations. However at a coarse-grained level,
  these operations commute with each other as soon as their arguments
  are distinct.
\end{example}

We will consider two execution semantics:
\begin{itemize}
\item Pessimistic Execution Semantics (section 3.1 of the paper)
  prevent conflicts by checking if there will be a conflict before
  doing anything. They are called pessimistic because they act like
  there will always be a conflict.
\item Optimistic Execution Semantics (section 3.2 of the paper) detect
  conflicts afterwards: they copy the initial state, and roll back if
  there is a conflict when committing. They are called optimistic
  because they act hoping that there will not be a conflict.
\end{itemize}

\subsection{Syntax}

The language is given by:
\begin{eqnarray*}
c & ::= & c;c\ |\ e:=e\ |\ {\tt if}\ b\ {\tt then\ }c\ {\tt else\ }c\\
s & ::= & s;s\ |\ c\ |\ {\tt beg;}\ t;\ {\tt end}\\
t & ::= & t;t\ |\ c\ |\ o.m
\end{eqnarray*}
${\tt beg;}\ t;\ {\tt end}$ is the syntax for a transaction. $o.m$
represents a method call $m$ on a shared object $o$.  Note that the
syntax purposely makes nested transactions impossible.

The semantics is a labeled transition system, with transitions
$$T,\sigma_{\sf sh}\ \overset\alpha\longrightarrow_A\ T',\sigma'_{\sf sh}$$
where $T$ is a set of transactions $t$, $\sigma_{\sf sh}$ is a global
state, i.e., a finite map from object ids to objects.
$\alpha\in\bot\cup(\mathbb{N}\times(o.m\cup\{{\tt beg},{\tt end},{\tt
  cmt}\}))$ is a label. ${\tt beg}$ is short for begin, and {\tt cmt}
is short for commit. $A$ just means atomic.

Each transaction is a tuple $\langle\tau,p\rangle$, where $\tau$ is a
transaction identifier and $p$ is the program text for the
transaction.

The abridged atomic semantics is given by:
$$\frac{}{(\langle\tau,c;c'\rangle\cup T),\sigma_{\sf
    sh}\overset\bot\longrightarrow_A (\langle\tau,c'\rangle\cup
  T),\SB{c}{\sigma_{\sf sh}}} $$
$$
\frac {\alpha=(\tau,{\tt beg})\cdot\alpha'\cdot(\tau,{\tt
    end})\cdot(\tau,{\tt cmt})\ \ \ \ \ \tau\ {\sf fresh}\ \ \ \ \
  (\langle\tau,t\rangle\cup T),\sigma_{\sf
    sh}\overset{\alpha'}{\longrightarrow^*}(\langle\tau,{\tt
    skip}\rangle\cup T),\sigma_{\sf sh}' } {(\langle\bot,{\tt beg;}\
  t;\ {\tt end}\rangle\cup T),\sigma_{\sf sh}
  \overset\alpha\longrightarrow_A (\langle\bot,{\tt skip}\rangle\cup
  T) ,\sigma_{\sf sh}'}$$


\subsection{Pessimistic semantics (section 3.1)}

A transaction is now a tuple $\langle\tau,s,M,\sigma_\tau\rangle$,
where $M$ is a sequence of object methods, and $\sigma_\tau$ is a
local state.  All the arrows are indexed with a $P$, for pessimistic.

$$\frac{}{
  (\langle\tau,s\in\{:=,{\tt if},\ldots\};s',M,\sigma_\tau\rangle\cup
  T),\sigma_{\sf sh}\overset\bot\longrightarrow_P
  (\langle\tau,s',M,\SB s{\sigma_\tau}\rangle\cup T),\sigma_{\sf sh}
}$$
$$\frac{\tau\ {\sf fresh}}{
  (\langle\bot,{\tt beg;}s,M,\sigma_\tau\rangle\cup T),\sigma_{\sf sh}
  \overset{\tau,{\tt beg}}{\longrightarrow_P} (\langle \tau, s,
  [\,],\sigma_\tau\rangle\cup T),\sigma_{\sf sh} }
$$
$$\hspace{-1.8cm}\frac{\{o.m\}\triangleleft{{\sf meths}(T)}}{
  (\langle\tau,x:=o.m;s,M,\sigma_\tau\rangle\cup T),\sigma_{\sf sh}
  \overset{\tau,o.m}{\longrightarrow_P} (\langle\tau,s,M::(``x:=o.m;
  s",\sigma_\tau,``o.m"),\sigma_\tau[x\mapsto rv(\SB{o}{\sigma_{\sf
      sh}.m})]\rangle\cup T), \sigma_{\sf sh}[o \mapsto
  \SB{o}{\sigma_{\sf sh}.m}] }$$

The difficult part is $o.m$ being invoked has some global effect: each
invokation of $o$ returns a new object and a return value (accessed
through $rv$).  Under transactional semantics, there is a guarantee to
the programmer that the actual execution will be equivalent to some
serial execution. To get this we need to know that it was ok to call
$o.m$ at that point. This is the reason behind the introduction of the
mover concept. We write $\{o.m\}\triangleleft{\sf meths}(T)$ for
``$o.m$ is a left mover of $T$''.

\begin{definition}
$o.m\triangleleft p.n$ if and only if
$$\{\sigma''\ |\ \exists\sigma'.\sigma\overset{p.n}\longrightarrow\sigma'\land
\sigma'\overset{o.m}\longrightarrow\sigma''\}\subseteq \{\sigma''\ |\
\exists\sigma'.\sigma\overset{o.m}\longrightarrow\sigma'\land
\sigma'\overset{p.n}\longrightarrow\sigma''\}$$ i.e., if the set of
states obtained by running $p.n$ followed by $o.m$ is included in the
set of states obtained by running $o.m$ followed by $p.n$ (left
commutativity).
\end{definition}

One problem of this semantics is that we can get deadlocks with two
transactions sending messages that are not inverse of each other. A
solution is running an $o.m$ that has an inverse that can be rolled
back, and then make some progress from there.

\subsection{Optimistic semantics (section 3.2)}

A transaction is now a tuple
$\langle\tau,s,\sigma_\tau,\overleftarrow{\sigma_\tau},\ell_\tau\rangle$,
where $\ell_\tau$ is a log, a list of messages that have been sent
already. All the arrows are indexed with an $O$, for optimistic.

$$\frac{\tau\ {\sf fresh}}{
  (\langle\bot,{\tt
    beg};s,\sigma_\tau,\overleftarrow{\sigma_\tau},[\,]\rangle\cup
  T),\sigma_{\sf sh},\ell_{\sf sh} \overset{(\tau,{\tt
      beg})}{\longrightarrow_O} (\langle\tau,s,{\sf
    snap}(\sigma_\tau,\sigma_{\sf sh}),\sigma_\tau[{\sf
    stmt}\mapsto``{\tt beg};s"],[\,]\rangle\cup T),\sigma_{\sf
    sh},\ell_{\sf sh} }$$ Message call:
$$\hspace{-2cm}\frac{}{
  (\langle\tau,x:=o.m;s,\sigma_\tau,\overleftarrow{\sigma_\tau},\ell_\tau\rangle\cup
  T),\sigma_{\sf sh},\ell_{\sf
    sh}\overset{(\tau,o.m)}{\longrightarrow_O}
  (\langle\tau,s,\sigma_\tau[o\mapsto(\SB{o}{\sigma_{\sf
      sh}}).m,x\mapsto rv((\SB{o}{\sigma_{\sf
      sh}}).m)],\overleftarrow{\sigma_\tau},\ell_\tau::(``o.m")\rangle\cup
  T) ,\sigma_{\sf sh},\ell_{\sf sh} }$$
$$\frac{\forall (\tau^{\sf cmt},\ell_{\tau'})\in\ell_{\sf
    sh}.\tau^{\sf cmt}>\tau\Rightarrow
  \ell_\tau\triangleright\ell_{\tau'}}{ (\langle\tau,{\tt
    end};s,\sigma_\tau,\overleftarrow{\sigma_\tau},\ell_\tau\rangle\cup
  T),\sigma_{\sf sh},\ell_{\sf sh} \overset{(\tau,{\sf
      cmt})}{\longrightarrow_O} (\langle\tau,s,{\sf
    zap}(\sigma_\tau),{\sf
    zap}(\overleftarrow{\sigma_\tau}),[\,]\rangle\cup T),{\sf
    merge(\sigma_{\sf sh},\ell_\tau),\ell_{\sf sh}::({\sf
      fresh}(\tau^{\sf cmt}),\ell_\tau)}}
$$
where the ${\sf merge}$ operation goes through the log where it finds
operations that it applies in order to the global state. In the last
rule, the condition $\forall (\tau^{\sf cmt},\ell_{\tau'})\in\ell_{\sf
  sh}.\tau^{\sf cmt}>\tau\Rightarrow
\ell_\tau\triangleright\ell_{\tau'}$ makes sure the ${\tt end}$
operation is sensible.

\subsection{Conclusion}
Section 5 of the paper develops the theory of trace semantics of those
programs, develops serial execution and shows both semantics are
equivalent to some serialized execution.

\end{document}

