Example files in this directory are meant to illustrate features of asyncoro
framework. They are not necessarily efficient versions, nor very useful. The
descriptions below are sorted on the names of files, so some examples at the
beginning use advanced features, whereas later files (especially files that
start with 'tut_') may be easier to follow.

dispy project (http://dispy.sourceforge.net) uses asyncoro to implement Python
framework for distributed and parallel computing.

* chat_chan_client.py and chat_chan_server.py use broadcasting over a channel to
  send messages to all participants to implement a simple chat (message)
  service.  To use this and other 'chat' examples below, run the server, and
  multiple clients (either on same machine or other machines in local
  network). Messages typed in one client show up at other clients.

* chat_sock_client.py and chat_sock_server.py use asynchronous network
  programming, coroutines and message passing to implement a chat (message)
  server that is used by clients to broadcast messages.

* discomp1.py illustrates how to use discoro and RemoteCoroScheduler for
  distributed computing. The computations are assumed to CPU intensive so at
  most one computation would be running at a server process (to use all
  available local or remote CPUs), similar to using 'dispy'
  (http://dispy.sourceforge.net) project. The computations are regular Python
  functions (not coroutine / generator functions), which are executed in a
  thread by a coroutine. See 'discoro_client*.py' files for executing only
  coroutines (i.e., computations are coroutines).

* discomp2.py is another example of distributed computing, similar to
  discomp1.py. It shows how to use status messages from discoro scheduler
  (instead of simpler RemoteCoroScheduler) to run coroutines at remote server
  processes. It also initializes global variable (asynchronous thread pool to
  run computations) using setup coroutine; the global variable is used in
  coroutines.

* discomp3.py illustrates how to relay status messages from discoro scheduler to
  RemoteCoroScheduler and httpd concurrently. Computations are executed in
  thread functions on remote servers which process stream of requests sent by
  client and send results back to client, using message passing. Status of
  cluster / node / serer can be monitored in a web browser (at port 8181).

* discomp4.py runs an external program (discomp4_proc.py) at remote servers. The
  program reads from standard input and writes to standard output. Asynchronous
  pipes and message passing are used to send input from client to this program
  executing on remote servers, and get the output back to client.

* discoro_client1.py uses RemoteCoroScheduler to distribute a coroutine function
  and execute remote coroutines with that function.

* discoro_client2.py uses RemoteCoroScheduler to distribute coroutine function
  and a class. The local coroutine (running at client) and remote coroutines
  exchange objects of that class using message passing.

* discoro_client3.py is an alternate implementation of discoro_client1.py;
  instead of using RemoteCoroScheduler (which is easier), messages from discoro
  scheduler are used to schedule remote coroutines.

* discoro_client4.py is another example of using discoro. It sends files at the
  client to remote process to execute computations that process those files and
  the remote process in turn sends the results in files back to the client.

* discoro_client5.py uses RemoteCoroScheduler to run remote coroutines. The
  remote coroutines send results back to coroutine at client.

* discoro_client6.py uses streaming of data to remote coroutines for efficient
  communication. The example also shows how to implement live/real-time
  analytics and send them to client.

* discoro_client6_channel.py is same as discoro_client6.py, except it uses
  channel to broadcast data to remote coroutines.

* discoro_client7.py shows how to relay status messages from discoro scheduler
  to RemoteCoroScheduler and httpd concurrently. Computation prograss can be
  monitored in a web browser.

* discoro_client8.py illustrates using RemoteCoroScheduler to submit
  computations and process the results in a concise form.

* discoro_client9.py uses RemoteCoroScheduler to setup remote server processes
  by reading data in files in to global variables (memory) for processing that
  data in comptations efficiently (i.e., in-memory processing).

* discoro_ssh_ec2.py is same as discoro_client8.py, but the setup is for using
  ssh port forwarding to work with Amazon EC2 cloud computing; i.e., the client
  runs locally and discoronode runs on remote Amazon EC2 cloud infrastructure.

* hotswap.py and hotswap_funcs.py illustrate how a running coroutine function
  can be swapped with a new function. The currently running function
  checks/validates the function being replaced, any unprocessed messages in the
  coroutine are processed with new functionality.

* pipe_csum.py uses asynchronous pipes to write data to and read data from a
  system program (that computes checksum of data).

* pipe_grep.py uses chained pipes with asynchronous read and write interface to
  count number of lines matching a pattern.

* rci_monitor_client.py and rci_monitor_server.py illustrate another approach to
  execute remote coroutines: The server registers a function and client requests
  to execute coroutine with that function. Compare this to discoro_client.py
  where the client sends the computation itself to the remote server, so the
  client can execute arbitrary functions, whereas with RCI only registered
  functions can be executed by clients.

* remote_channel_client.py and remote_channel_server.py use broadcasting
  channels to exchange messages among a sender and local/remote recipients.

* remote_coro_client.py and remote_coro_server.py exchange messages with
  one-to-one message passing to exchange messages between two remote coroutines.

* socket_afile.py creates a server and a client connected with a socket, which
  is then converted to asynchronous file. The server and client exchange data
  with asynchronous file interface. This example doesn't work in Windows, as
  sockets in Windows don't have underlying file.

* tut_channel.py is another example illustrating usage of broadcasting channel
  to exchange messages in local coroutines.

* tut_client.py and tut_server.py show message passing between remote client and
  server coroutines.

* tut_client_server.py shows message passing between local client and server
  coroutines. The remote version and local version are similar, except that
  remote versions register/locate coroutines.

* tut_coros.py creates a number of coroutines that each suspend execution for a
  brief period. The number of coroutines created can be increased to thousands
  or tens of thousands to show asyncoro can scale well.

* tut_sock_client.py and tut_sock_server.py use asynchronous network
  programmming to communicate.

* udp.py creates client server coroutines that communicate using asynchronous
  UDP sockets.

* webserver.py is an impelementation of "Ping Pong" benchmark server described
  at http://nichol.as/asynchronous-servers-in-python.
