YMMV
email cpiro@facebook.com
--

TO START A SERVER:

$ cd lib/erl/lib/thrift/
$ cd tutorial
$ thrift -cpp -java -py -php -rb -perl -erl -xsd -r tutorial.thrift
$ cd ..
$ make
$ ./server.sh
> Pid = server:start().
  ** GAZE IN AMAZEMENT **
> server:stop(Pid).

NOTES:

get/set never means process dictionary

tExecptions and t*Factorys are straight "new" -- e.g. TF = tTransportFactory:new()
everything else is start_new (i.e. gen_server:start_link) -- this spawns a process and returns a pid

notable change from the Ruby:
in t*Server:new, the parameters now include a handler, i.e. the generated module name.  For example if your interface is called calculator, then to spawn a TSimpleServer try: oop:start_new(tSimpleServer, [calculator, calculatorHandler, Transport, TF])

tErlProcessor is a shim around the generated code (which is not actually a gen_server).  Of course tErlProcessor isn't a gen_server either ... thrift_oop_server is a shim to make our "Thrift objects" gen_servers.  Maybe we should remove some layers?

Use tErlServer and tErlAcceptor.  tSimpleServer and tServerSocket are incompatible by design ... the call trace is spastic across the process tree.  tErlServer and tErlAcceptor follow the same model as iserve: 
 * the top level code spawns a tErlServer, which listens on a socket
 * a tErlAcceptor is spawned and calls accept() on the listening socket
 * when accept() finishes, the tErlAcceptor 
   * tells the tErlServer to spawn a new acceptor
   * handles the requests by spawning a processor, a transport, and a protocol
 * (the tricky part) when the socket closes, the protocol exits, so:
   * the transport exits because it's the one caller of the protocol
   * likewise, the processor exits because it's the caller of the transport
   * the tErlAcceptor traps the protocol's exit and exits with an acceptor_done
   * the tErlServer sees that the acceptor exited and does nothing since there is already another acceptor accept()ing on the listen socket
