Working with objects on other computers

	If you are connected to a LAN or the Internet, you
	can communicate tranparently with objects created by
	other running Alltalk programs. 
	
	For this example we will will consider only two programs
	running on two different machines.
	
	Machine A has an IP number stored in the string ipA
	Machine B has an IP number stored in the string ipB
	
	When two or more Alltalk programs want to interact
	over a network, they must be assigned node number
	in the range of 0..15. So you are limited to a
	total of 16 different programs that can interact.
	
	In our example we will assume that two programs
	are running on Machine A to which we assign
	the node number 1 and 2.
	
	A third program is running on Machine B which
	will be assigned the node number 3.
	
	To configure these programs so they can communicate
	each must establish its own node number and a
	connection to the other two programs. The node number
	of a program is represented by a database inside
	the Node class. A connection between two programs
	is maintained by objects of class Tunnel.
	
	Program 1 will send the following messages:
	
		Node.init[1]
		.route[2, ipA]
		.route[3, ipB]

	Program 2 will send these messages
	
		Node.init[2]
		.route[1, ipA]
		.route[3, ipB]
		
	Program 3 will send these messages:
	
		Node.init[3]
		.route[1, ipA]
		.route[2, ipA]
	
	In order to send messages to objects in other
	programs, you have to obtain their object identifiers
	by looking them up on the machine where they live.
	Each of the Tunnels we've created acts like a
	Dictionary of the objects that visible in the
	top level scope on the remote program.
	
	For example, suppose that Program 1 needs to
	send message to an object stored in the global
	varible 'goop' in Program 3:
	
	Program 1 will create a varible to hold the 
	remote object identifier and lookup the remote
	object:
	
		VAR myGoop := Node.lookup[3, 'goop']
		
	Program 1 can now treat the object stored
	in myGoop like any local object.
	
	You can pass remote objects as parameters to
	message sent anywhere and they will continue
	to act like local objects in other programs
	as long as those programs are attached to
	the objects home program by a Tunnel.
			
How can a program create new objects inside another program?
	
	Classes are simply objects themselves, stored in
	global variables that match the class names.
		
	To create a object on another node, lookup the
	class by name and the create an instance:
		
	To create a String that lives on another program:
		
		VAR s := Node.lookup[n, 'String'].newWith[128]
		
	The variable s now contains a reference to a
	string created inside the program attached
	to the other side of Tunnel d2.

Limitations 
		
	A very small number of messages are not automatically forwarded
	to the remote processes. For example, #writeln, by default is
	not forwarded so the expression:
	
		s.writeln
		
	Will be displayed locally as
	
		(RemoteObject 0x203D3464)
		
	If you actually want to send the #writeln message to the 
	remote string you can use:
	
		s._writeln
		
	This would cause the string s to be written on the remote
	programs listener window.
	
	The #writeln message is not forwarded to facilitate local
	debugging which would fail if the remote object id's could
	not be displayed by the #writeln selector.
	
	Similarly, the #string selector is not forwarded because
	it is used be the Inspector to make objects visible in
	the instance variable view. You can use #_string to get
	the "real" #string selector sent to a remote object.
	
Circular references

	It is possible for node A to send a message to an object
	on node B handled by a method that sends a message back to A.
		
	If the last method above tries to send a message to B,
	it will find the link busy with the original first message.
	
	To resolve this difficulty, the server creates a new
	link to B and forwards the message.
	
	The link table contains two linked lists for each node.
	A busy list and a free list.
	When a message is forwarded, we take a node from the 
	free list if possible. Otherwise a new link is created.
	When the link becomes free, we replace it on the free list.
	When an error is detected during any part of the process,
	the link is closed and returned to the free list.
	
	All static state variables in Node and Link are replaced
	by arrays taken from pools. After each message cycle,
	or errorl, these objects are restored to their respective
	pools.
	
