#include <iostream>
#include <memory>
#include <string>
#include <boost/test/minimal.hpp>
#include <boost/thread/thread.hpp>
#ifdef RCF_USE_BOOST_THREADS
#error This test must be built with RCF in single-threaded mode, i.e. RCF_USE_BOOST_THREADS must not be defined.
#endif
#include <RCF/Idl.hpp>
#include <RCF/RcfServer.hpp>
#include <RCF/test/TransportFactories.hpp>
#include <RCF/util/CommandLine.hpp>
#include <RCF/util/Platform/OS/Sleep.hpp>
RCF_BEGIN(I_X, "I_X")
RCF_METHOD_R1(std::string, echo, std::string)
RCF_METHOD_V0(void, stopServer)
RCF_END(I_X)
volatile bool serverStarted = false;
std::auto_ptr<RCF::RcfServer> server;
boost::shared_ptr<boost::thread> serverThread;
void joinServerThread()
{
serverThread->join();
}
void serverThreadFunc()
{
server->startInThisThread( joinServerThread );
serverStarted = false;
}
struct X
{
std::string echo(const std::string &s)
{
return s;
}
void stopServer()
{
server->stop(false);
}
};
template<typename T, typename U>
class A
{
public:
void onServerStarted(RCF::RcfServer &server)
{
serverStarted = true;
}
void onServerStarted(RCF::RcfServer &server1, RCF::RcfServer &server2)
{}
};
void onServerStarted(RCF::RcfServer &server)
{
serverStarted = true;
}
int test_main(int argc, char **argv)
{
util::CommandLine::getSingleton().parse(argc, argv);
for (unsigned int i=0; i<RCF::getTransportFactories().size(); ++i)
{
RCF::TransportFactoryPtr transportFactoryPtr = RCF::getTransportFactories()[i];
std::pair<RCF::ServerTransportPtr, RCF::ClientTransportAutoPtrPtr> transports = transportFactoryPtr->createTransports();
RCF::ServerTransportPtr serverTransportPtr( transports.first );
RCF::ClientTransportAutoPtr clientTransportAutoPtr( *transports.second );
RCF::writeTransportTypes(std::cout, *serverTransportPtr, *clientTransportAutoPtr);
X x;
server.reset(new RCF::RcfServer(serverTransportPtr));
server->bind<I_X>(x);
// callback to a standalone function...
server->setStartCallback(onServerStarted );
// TODO: why is borland choking on this?
#ifndef __BORLANDC__
// or to a member function
A<int,int> a;
server->setStartCallback(&A<int,int>::onServerStarted, a); // on some compilers (msvc 7.1 at least), the "&" isn't needed
#endif
RcfClient<I_X> client(clientTransportAutoPtr->clone());
std::string s;
serverStarted = false;
serverThread.reset( new boost::thread(&serverThreadFunc) );
while (!serverStarted);
s = client.echo("abc");
BOOST_CHECK(s == "abc");
BOOST_CHECK(serverStarted == true);
server->stop();
serverThread.reset();
while (serverStarted);
serverThread.reset( new boost::thread(&serverThreadFunc) );
while (!serverStarted);
s = client.echo("abc");
BOOST_CHECK(s == "abc");
//BOOST_CHECK(serverStarted == true); // fails on Win32 because the system seems to reuse the old thread
serverStarted = true;
client.stopServer(RCF::Oneway); // remotely stopping the server
while (serverStarted); // wait until server thread exits
server.reset();
}
return 0;
}