Search code examples
thriftthrift-protocol

Apache Thrift: Open and close transport automatically in C++


Background: I have many small c++ programs that all use the same static library. I'm now implementing thrift as a middle layer so that I can run the small c++ programs on a different computer from the static library. I can't change the c++ programs, so I am making a "fake" static library that looks like the original, but is actually a thrift client that calls the real static library.

Issue: How can I make the static library so that the c++ programs will automatically open the socket when it opens the library, and closes the socket when the program exits??

Usually thrift clients use a main method that opens the socket in the beginning and closes it in the end. I can have the library check if the socket is open before every method call, but I don't know how to close the socket. Is there any problem with leaving it open?


Solution

  • One approach might be to create a C++ class in your library with a single local static instance. Since the instance will be constructed on first call and destroyed on unload, you can connect and disconnect using the constructor/destructor, something like this:

    #include <boost/shared_ptr.hpp>
    #include <thrift/transport/TSocket.h>
    #include <thrift/protocol/TBinaryProtocol.h>
    #include "gen-cpp/mySvc.h"                  
    
    using namespace apache::thrift::transport;  
    using namespace apache::thrift::protocol;   
    
    class ThriftProxy {
    public:
        ThriftProxy() :
            trans(new TSocket("myhost", 8585)),
            proto(new TBinaryProtocol(trans)),
            client_(proto)
        {
            trans->open();
        }
    
        ~ThriftProxy()
        {
            trans->close();
        }
    
        static mySvcClient & client() 
        {
            static ThriftProxy proxy;
            return proxy.client_;
        }    
    
    private:
        boost::shared_ptr<TSocket> trans;
        boost::shared_ptr<TProtocol> proto;
        mySvcClient client_;
    };
    

    the functions in your lib can then call through to the Apache Thrift server using the ThriftProxy::client() method:

    int exportedFunc(int i) {
        return ThriftProxy::client().myRPCFunc(i);
    }
    

    Note: In most cases adding a TBufferedTransport or TFramedTransport to the I/O stack is a good idea to reduce small writes to the network. Left out here to keep the example simple.