//*****************************************************************************
// 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