[thrift] Add optional callback inside of serve()

Summary: If enabled, the callback function will be run after the listening socket is opened and the event loop initialized, just prior to calling event_loop()

This is handy if you want to defer some of your initialization until after the socket is open -- allowing clients to connect, but not processing requests until the initialization is complete. I use this in the Synapse tablet server to minimize the communications interruption that happens during a tablet split (replaying commit logs after opening the listening socket).

Review: mcslee
Test Plan: compiled it into Synapse's tablet server
Revert: ok


git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@665137 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/cpp/src/server/TNonblockingServer.h b/lib/cpp/src/server/TNonblockingServer.h
index 6da9bf5..6997c45 100644
--- a/lib/cpp/src/server/TNonblockingServer.h
+++ b/lib/cpp/src/server/TNonblockingServer.h
@@ -63,6 +63,11 @@
    */
   std::stack<TConnection*> connectionStack_;
 
+  // Pointer to optional function called after opening the listen socket and
+  // before running the event loop, along with its argument data
+  void (*preServeCallback_)(void*);
+  void* preServeCallbackArg_;
+
   void handleEvent(int fd, short which);
 
  public:
@@ -72,7 +77,9 @@
     serverSocket_(0),
     port_(port),
     frameResponses_(true),
-    threadPoolProcessing_(false) {}
+    threadPoolProcessing_(false),
+    preServeCallback_(NULL),
+    preServeCallbackArg_(NULL) {}
 
   TNonblockingServer(boost::shared_ptr<TProcessor> processor, 
                      boost::shared_ptr<TProtocolFactory> protocolFactory,
@@ -82,7 +89,9 @@
     serverSocket_(0),
     port_(port),
     frameResponses_(true),
-    threadManager_(threadManager) {
+    threadManager_(threadManager), 
+    preServeCallback_(NULL),
+    preServeCallbackArg_(NULL) {
     setInputTransportFactory(boost::shared_ptr<TTransportFactory>(new TTransportFactory()));
     setOutputTransportFactory(boost::shared_ptr<TTransportFactory>(new TTransportFactory()));
     setInputProtocolFactory(protocolFactory);
@@ -101,7 +110,9 @@
     serverSocket_(0),
     port_(port),
     frameResponses_(true),
-    threadManager_(threadManager) {
+    threadManager_(threadManager),
+    preServeCallback_(NULL),
+    preServeCallbackArg_(NULL) {
     setInputTransportFactory(inputTransportFactory);
     setOutputTransportFactory(outputTransportFactory);
     setInputProtocolFactory(inputProtocolFactory);
@@ -141,6 +152,12 @@
   }
 
   void serve();
+
+  void setPreServeCallback(void(*fn_ptr)(void*), void* arg = NULL) {
+    preServeCallback_ = fn_ptr;
+    preServeCallbackArg_ = arg;
+  }
+
 };
 
 /**