Click here to Skip to main content
15,886,873 members
Articles / Programming Languages / C++

RCF - Interprocess Communication for C++

Rate me:
Please Sign up or sign in to vote.
4.94/5 (147 votes)
25 Oct 2011CPOL20 min read 4.6M   8.4K   331  
A server/client IPC framework, using the C++ preprocessor as an IDL compiler.
//*****************************************************************************
// RCF - Remote Call Framework
// Copyright (c) 2005. All rights reserved.
// Developed by Jarl Lindrud.
// Contact: jlindrud@hotmail.com .
//*****************************************************************************

#ifndef INCLUDE_RCF_OBJECTFACTORYSERVICE_HPP
#define INCLUDE_RCF_OBJECTFACTORYSERVICE_HPP

#include <map>
#include <string>
#include <vector>

#include <boost/shared_ptr.hpp>
#include <boost/utility.hpp>

#include <RCF/GetInterfaceName.hpp>
#include <RCF/Service.hpp>
#include <RCF/StubFactory.hpp>
#include <RCF/ThreadLibrary.hpp>
#include <RCF/Token.hpp>

namespace RCF {

    class RcfServer;
    class StubEntry;
    class I_StubFactory;
    class I_RcfClient;
    class Token;

    typedef boost::shared_ptr<StubEntry> StubEntryPtr;
    typedef boost::shared_ptr<I_StubFactory> StubFactoryPtr;

    /// Service allowing remote clients to create objects on the server side,
    /// as opposed to just calling methods on pre-existing objects.
    class ObjectFactoryService : 
        public I_Service, 
        public I_StubEntryLookupProvider,
        boost::noncopyable
    {
    public:

        /// Constructor.
        /// \param numberOfTokens Maximum number of tokens, thereby also maximum number of created objects.
        /// \param objectTimeoutS Duration of time, in seconds, which must pass after a client invocation, before a created object may be deleted.
        ObjectFactoryService(unsigned int numberOfTokens, unsigned int objectTimeoutS);

        /// Remotely accessible function, via I_ObjectFactory, allows a client to request the creation of an object.
        /// \param objectName Name of the type of the object to be created.
        /// \param token Token assigned to the created object, if the object was created.
        /// \return true if successful, otherwise false.
        bool createObject(const std::string &objectName, Token &token);

        /// Binds an object factory to a name.
        /// \param name Name by which clients will access the object factory.
        /// \return true if successful, otherwise false.
        template<typename InterfaceT, typename ImplementationT> 
        bool bind(std::string name = "");

    private:
        StubEntryPtr getStubEntryPtr(const Token &token);
        void onServiceAdded(RcfServer &server);
        void onServiceRemoved(RcfServer &server);
        //void wakeCleanup();
        void stopCleanup();
        bool cycleCleanup(int timeoutMs, const volatile bool &stopFlag);
        bool insertStubFactory(const std::string &objectName, const std::string &desc, boost::shared_ptr<I_StubFactory> factory);
        bool removeStubFactory(const std::string &objectName);
        boost::shared_ptr<I_StubFactory> getStubFactory(const std::string &objectName);
        void cleanupStubMap(unsigned int timeoutS);
        void allocateStubMap();

        class TokenFactory : boost::noncopyable
        {
        public:
            TokenFactory(int tokenCount);
            bool requestToken(Token &token);
            void returnToken(const Token &token);
            const std::vector<Token> &getTokenSpace();
            unsigned int getAvailableTokenCount();

        private:
            std::vector<Token> mTokenSpace;
            std::vector<Token> mAvailableTokens;
            ReadWriteMutex mMutex;
        };

        // internally synchronized
        TokenFactory mTokenFactory;

        unsigned int mClientStubTimeoutS;
        Mutex mCleanupThresholdMutex;
        Condition mCleanupThresholdCondition;
        
        typedef std::map<std::string, StubFactoryPtr> StubFactoryMap;
        typedef std::map<Token, StubEntryPtr> StubMap;
        StubMap mStubMap; // preallocated and synchronized per element

        ReadWriteMutex mStubFactoryMapMutex;
        StubFactoryMap mStubFactoryMap;

        volatile bool mStopFlag;
    };

    typedef boost::shared_ptr<ObjectFactoryService> ObjectFactoryServicePtr;

    bool createRemoteObjectNamed(I_RcfClient &rcfClient, std::string objectName);

    template<typename Interface>
    inline bool createRemoteObject(I_RcfClient &rcfClient, std::string objectName = "")
    {
        if (objectName == "")
        {
            objectName = getInterfaceName<Interface>();
        }
        return createRemoteObjectNamed(rcfClient, objectName);
    }

    template<typename InterfaceT, typename ImplementationT> 
    inline bool ObjectFactoryService::bind(std::string name_)
    {
        const std::string &name = (name_ == "") ? getInterfaceName<InterfaceT>() : name_;
        boost::shared_ptr<I_StubFactory> stubFactoryPtr( new RCF::StubFactory<ImplementationT, InterfaceT>() );
        std::string desc; // TODO
        return insertStubFactory(name, desc, stubFactoryPtr);
    }

} // namespace RCF

#endif // ! INCLUDE_RCF_OBJECTFACTORYSERVICE_HPP

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Australia Australia
Software developer, from Sweden and now living in Canberra, Australia, working on distributed C++ applications. When he is not programming, Jarl enjoys skiing and playing table tennis. He derives immense satisfaction from referring to himself in third person.

Comments and Discussions