\documentclass{article}
\usepackage{epsfig}
\usepackage{latexsym}
%\textheight 4.8in
%\topmargin -0.25in

\topmargin=-.6in
\textheight=9.0in
\textwidth=5.5in
\oddsidemargin=.5in

\title{Matrix-Vector Product: A Small Example\\
 of Parallel Processing Using CORBA}

\author{David R. Musser}

\newcommand{\code}[1]{\texttt{#1}}

\begin{document} \maketitle

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Introduction}

In this note I describe a distributed version of a matrix-vector
product computation, devised as simple demonstration of a CORBA
client-server system in which the client performs an algorithm that
distributes parts of a large computation to two or more servers.  The
servers are functionally identical, but they can be compiled with
CORBA implementations on different operating systems and run on
different machines from the client and from each other.  With a bit
more work it should be possible also to make them work with different
CORBA implementations and/or with different parts implemented in
different languages.  In this note the omniORB CORBA implementation is
used; the example has also been compiled and tested with the MICO ORB,
but not with both ORBs involved in the same computations.  The
implementation language in all cases is C++, but in some experiments
two different C++ compilers have been used; e.g., Microsoft Visual C++
6.0 on Windows 95 and GNU C++ 2.8.1 on SunOS.

These programs are only intended as simple exercises aimed at
exploring ideas about combining generic programming techniques with
distributed computing.  For a serious effort at providing distributed
components for linear algebra, one should start with close examination
of efforts such as the PETSc
Library,\footnote{http://www-unix.mcs.anl.gov/petsc} which does
distributed computation but doesn't employ generic programming, or the
Matrix Template Library
(MTL),\footnote{http://lsc.nd.edu/research/mtl} which makes extensive
use of generic programming but doesn't (yet) do distributed
computation.

Besides having the flexibility to have servers and clients
inter-operating on different machines or operating systems, this
example provides further opportunities for generality.  Varying the
type of data elements is one possibility.  Another, with which the
term ``generic programming,'' is perhaps most often identified, is
varying the type of sequence data structure used, without having to
change the algorithm(s) involved; that is, the algorithms are generic
with respect to different data structures.  As currently written, the
program uses the vector representation from the C++ standard library,
but the product algorithm would work equally well with a standard
library list representation. (Actually this is not quite true with the
algorithm is described here, but with small modifications we could
obtain an algorithm that would work with both a list and a vector
representation.)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Client-server structure}

The distributed matrix-product system consists of:
\begin{itemize}

 \item A server that provides a matrix object equipped with a
\verb|block_product| function, which is a function that is able to use
a designated range of rows of a matrix \verb|m| and a column vector
\verb|c| and produce the corresponding range of elements of the column
vector \verb|r| that is the matrix-vector product of \verb|m| and
\verb|c|.  This server registers the object reference of the
matrix with the CORBA Naming Service, using a name specified by
the user on the command line.  One
should start two copies of the server, each with a different name;
e.g.,
\begin{verbatim}
  server matrix1
  server matrix2
\end{verbatim}
  
 \item A client that connects to two matrix servers holding the same
matrix and uses their matrix \verb|block_product| functions.  The call
of the first server's \verb|block_product| function computes the top
half of a matrix-vector product and the call on the second server does
the second half.  These calls are done in parallel, by making the
first call via the Dynamic Invocation Interface, as described later.
One tells the clients the names of the servers with two parameters
on the command line, and the client uses the Naming Service to
look them up and obtain the corresponding object references.

\end{itemize}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{IDL definitions}

For this simple example, the entire IDL specification consists of just
these two parts:\footnote{Throughout we present code in a variant of
Knuth's literate programming style \cite{Knuth:literate}, in which
code is presented in ``parts'' numbered according to the page number
on which they appear (with parts on the same page distinguished by
appending a letter to the number).  This form of presentation is
supported by Briggs' Nuweb tool \cite{Briggs} (slightly modified) with
which we also generate all code files directly from the document's
source file.  Parts may refer to other parts that have either already
been defined or are defined later in the document; one can choose
whatever order of presentation seems best for expository purposes,
while the order in which code appears in the compilation files is a
matter of how the parts are ordered when included in file parts such
as \code{matrix.idl}.  See also Appendix~\ref{nuweb:hints}.  (Even
experienced Nuweb users should see the note there about problems with
including line directives in IDL files.)}

\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{part1}
\verb@"matrix.idl"@ {\footnotesize 2a }$\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\hbox{$\langle$Row and Column types {\footnotesize 2b}$\rangle$}\verb@@\\
\mbox{}\verb@@\hbox{$\langle$Matrix interface {\footnotesize 3a}$\rangle$}\verb@@\end{list}
\vspace{-2ex}
\end{minipage}\\[4ex]
\end{flushleft}
The interfaces of the CORBA objects used in this example are expressed
in CORBA's Interface Definition Language (IDL).  First we define
\code{Row} and \code{Column} objects in terms of IDL's built-in
\code{Sequence} type:

\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{part2}
$\langle$Row and Column types {\footnotesize 2b}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@typedef sequence<double> Row;@\\
\mbox{}\verb@typedef sequence<double> Column;@\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item Used in part 2a.
\end{list}
\end{minipage}\\[4ex]
\end{flushleft}
The IDL \code{sequence} type is similar in its functionality to the
C++ standard library \code{vector} type but is more limited.  In a
later section we consider the possibility of defining an IDL interface
for (special cases of) the \code{vector} type and redoing this matrix
example in terms of it.

We use \code{double} is used as the type of row, column, and matrix
elements.  CORBA has no mechanism for compile-time type
parameterization analogous to C++ templates or Ada generics, but we
could make this example more generic by using its dynamic type system,
using type \code{Any} in place of \code{double}.  This is left for a
future extension.

We next define the \code{Matrix} type, essentially as a
\code{sequence} of \code{Row}'s.  Actually, we define \code{Matrix}
not just with a \code{typedef} but with an \code{interface}
definition, which allows us to provide its objects with operations we
intend to provide:

\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{part3}
$\langle$Matrix interface {\footnotesize 3a}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@interface Matrix {@\\
\mbox{}\verb@   typedef sequence<Row> rep;@\\
\mbox{}\verb@   Column block_product(in unsigned long first, @\\
\mbox{}\verb@                        in unsigned long last,@\\
\mbox{}\verb@                        in Column c);@\\
\mbox{}\verb@};@\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item Used in part 2a.
\end{list}
\end{minipage}\\[4ex]
\end{flushleft}
In this case we specify only one operation, \code{block\_product},
which takes two parameters of type \code{unsigned long}
and one of type \code{Column}; it returns an object of type
\code{Column}.

The \code{rep} type is for use in the implementation, but in a larger
example there might be operations that have this as a parameter
type or return type.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Matrix server implementation} 

In the server program we provide an implementation of the
\code{block\_product} function, set up a matrix, and initialize to
perform the \code{block\_product} operation on the matrix at the
request of clients.  The overall structure of the server is as
follows.

\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{part4}
\verb@"server.cpp"@ {\footnotesize 3b }$\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\hbox{$\langle$Include standard and CORBA library headers {\footnotesize 3c}$\rangle$}\verb@@\\
\mbox{}\verb@@\hbox{$\langle$Include matrix object interface generated by IDL compiler {\footnotesize 3d}$\rangle$}\verb@@\\
\mbox{}\verb@@\hbox{$\langle$Include auxiliary file to help with using the Naming Service {\footnotesize 9a}$\rangle$}\verb@@\\
\mbox{}\verb@@\hbox{$\langle$Define matrix object implementation {\footnotesize 4e}$\rangle$}\verb@@\\
\mbox{}\verb@@\\
\mbox{}\verb@int main(int argc, char *argv[])@\\
\mbox{}\verb@{@\\
\mbox{}\verb@  assert(argc == 2);@\\
\mbox{}\verb@  const int N = 20;@\\
\mbox{}\verb@  @\hbox{$\langle$Set up matrix m0 {\footnotesize 4a}$\rangle$}\verb@@\\
\mbox{}\verb@  @\hbox{$\langle$Initialize ORB connection {\footnotesize 4b}$\rangle$}\verb@@\\
\mbox{}\verb@  @\hbox{$\langle$Use m0 to initialize a matrix object, matrix1, and serve it up {\footnotesize 4c}$\rangle$}\verb@@\\
\mbox{}\verb@  @\hbox{$\langle$Register matrix1 with the Naming Service {\footnotesize 4d}$\rangle$}\verb@@\\
\mbox{}\verb@  boa->impl_is_ready();@\\
\mbox{}\verb@  return 0;@\\
\mbox{}\verb@}@\end{list}
\vspace{-2ex}
\end{minipage}\\[4ex]
\end{flushleft}
For this simple example only a few header files are needed.

\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{part5}
$\langle$Include standard and CORBA library headers {\footnotesize 3c}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@#include <vector>@\\
\mbox{}\verb@#include <iostream.h>@\\
\mbox{}\verb@using namespace std;@\\
\mbox{}\verb@#pragma warning (disable : 4786)@\\
\mbox{}\verb@#include <omniORB2/CORBA.h>@\\
\mbox{}\verb@#include "omnithread.h"@\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item Used in parts 3b, 5d.
\end{list}
\end{minipage}\\[4ex]
\end{flushleft}
Note that \code{<iostream.h>} is included, not the now-standard
\code{<iostream>}, because the latter leads to compilation errors
under VC++.  This might need to be changed when using another
compiler.

\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{part6}
$\langle$Include matrix object interface generated by IDL compiler {\footnotesize 3d}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@#include "matrix.h"@\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item Used in parts 3b, 5d.
\end{list}
\end{minipage}\\[4ex]
\end{flushleft}
To keep the example simple, we construct the matrix that
\code{block\_product} operates on in the server.

\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{part7}
$\langle$Set up matrix m0 {\footnotesize 4a}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@vector<double> r;@\\
\mbox{}\verb@vecrep m0;@\\
\mbox{}\verb@@\\
\mbox{}\verb@for (int i = 0; i < N; ++i) {@\\
\mbox{}\verb@  r.erase(r.begin(), r.end());@\\
\mbox{}\verb@  for (int j = 0; j < N; ++j)@\\
\mbox{}\verb@    r.push_back(i*N + j);@\\
\mbox{}\verb@  m0.push_back(r);@\\
\mbox{}\verb@}@\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item Used in part 3b.
\end{list}
\end{minipage}\\[4ex]
\end{flushleft}
The server initialization is standard.

\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{part8}
$\langle$Initialize ORB connection {\footnotesize 4b}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@cout << "Initializing..." << endl;@\\
\mbox{}\verb@CORBA::ORB_var orb = CORBA::ORB_init(argc, argv, "omniORB2");@\\
\mbox{}\verb@CORBA::BOA_var boa = orb->BOA_init(argc, argv, "omniORB2_BOA");@\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item Used in parts 3b, 5d.
\end{list}
\end{minipage}\\[4ex]
\end{flushleft}
The type used in the following initialization is
\code{Matrix\_impl}, which is implemented by a class derived,
as required by the omniORB object interface
conventions, from the class \code{sk\_Matrix} generated
by the omniORB IDL compiler.

\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{part9}
$\langle$Use m0 to initialize a matrix object, matrix1, and serve it up {\footnotesize 4c}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@Matrix_impl matrix1(m0);@\\
\mbox{}\verb@matrix1._obj_is_ready(boa);@\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item Used in part 3b.
\end{list}
\end{minipage}\\[4ex]
\end{flushleft}
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{part10}
$\langle$Register matrix1 with the Naming Service {\footnotesize 4d}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@Matrix_var myobjRef = matrix1._this();@\\
\mbox{}\verb@if (!bindObjectToName(orb, myobjRef, "test", argv[1])) {@\\
\mbox{}\verb@  return 1;@\\
\mbox{}\verb@}@\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item Used in part 3b.
\end{list}
\end{minipage}\\[4ex]
\end{flushleft}
\begin{flushleft} \small \label{part11}
$\langle$Define matrix object implementation {\footnotesize 4e}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@typedef vector<vector<double> > vecrep;@\\
\mbox{}\verb@@\\
\mbox{}\verb@@\hbox{$\langle$Define inner product function {\footnotesize 5c}$\rangle$}\verb@@\\
\mbox{}\verb@@\\
\mbox{}\verb@class Matrix_impl : virtual public _sk_Matrix {@\\
\mbox{}\verb@    rep mr;@\\
\mbox{}\verb@    int _calls;@\\
\mbox{}\verb@public:@\\
\mbox{}\verb@    @\hbox{$\langle$Constructor, for conversion from vector representation {\footnotesize 5a}$\rangle$}\verb@@\\
\mbox{}\verb@    @\hbox{$\langle$Block product member function {\footnotesize 5b}$\rangle$}\verb@@\\
\mbox{}\verb@};@\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item Used in part 3b.
\end{list}
\end{flushleft}
The constructor copies from a matrix given in vector form to
a representation in terms of the CORBA sequence type.

\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{part12}
$\langle$Constructor, for conversion from vector representation {\footnotesize 5a}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@Matrix_impl (const vecrep& m0)@\\
\mbox{}\verb@{@\\
\mbox{}\verb@  _calls = 0;@\\
\mbox{}\verb@  mr.length(m0.size());@\\
\mbox{}\verb@  for (int i = 0; i < m0.size(); ++i) {@\\
\mbox{}\verb@    mr[i].length(m0[i].size());@\\
\mbox{}\verb@    for (int j = 0; j < m0[i].size(); ++j)@\\
\mbox{}\verb@      mr[i][j] = m0[i][j];@\\
\mbox{}\verb@  }@\\
\mbox{}\verb@}@\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item Used in part 4e.
\end{list}
\end{minipage}\\[4ex]
\end{flushleft}
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{part13}
$\langle$Block product member function {\footnotesize 5b}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@Column* block_product(CORBA::ULong first, @\\
\mbox{}\verb@                      CORBA::ULong last, const Column& c )@\\
\mbox{}\verb@{@\\
\mbox{}\verb@  cout << "block_product(" << first << ", " << last << ", c) start" @\\
\mbox{}\verb@       << endl;@\\
\mbox{}\verb@  Column* z = new Column;@\\
\mbox{}\verb@  z->length(last - first);@\\
\mbox{}\verb@  int k = 0;@\\
\mbox{}\verb@  for (int i = first; i != last; ++i, ++k) @\\
\mbox{}\verb@    (*z)[k] = inner_product(mr[i], c);@\\
\mbox{}\verb@  cout << "block_product(" << first << ", " << last << ", c) end" @\\
\mbox{}\verb@       << endl;@\\
\mbox{}\verb@  return z;@\\
\mbox{}\verb@}@\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item Used in part 4e.
\end{list}
\end{minipage}\\[4ex]
\end{flushleft}
Finally, the inner product function used in computing the block product
is written in terms of the Row and Column types.

\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{part14}
$\langle$Define inner product function {\footnotesize 5c}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@double inner_product(const Row& r, const Column& c) {@\\
\mbox{}\verb@  double result = 0;@\\
\mbox{}\verb@  for (int i = 0; i < r.length(); ++i)@\\
\mbox{}\verb@    result += r[i] * c[i];@\\
\mbox{}\verb@  return result;@\\
\mbox{}\verb@}@\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item Used in part 4e.
\end{list}
\end{minipage}\\[4ex]
\end{flushleft}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Matrix client}

This is a client that connects to two matrix servers
holding the same matrix and uses their matrix \code{block\_product}
functions.  The call of the first server's \code{block\_product} 
function computes the top half of a matrix-vector product
and the call on the second server does the second
half.  These calls are done in parallel, making use of a 
feature of the Dynamic Invocation Interface.

\begin{flushleft} \small \label{part15}
\verb@"client.cpp"@ {\footnotesize 5d }$\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\hbox{$\langle$Include standard and CORBA library headers {\footnotesize 3c}$\rangle$}\verb@@\\
\mbox{}\verb@@\hbox{$\langle$Include matrix object interface generated by IDL compiler {\footnotesize 3d}$\rangle$}\verb@@\\
\mbox{}\verb@@\hbox{$\langle$Include auxiliary file to help with using the Naming Service {\footnotesize 9a}$\rangle$}\verb@@\\
\mbox{}\verb@@\\
\mbox{}\verb@int main( int argc, char *argv[] )@\\
\mbox{}\verb@{@\\
\mbox{}\verb@  @\hbox{$\langle$Initialize ORB connection {\footnotesize 4b}$\rangle$}\verb@@\\
\mbox{}\verb@  vector<Matrix_var> client;@\\
\mbox{}\verb@  @\hbox{$\langle$Initialize client[0] and client[1] using Naming Service {\footnotesize 6a}$\rangle$}\verb@@\\
\mbox{}\verb@  const int N = 20;@\\
\mbox{}\verb@  @\hbox{$\langle$Create a column of all 3's {\footnotesize 6b}$\rangle$}\verb@@\\
\mbox{}\verb@  cout << "Computing the matrix-vector product..." << endl;@\\
\mbox{}\verb@  vector<Column*> result(2);@\\
\mbox{}\verb@  @\hbox{$\langle$Compute top and bottom halves of matrix product in parallel {\footnotesize 7a}$\rangle$}\verb@@\\
\mbox{}\verb@  @\hbox{$\langle$Output first half of result from result[0], second half from result[1] {\footnotesize 7g}$\rangle$}\verb@@\\
\mbox{}\verb@  cout << endl;@\\
\mbox{}\verb@  return 0;@\\
\mbox{}\verb@}@\end{list}
\vspace{-2ex}
\end{flushleft}
\begin{flushleft} \small \label{part16}
$\langle$Initialize client[0] and client[1] using Naming Service {\footnotesize 6a}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@int j;@\\
\mbox{}\verb@for (j = 1; j <= 2; ++j) {@\\
\mbox{}\verb@  cout << "j = " << j << endl;@\\
\mbox{}\verb@  try {@\\
\mbox{}\verb@    CORBA::Object_var obj = getObjectReference(orb, "test", argv[j]);@\\
\mbox{}\verb@    client.push_back(Matrix::_narrow(obj));@\\
\mbox{}\verb@    if (CORBA::is_nil(client[j-1])) {@\\
\mbox{}\verb@      cerr << "Cannot invoke on a nil object reference.\n" << endl;@\\
\mbox{}\verb@      return 1;@\\
\mbox{}\verb@    }@\\
\mbox{}\verb@    assert(!CORBA::is_nil(client[j - 1]));@\\
\mbox{}\verb@  }@\\
\mbox{}\verb@  catch(CORBA::COMM_FAILURE& ex) {@\\
\mbox{}\verb@    cerr << "Caught system exception COMM_FAILURE, unable to contact the "@\\
\mbox{}\verb@         << "object." << endl;@\\
\mbox{}\verb@    return 1;@\\
\mbox{}\verb@  }@\\
\mbox{}\verb@  catch(omniORB::fatalException& ex) {@\\
\mbox{}\verb@  cerr << "Caught omniORB2 fatalException. This indicates a bug is caught "@\\
\mbox{}\verb@       << "within omniORB2.\nPlease send a bug report.\n"@\\
\mbox{}\verb@       << "The exception was thrown in file: " << ex.file() << "\n"@\\
\mbox{}\verb@       << "                            line: " << ex.line() << "\n"@\\
\mbox{}\verb@       << "The error message is: " << ex.errmsg() << endl;@\\
\mbox{}\verb@    return 1;@\\
\mbox{}\verb@  }@\\
\mbox{}\verb@  catch(...) {@\\
\mbox{}\verb@    cerr << "Caught a system exception." << endl;@\\
\mbox{}\verb@  }@\\
\mbox{}\verb@}@\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item Used in part 5d.
\end{list}
\end{flushleft}
We create (arbitrarily) a \code{Column} to send to the servers
in the \code{block\_product} calls.

\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{part17}
$\langle$Create a column of all 3's {\footnotesize 6b}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@Column c;@\\
\mbox{}\verb@c.length(N);@\\
\mbox{}\verb@for (int i = 0; i < N; ++i) @\\
\mbox{}\verb@  c[i] = 3;@\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item Used in part 5d.
\end{list}
\end{minipage}\\[4ex]
\end{flushleft}
For the \code{block\_product} calls, we want to do the equivalent of
\begin{verbatim}
  result[0] = client[0]->block_product(0, N/2, c);
  result[1] = client[1]->block_product(N/2, N, c);
\end{verbatim}
except have them execute in parallel.  To achieve this we do the first
\code{block\_product} using the DII and send the request with
\code{send\_deferred} instead of (the normal) invoke call.  Thus, the
first call does not block and we can proceed with the second
\code{block\_product} (calling it in the usual way).

\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{part18}
$\langle$Compute top and bottom halves of matrix product in parallel {\footnotesize 7a}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\hbox{$\langle$Set up first half with DII request {\footnotesize 7b}$\rangle$}\verb@@\\
\mbox{}\verb@@\hbox{$\langle$Asynchronously do block\_product on second server {\footnotesize 7c}$\rangle$}\verb@@\\
\mbox{}\verb@@\hbox{$\langle$Wait for the first block\_product call to finish {\footnotesize 7d}$\rangle$}\verb@@\\
\mbox{}\verb@@\hbox{$\langle$Check for exceptions {\footnotesize 7e}$\rangle$}\verb@@\\
\mbox{}\verb@@\hbox{$\langle$Get the return value from the first half {\footnotesize 7f}$\rangle$}\verb@@\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item Used in part 5d.
\end{list}
\end{minipage}\\[4ex]
\end{flushleft}
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{part19}
$\langle$Set up first half with DII request {\footnotesize 7b}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@CORBA::Request_var _req = client[0]->_request( "block_product" );@\\
\mbox{}\verb@_req->add_in_arg( "first" ) <<= (CORBA::ULong)0;@\\
\mbox{}\verb@_req->add_in_arg( "last" ) <<= (CORBA::ULong)(N/2);@\\
\mbox{}\verb@_req->add_in_arg( "c" ) <<= c;@\\
\mbox{}\verb@_req->set_return_type(_tc_Column);@\\
\mbox{}\verb@_req->send_deferred();@\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item Used in part 7a.
\end{list}
\end{minipage}\\[4ex]
\end{flushleft}
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{part20}
$\langle$Asynchronously do block\_product on second server {\footnotesize 7c}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@result[1] = client[1]->block_product(N/2, N, c);@\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item Used in part 7a.
\end{list}
\end{minipage}\\[4ex]
\end{flushleft}
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{part21}
$\langle$Wait for the first block\_product call to finish {\footnotesize 7d}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@_req->get_response();@\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item Used in part 7a.
\end{list}
\end{minipage}\\[4ex]
\end{flushleft}
\begin{flushleft} \small \label{part22}
$\langle$Check for exceptions {\footnotesize 7e}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@if(_req->env()->exception()) {@\\
\mbox{}\verb@  CORBA::Exception *_ex = _req->env()->exception();@\\
\mbox{}\verb@  /* Following is from MICO version, needs to be ported to omniORB@\\
\mbox{}\verb@  CORBA::UnknownUserException *_uuex = @\\
\mbox{}\verb@     CORBA::UnknownUserException::_downcast( _ex );@\\
\mbox{}\verb@  if(_uuex) {@\\
\mbox{}\verb@    mico_throw( CORBA::UNKNOWN() );@\\
\mbox{}\verb@  } else {@\\
\mbox{}\verb@    mico_throw( *_ex );@\\
\mbox{}\verb@  }@\\
\mbox{}\verb@  */@\\
\mbox{}\verb@}@\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item Used in part 7a.
\end{list}
\end{flushleft}
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{part23}
$\langle$Get the return value from the first half {\footnotesize 7f}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@_req->return_value() >>= result[0];@\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item Used in part 7a.
\end{list}
\end{minipage}\\[4ex]
\end{flushleft}
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{part24}
$\langle$Output first half of result from result[0], second half from result[1] {\footnotesize 7g}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@cout << "The result: " << endl;@\\
\mbox{}\verb@for (j = 0; j < 2; ++j) {@\\
\mbox{}\verb@  for (int k = 0; k < result[j]->length(); ++k)@\\
\mbox{}\verb@    cout << (*result[j])[k] << " ";@\\
\mbox{}\verb@}@\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item Used in part 5d.
\end{list}
\end{minipage}\\[4ex]
\end{flushleft}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Running the servers and client}

When the client and two instances of the server are run as described
in the second section, the output by the client is as follows:

\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{part25}
$\langle$Client output {\footnotesize 8a}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@D:\dsc\omniorb\examples\matrix2>client matrix1 matrix2@\\
\mbox{}\verb@Initializing...@\\
\mbox{}\verb@j = 1@\\
\mbox{}\verb@j = 2@\\
\mbox{}\verb@Computing the matrix-vector product...@\\
\mbox{}\verb@The result:@\\
\mbox{}\verb@570 1770 2970 4170 5370 6570 7770 8970 10170 11370 12570 13770 14970 @\\
\mbox{}\verb@16170 17370 18570 19770 20970 22170 23370@\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item Not used.
\end{list}
\end{minipage}\\[4ex]
\end{flushleft}
(The last line was manually broken to fit within the margins.)

The output by the servers is

\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{part26}
$\langle$Server 1 output {\footnotesize 8b}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@D:\dsc\omniorb\examples\matrix2>server matrix1@\\
\mbox{}\verb@Initializing...@\\
\mbox{}\verb@block_product(0, 10, c) start@\\
\mbox{}\verb@block_product(0, 10, c) end@\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item Not used.
\end{list}
\end{minipage}\\[4ex]
\end{flushleft}
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{part27}
$\langle$Server 2 output {\footnotesize 8c}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@D:\dsc\omniorb\examples\matrix2>server matrix2@\\
\mbox{}\verb@Initializing...@\\
\mbox{}\verb@block_product(10, 20, c) start@\\
\mbox{}\verb@block_product(10, 20, c) end@\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item Not used.
\end{list}
\end{minipage}\\[4ex]
\end{flushleft}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{thebibliography}{MMM83}

\bibitem[Briggs]{Briggs} P.~Briggs, \emph{Nuweb, a simple literate
programming tool}, Version 0.87, 1989.

\bibitem[Knuth84]{Knuth:literate} D.E.~Knuth, Literate programming.
{\em Computer Journal} 27 (1984), 97--111.

\end{thebibliography}

\newpage
\appendix

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Name binding auxiliary functions}

The functions \code{bindObjectToName} and \code{getObjectReference},
used in the server and client respectively, are used to access the
Naming Service.  These functions, which are provided in the auxiliary
file \code{namebind.cpp}, are based on the Echo example that comes
with OmniORB.

\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{part28}
$\langle$Include auxiliary file to help with using the Naming Service {\footnotesize 9a}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@#include "namebind.cpp"@\\
\mbox{}\verb@@\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item Used in parts 3b, 5d.
\end{list}
\end{minipage}\\[4ex]
\end{flushleft}
\begin{flushleft} \small \label{part29}
\verb@"namebind.cpp"@ {\footnotesize 9b }$\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@static CORBA::Boolean@\\
\mbox{}\verb@  bindObjectToName(CORBA::ORB_ptr orb, CORBA::Object_ptr obj, @\\
\mbox{}\verb@                   const char* context, const char* name)@\\
\mbox{}\verb@{@\\
\mbox{}\verb@  CosNaming::NamingContext_var rootContext;@\\
\mbox{}\verb@  @\\
\mbox{}\verb@  try {@\\
\mbox{}\verb@    // Obtain a reference to the root context of the Name service:@\\
\mbox{}\verb@    CORBA::Object_var initServ;@\\
\mbox{}\verb@    initServ = orb->resolve_initial_references("NameService");@\\
\mbox{}\verb@@\\
\mbox{}\verb@    // Narrow the object returned by resolve_initial_references()@\\
\mbox{}\verb@    // to a CosNaming::NamingContext object:@\\
\mbox{}\verb@    rootContext = CosNaming::NamingContext::_narrow(initServ);@\\
\mbox{}\verb@    if (CORBA::is_nil(rootContext)) @\\
\mbox{}\verb@      {@\\
\mbox{}\verb@        cerr << "Failed to narrow naming context." << endl;@\\
\mbox{}\verb@        return 0;@\\
\mbox{}\verb@      }@\\
\mbox{}\verb@  }@\\
\mbox{}\verb@  catch(CORBA::ORB::InvalidName& ex) {@\\
\mbox{}\verb@    cerr << "Service required is invalid [does not exist]." << endl;@\\
\mbox{}\verb@    return 0;@\\
\mbox{}\verb@  }@\\
\mbox{}\verb@@\\
\mbox{}\verb@  try {@\\
\mbox{}\verb@    CosNaming::Name contextName;@\\
\mbox{}\verb@    contextName.length(1);@\\
\mbox{}\verb@    contextName[0].id   = (const char*) context;@\\
\mbox{}\verb@    contextName[0].kind = (const char*) "my_context"; @\\
\mbox{}\verb@    // Note on kind: The kind field is used to indicate the type@\\
\mbox{}\verb@    // of the object. This is to avoid conventions such as that used@\\
\mbox{}\verb@    // by files (name.type -- e.g. test.ps = postscript etc.)@\\
\mbox{}\verb@@\\
\mbox{}\verb@    CosNaming::NamingContext_var testContext;@\\
\mbox{}\verb@    try {@\\
\mbox{}\verb@      // Bind the context to root, and assign testContext to it:@\\
\mbox{}\verb@      testContext = rootContext->bind_new_context(contextName);@\\
\mbox{}\verb@    }@\\
\mbox{}\verb@    catch(CosNaming::NamingContext::AlreadyBound& ex) {@\\
\mbox{}\verb@      // If the context already exists, this exception will be raised.@\\
\mbox{}\verb@      // In this case, just resolve the name and assign testContext@\\
\mbox{}\verb@      // to the object returned:@\\
\mbox{}\verb@      CORBA::Object_var tmpobj;@\\
\mbox{}\verb@      tmpobj = rootContext->resolve(contextName);@\\
\mbox{}\verb@      testContext = CosNaming::NamingContext::_narrow(tmpobj);@\\
\mbox{}\verb@      if (CORBA::is_nil(testContext)) {@\\
\mbox{}\verb@        cerr << "Failed to narrow naming context." << endl;@\\
\mbox{}\verb@        return 0;@\\
\mbox{}\verb@      }@\\
\mbox{}\verb@    } @\\
\mbox{}\verb@@\\
\mbox{}\verb@    // Bind the object (obj) to testContext, naming it FrontOffice;@\\
\mbox{}\verb@    CosNaming::Name objectName;@\\
\mbox{}\verb@    objectName.length(1);@\\
\mbox{}\verb@    objectName[0].id   = (const char*) name; @\\
\mbox{}\verb@    objectName[0].kind = (const char*) "Object"; @\\
\mbox{}\verb@@\\
\mbox{}\verb@@\\
\mbox{}\verb@    // Bind obj with name objectName to the testContext:@\\
\mbox{}\verb@    try {@\\
\mbox{}\verb@      testContext->bind(objectName,obj);@\\
\mbox{}\verb@    }@\\
\mbox{}\verb@    catch(CosNaming::NamingContext::AlreadyBound& ex) {@\\
\mbox{}\verb@      testContext->rebind(objectName,obj);@\\
\mbox{}\verb@    }@\\
\mbox{}\verb@    // Note: Using rebind() will overwrite any Object previously bound @\\
\mbox{}\verb@    //       to /test/FrontOffice with obj.@\\
\mbox{}\verb@    //       Alternatively, bind() can be used, which will raise a@\\
\mbox{}\verb@    //       CosNaming::NamingContext::AlreadyBound exception if the name@\\
\mbox{}\verb@    //       supplied is already bound to an object.@\\
\mbox{}\verb@@\\
\mbox{}\verb@    // Amendment: When using OrbixNames, it is necessary to first try bind@\\
\mbox{}\verb@    // and then rebind, as rebind on its own will throw a NotFoundexception if@\\
\mbox{}\verb@    // the Name has not already been bound. [This is incorrect behaviour -@\\
\mbox{}\verb@    // it should just bind].@\\
\mbox{}\verb@  }@\\
\mbox{}\verb@  catch (CORBA::COMM_FAILURE& ex) {@\\
\mbox{}\verb@    cerr << "Caught system exception COMM_FAILURE, unable to contact the "@\\
\mbox{}\verb@         << "naming service." << endl;@\\
\mbox{}\verb@    return 0;@\\
\mbox{}\verb@  }@\\
\mbox{}\verb@  catch (omniORB::fatalException& ex) {@\\
\mbox{}\verb@    throw;@\\
\mbox{}\verb@  }@\\
\mbox{}\verb@  catch (...) {@\\
\mbox{}\verb@    cerr << "Caught a system exception while using the naming service."@\\
\mbox{}\verb@         << endl;@\\
\mbox{}\verb@    return 0;@\\
\mbox{}\verb@  }@\\
\mbox{}\verb@  return 1;@\\
\mbox{}\verb@}@\\
\mbox{}\verb@@\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item File defined by parts 9b, 10.
\end{list}
\end{flushleft}
\begin{flushleft} \small \label{part30}
\verb@"namebind.cpp"@ {\footnotesize 10 }$\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@static @\\
\mbox{}\verb@CORBA::Object_ptr@\\
\mbox{}\verb@  getObjectReference(CORBA::ORB_ptr orb, const char* context, @\\
\mbox{}\verb@                     const char* name)@\\
\mbox{}\verb@{@\\
\mbox{}\verb@  CosNaming::NamingContext_var rootContext;@\\
\mbox{}\verb@  @\\
\mbox{}\verb@  try {@\\
\mbox{}\verb@    // Obtain a reference to the root context of the Name service:@\\
\mbox{}\verb@    CORBA::Object_var initServ;@\\
\mbox{}\verb@    initServ = orb->resolve_initial_references("NameService");@\\
\mbox{}\verb@@\\
\mbox{}\verb@    // Narrow the object returned by resolve_initial_references()@\\
\mbox{}\verb@    // to a CosNaming::NamingContext object:@\\
\mbox{}\verb@    rootContext = CosNaming::NamingContext::_narrow(initServ);@\\
\mbox{}\verb@    if (CORBA::is_nil(rootContext)) @\\
\mbox{}\verb@      {@\\
\mbox{}\verb@        cerr << "Failed to narrow naming context." << endl;@\\
\mbox{}\verb@        return CORBA::Object::_nil();@\\
\mbox{}\verb@      }@\\
\mbox{}\verb@  }@\\
\mbox{}\verb@  catch(CORBA::ORB::InvalidName& ex) {@\\
\mbox{}\verb@    cerr << "Service required is invalid [does not exist]." << endl;@\\
\mbox{}\verb@    return CORBA::Object::_nil();@\\
\mbox{}\verb@  }@\\
\mbox{}\verb@@\\
\mbox{}\verb@  CosNaming::Name fullName;@\\
\mbox{}\verb@  fullName.length(2);@\\
\mbox{}\verb@@\\
\mbox{}\verb@  fullName[0].id   = (const char*) context;@\\
\mbox{}\verb@  fullName[0].kind = (const char*) "my_context"; @\\
\mbox{}\verb@  fullName[1].id   = (const char*) name;@\\
\mbox{}\verb@  fullName[1].kind = (const char*) "Object";@\\
\mbox{}\verb@  // Note on kind: The kind field is used to indicate the type@\\
\mbox{}\verb@  // of the object. This is to avoid conventions such as that used@\\
\mbox{}\verb@  // by files (name.type -- e.g. test.ps = postscript etc.)@\\
\mbox{}\verb@@\\
\mbox{}\verb@  @\\
\mbox{}\verb@  CORBA::Object_ptr obj;@\\
\mbox{}\verb@  try {@\\
\mbox{}\verb@    // Resolve the name to an object reference, and assign the reference @\\
\mbox{}\verb@    // returned to a CORBA::Object:@\\
\mbox{}\verb@    obj = rootContext->resolve(fullName);@\\
\mbox{}\verb@  }@\\
\mbox{}\verb@  catch(CosNaming::NamingContext::NotFound& ex)@\\
\mbox{}\verb@    {@\\
\mbox{}\verb@      // This exception is thrown if any of the components of the@\\
\mbox{}\verb@      // path [contexts or the object] aren't found:@\\
\mbox{}\verb@      cerr << "Context not found." << endl;@\\
\mbox{}\verb@      return CORBA::Object::_nil();@\\
\mbox{}\verb@    }@\\
\mbox{}\verb@  catch (CORBA::COMM_FAILURE& ex) {@\\
\mbox{}\verb@    cerr << "Caught system exception COMM_FAILURE, unable to contact the "@\\
\mbox{}\verb@         << "naming service." << endl;@\\
\mbox{}\verb@    return CORBA::Object::_nil();@\\
\mbox{}\verb@  }@\\
\mbox{}\verb@  catch(omniORB::fatalException& ex) {@\\
\mbox{}\verb@    throw;@\\
\mbox{}\verb@  }@\\
\mbox{}\verb@  catch (...) {@\\
\mbox{}\verb@    cerr << "Caught a system exception while using the naming service."@\\
\mbox{}\verb@         << endl;@\\
\mbox{}\verb@    return CORBA::Object::_nil();@\\
\mbox{}\verb@  }@\\
\mbox{}\verb@  return obj;@\\
\mbox{}\verb@}@\\
\mbox{}\verb@@\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item File defined by parts 9b, 10.
\end{list}
\end{flushleft}
\section{A Makefile}

This Makefile is for use with the Microsoft Visual C++ compiler.  Note
the \code{IDLFLAGS} variable, which defines the flags necessary to
cause the omniORB IDL compiler to include certain type information
needed for DII calls.  These are specific to omniORB.  Some
of the file paths used in other variables are specific to the 
way omniORB is installed.

\begin{flushleft} \small \label{part31}
\verb@"Makefile"@ {\footnotesize 12 }$\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@# Filename   : Makefile@\\
\mbox{}\verb@# Adapted from one written by : Stephen Cerniglia@\\
\mbox{}\verb@# Creation Date : February 21, 1999@\\
\mbox{}\verb@@\\
\mbox{}\verb@# Compiler Macros@\\
\mbox{}\verb@IDL      = omniidl2@\\
\mbox{}\verb@IDLFLAGS = -a -h .h -s Skel.cpp @\\
\mbox{}\verb@CPP      = cl.exe@\\
\mbox{}\verb@OMNIDEFS = /D__WIN32__ /D__x86__ /D__NT__ /D__OSVERSION__=4@\\
\mbox{}\verb@CPPFLAGS = /c /O2 /MD /GX  @{\tt \$}\verb@(OMNIDEFS)@\\
\mbox{}\verb@LD       = link.exe@\\
\mbox{}\verb@#LDFLAGS  = -nologo@\\
\mbox{}\verb@#LDFLAGS  = /nologo /debug /subsystem:console /incremental:no@\\
\mbox{}\verb@@\\
\mbox{}\verb@# Project Macros@\\
\mbox{}\verb@PROJECT = matrix@\\
\mbox{}\verb@SERVER  = server@\\
\mbox{}\verb@CLIENT  = client@\\
\mbox{}\verb@LIBDIR  = d:\dsc\omniorb\omniorb_2.7.0\lib\x86_win32@\\
\mbox{}\verb@OMNILIBS = omniDynamic270_rt.lib omniORB270_rt.lib \@\\
\mbox{}\verb@   omnithread2_rt.lib wsock32.lib advapi32.lib \@\\
\mbox{}\verb@   -libpath:d:\dsc\omniorb\omniORB_2.7.0\lib\x86_win32@\\
\mbox{}\verb@INCLDIR = /ID:\dsc\omniorb\OmniORB_2.7.0\include@\\
\mbox{}\verb@@\\
\mbox{}\verb@@\\
\mbox{}\verb@all: idl both server client@\\
\mbox{}\verb@@\\
\mbox{}\verb@both: nuweb@\\
\mbox{}\verb@        @{\tt \$}\verb@(CPP) @{\tt \$}\verb@(INCLDIR) @{\tt \$}\verb@(CPPFLAGS) @{\tt \$}\verb@(PROJECT)Skel.cpp \@\\
\mbox{}\verb@              /Fo@{\tt \$}\verb@(PROJECT).obj@\\
\mbox{}\verb@        @{\tt \$}\verb@(CPP) @{\tt \$}\verb@(INCLDIR) @{\tt \$}\verb@(CPPFLAGS) @{\tt \$}\verb@(PROJECT)DynSkel.cpp \@\\
\mbox{}\verb@              /Fo@{\tt \$}\verb@(PROJECT)Dyn.obj@\\
\mbox{}\verb@@\\
\mbox{}\verb@server: nuweb@\\
\mbox{}\verb@        @{\tt \$}\verb@(CPP) @{\tt \$}\verb@(INCLDIR) @{\tt \$}\verb@(CPPFLAGS) @{\tt \$}\verb@(SERVER).cpp \@\\
\mbox{}\verb@              /Fo@{\tt \$}\verb@(SERVER).obj@\\
\mbox{}\verb@        @{\tt \$}\verb@(LD) @{\tt \$}\verb@(LDFLAGS) -out:@{\tt \$}\verb@(SERVER).exe @{\tt \$}\verb@(OMNILIBS) \@\\
\mbox{}\verb@              @{\tt \$}\verb@(PROJECT).obj @{\tt \$}\verb@(SERVER).obj@\\
\mbox{}\verb@@\\
\mbox{}\verb@client: nuweb@\\
\mbox{}\verb@        @{\tt \$}\verb@(CPP) @{\tt \$}\verb@(INCLDIR) @{\tt \$}\verb@(CPPFLAGS) @{\tt \$}\verb@(CLIENT).cpp \@\\
\mbox{}\verb@              /Fo@{\tt \$}\verb@(CLIENT).obj@\\
\mbox{}\verb@        @{\tt \$}\verb@(LD) @{\tt \$}\verb@(LDFLAGS) -out:@{\tt \$}\verb@(CLIENT).exe @{\tt \$}\verb@(OMNILIBS) \@\\
\mbox{}\verb@              @{\tt \$}\verb@(PROJECT).obj @{\tt \$}\verb@(PROJECT)Dyn.obj @{\tt \$}\verb@(CLIENT).obj@\\
\mbox{}\verb@@\\
\mbox{}\verb@idl: nuweb@\\
\mbox{}\verb@        @{\tt \$}\verb@(IDL) @{\tt \$}\verb@(IDLFLAGS) @{\tt \$}\verb@(PROJECT).idl@\\
\mbox{}\verb@@\\
\mbox{}\verb@zip: nuweb@\\
\mbox{}\verb@        zip all *.cpp *.h *.idl Makefile@\\
\mbox{}\verb@@\\
\mbox{}\verb@clean:@\\
\mbox{}\verb@        del *.obj@\\
\mbox{}\verb@        del *.exe@\\
\mbox{}\verb@        del @{\tt \$}\verb@(PROJECT)Skel.cpp@\\
\mbox{}\verb@        del @{\tt \$}\verb@(PROJECT).h@\\
\mbox{}\verb@        del *.pdb@\\
\mbox{}\verb@@\\
\mbox{}\verb@nuweb: matrix.w@\\
\mbox{}\verb@        nuweb matrix@\\
\mbox{}\verb@@\\
\mbox{}\verb@doc: nuweb@\\
\mbox{}\verb@        latex matrix@\\
\mbox{}\verb@        nuweb matrix@\\
\mbox{}\verb@        latex matrix@\\
\mbox{}\verb@        dvips -o matrix.ps matrix@\\
\mbox{}\verb@@\end{list}
\vspace{-2ex}
\end{flushleft}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Hints for using Nuweb}
\label{nuweb:hints}

The Nuweb tool used in this exercise is a minor modification to
Brigg's \cite{Briggs} original tool, or actually to a version
previously modified by Ramsdell and Mengel.  I made additional small
changes in terminology in the \LaTeX\ file the tool produces: ``part''
is used in place of ``scrap'' and ``definition'' in place of
``macro.''  This version, called Nuweb 0.91, is available from
\emph{http://www.cs.rpi.edu/\~{}musser/gp/}. The only differences are
in the \texttt{.tex} documentation file; the new version does not
differ from previous versions in the way it produces code files from
Nuweb source files.

There are a few points about Nuweb that could trip you up if you
aren't aware of them:\begin{enumerate}

 \item Nuweb normally replaces tab characters with eight blanks.  You
can have it retain the tabs by putting a flag, {\tt -t}, on 
the Nuweb \texttt{@o} (or \texttt{@O}) command that outputs the
file.  If you keep your makefiles in a Nuweb document, as in the
preceding appendix, be sure to use this flag since the tabs are
essential to the correct interpretation of the makefile by the
\texttt{make} utility.  Thus the command to output the makefile looks
like this:
\begin{verbatim}
   @O Makefile -t
\end{verbatim}

 \item Another useful flag on Nuweb file output commands is
\texttt{-d}.  This causes \verb|#line| directives to be inserted in
the file, which are used by compilers, editors, debuggers, and other
tools to relate error messages back to lines in the original source
file (the Nuweb \texttt{.w} file in this case) rather than lines in
the file the tool is processing.  Using this feature makes it a lot
easier to make corrections directly to the Nuweb source file, which is
crucial to the literate programming approach---you shouldn't be even
looking at, much less editing, the code files or \texttt{.tex} file
produced by Nuweb.

 \item That said, there seems to be a problem with the omniORB IDL compiler
(\texttt{omniidl2}) getting a little confused by line directives in
\texttt{.idl} files.  It understands them to the extent of correctly
emitting error messages in terms of the Nuweb source file, but it
somehow fails to produce the correct \texttt{.h} file (containing C++
stub code).  For this reason, you must \emph{not} use the \texttt{-d}
flag when outputting IDL files for input to \texttt{omniidl2}.  (Or
you could use the flag initially while working out any syntax errors
in your IDL file, then remove it.)

This problem is not likely to appear when using other CORBA IDL
compilers, but I haven't yet tried it with any others.

\end{enumerate}

\end{document}





