#include <iostream>
#include <memory>
#include <string>
#include <boost/thread/thread.hpp>
#include <RCF/test/TestMinimal.hpp>
#ifdef RCF_MULTI_THREADED
#error This test must be built with RCF in single-threaded mode, i.e. RCF_MULTI_THREADED 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>
namespace Test_SingleThreadedServer {
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 gServerStarted = false;
boost::shared_ptr<boost::thread> gServerThreadPtr;
std::auto_ptr<RCF::RcfServer> gServerAutoPtr;
void joinServerThread()
{
gServerThreadPtr->join();
}
void serverThreadFunc()
{
/*
boost::bind(&boost::thread::join, gServerThreadPtr);
boost::bind(joinServerThread);
RCF::RcfServer::JoinFunctor joinFunctor1(
boost::bind(&boost::thread::join, gServerThreadPtr));
RCF::RcfServer::JoinFunctor joinFunctor2(
boost::bind(joinServerThread));
RCF::RcfServer::JoinFunctor joinFunctor3(joinServerThread);
//gServerAutoPtr->startInThisThread(joinFunctor);
*/
// boost::bind for vc6
gServerAutoPtr->startInThisThread( boost::bind(joinServerThread) );
gServerStarted = false;
}
struct X
{
std::string echo(const std::string &s)
{
return s;
}
void stopServer()
{
gServerAutoPtr->stop(false);
}
};
template<typename T, typename U>
class A
{
public:
void onServerStarted(RCF::RcfServer &server)
{
gServerStarted = true;
}
//void onServerStarted(RCF::RcfServer &server1, RCF::RcfServer &server2)
//{}
};
void onServerStarted(RCF::RcfServer &server)
{
gServerStarted = true;
}
} // namespace Test_SingleThreadedServer
int RCF_TEST_MAIN(int argc, char **argv)
{
printTestHeader(__FILE__);
using namespace Test_SingleThreadedServer;
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 );
if (typeid(*serverTransportPtr) == typeid(RCF::UdpServerTransport))
{
// TODO: find out why shared_ptr cycle detection is flagging the UDP server transport
continue;
}
RCF::writeTransportTypes(std::cout, *serverTransportPtr, *clientTransportAutoPtr);
X x;
gServerAutoPtr.reset(new RCF::RcfServer(serverTransportPtr));
gServerAutoPtr->bind( (I_X*) 0, x);
// callback to a standalone function...
gServerAutoPtr->setStartCallback(
boost::bind(Test_SingleThreadedServer::onServerStarted, _1) );
// TODO: why is borland choking on this?
// maybe it isn't
//#ifndef __BORLANDC__
// or to a member function
A<int,int> a;
gServerAutoPtr->setStartCallback(
boost::bind(&A<int,int>::onServerStarted, a, _1));
//#endif
RcfClient<I_X> client(clientTransportAutoPtr->clone());
std::string s;
gServerStarted = false;
gServerThreadPtr.reset( new boost::thread(&serverThreadFunc) );
while (!gServerStarted);
s = client.echo("abc");
BOOST_CHECK(s == "abc");
BOOST_CHECK(gServerStarted == true);
gServerAutoPtr->stop();
gServerStarted = false;
gServerThreadPtr.reset( new boost::thread(&serverThreadFunc) );
while (!gServerStarted);
Platform::OS::SleepMs(1000);
s = client.echo("abc");
BOOST_CHECK(s == "abc");
//BOOST_CHECK(serverStarted == true); // fails on Win32 because the system seems to reuse the old thread
gServerStarted = true;
client.stopServer(RCF::Oneway); // remotely stopping the server
while (gServerStarted == true); // wait until server thread exits
gServerAutoPtr.reset();
}
return 0;
}