Hello,
i would like the client application to remain responsive after the
connection to the render servers has been initialized. The
MultiDisplayWindow::init() function blocks until all render servers have
connected, therefore i would like to call init or initAsync on the
MultiDisplayWindow instance in another thread.

I changed the code of the testDynamicClusterClient.cpp file (attached)
such that on connection request a thread is created that operates on
aspect 1. After that, the function in the main thread returns.

The MultiDisplayWindow pointer is changed to a MTRecPtr such that it will
be available in the connection thread. After the thread is synced to the
main thread, initAsync is called. Once a server connected, the thread
waits on a barrier.

The main thread continuously polls if the thread is waiting on the barrier
and if so, pulls the changes from the connection thread to the main
thread.
The connection thread then finishes.

This works until i want to disconnect. Setting the
MultiDisplayWindowMTRecPtr to NULL does not free the object, the
connection is lost but the server window is not closed. At this point only
the main thread exists, therefore i am puzzled what could keep the window
from being destroyed. Any ideas?

P.S. How about an explicit ClusterWindow::disconnect() that would set any
pointers that refer to the window instance to NULL, like the WeakPtr?
// testDynamicClusterClient2
//
// OpenSG cluster client program where you can dynamicly connect/disconnect
// to the servers.
// It is similar to testDynamicClusterClient but this time we create from the
// current state a changelist and send this to the cluster servers.
// This variant is much easier to implement in your own app but could be
// problematic if you use more than one aspect in your app.

// To test it, run 
//   ./testClusterServer -w pipe0 &
//   ./testDynamicClusterClient2 pipe0
//
// press 'c' to connect to the servers and 'd' to disconnect. 


#include "OSGGLUT.h"
#include "OSGConfig.h"
#include "OSGSimpleGeometry.h"
#include "OSGGLUTWindow.h"
#include "OSGSimpleSceneManager.h"
#include "OSGMultiDisplayWindow.h"
#include "OSGSceneFileHandler.h"
#include "OSGRemoteAspect.h"
#include "OSGFieldContainerFactory.h"

#include "OSGBasetypes.h"
#include "OSGThread.h"
#include "OSGBarrier.h"
#include "OSGLock.h"

#include <string>
#include <vector>

// The SimpleSceneManager to manage simple applications
OSG::SimpleSceneManagerRefPtr    _mgr = NULL;
OSG::GLUTWindowRecPtr            _client_win = NULL;
OSG::MultiDisplayWindowMTRecPtr    _cluster_win = NULL;
OSG::NodeRecPtr                  _root = NULL;
std::vector<std::string>         _pipenames;

OSG::ThreadRefPtr m_connThread = 0;
OSG::ThreadRefPtr m_appThread = 0;
OSG::BarrierRefPtr m_syncBarrier = 0;
OSG::LockRefPtr m_lock = 0;

// forward declaration so we can have the interesting stuff upfront
int setupGLUT( int *argc, char *argv[] );
void display(void);

// Initialize GLUT & OpenSG and set up the scene
int doMain(int argc, char **argv)
{
    std::cout << "start a cluster server with './testClusterServer -w pipe0'\n"
                 "press 'c' to connect to the servers.\n"
                 "press 'd' to disconnect from the servers.\n"
                 "press 'n' to delete current scene.\n"
                 "press 't' to create a torus.\n"
                 "press 'l' to load scene 'tie.wrl'.\n"
              << std::endl;
    
    // OSG init
    OSG::osgInit(argc,argv);

    // GLUT init
    int winid = setupGLUT(&argc, argv);

    // the connection between GLUT and OpenSG

    _client_win = OSG::GLUTWindow::create();

    _client_win->setGlutId(winid);
    _client_win->init();
    _client_win->setSize(300,300);
    
    for(OSG::Int32 i=0;i<argc-1;++i)
    {
        if(argv[i+1] != NULL)
            _pipenames.push_back(argv[i+1]);
    }

    if(_pipenames.empty())
        _pipenames.push_back("pipe0");
    
    _root = OSG::Node::create();
    
    _root->setCore(OSG::Group::create());
    
    // create default scene
    OSG::NodeUnrecPtr scene = OSG::makeTorus(.5, 2, 16, 16);

    _root->addChild(scene);

    // create the SimpleSceneManager helper
    _mgr = OSG::SimpleSceneManager::create();

    // tell the manager what to manage
    _mgr->setWindow(_client_win );
    _mgr->setRoot  (_root);

    // show the whole scene
    _mgr->showAll();
    
    return 0;
}

int main(int argc, char **argv)
{
    doMain(argc, argv);

    glutMainLoop();

    return 0;
}

static bool updateConnStatus(const std::string& msg, const std::string& server, 
OSG::Real32 progress)
{
    //Accessed from connection thread, needs lock if accesses member/global 
variables
    printf("%s  %s: %f\n", msg.c_str(), server.c_str(), progress);
    return true;
}

static void threadfunc(void* arg)
{
    m_syncBarrier->enter(2);
        m_appThread->getChangeList()->applyAndClear();
        m_syncBarrier->enter(2);

        m_connThread->getChangeList()->clear();

        try
        {
                OSG::ClusterWindow::ConnectionCB updateConnStatusCB = 
boost::bind(&updateConnStatus, _1, _2, _3);
                if (!_cluster_win->initAsync(updateConnStatusCB))
                {
                        _cluster_win = 0;
                        SLOG << "Connection was cancelled." << OSG::endLog;
                }
        }
        catch (OSG_STDEXCEPTION_NAMESPACE::exception& e) 
        {
                _cluster_win = 0;
        SLOG << e.what() << OSG::endLog;
        }
        
        OSG::commitChanges();

        m_syncBarrier->enter(2);
        m_syncBarrier->enter(2);
}

void poll()
{
    if (!m_syncBarrier)
        return;

    if(m_syncBarrier->getNumWaiting() > 0)
    {
            m_syncBarrier->enter(2);
            m_connThread->getChangeList()->applyAndClear();
            m_syncBarrier->enter(2);

        OSG::Thread::join(m_connThread);
    
            OSG::Thread::getCurrentChangeList()->commitChangesAndClear();
            OSG::Thread::getCurrentChangeList()->fillFromCurrentState();
        
            m_connThread  = NULL;
            m_appThread   = NULL;
            m_syncBarrier = NULL;

        //glutIdleFunc(NULL);
        glutPostRedisplay();
    }
}

static void connectCluster(void)
{
    if(_cluster_win != NULL)
        return;

    OSG::Viewport *clientvp = _client_win->getPort(0);
    
    // create the viewports for the cluster just a simple one ...
    OSG::ViewportUnrecPtr vp = OSG::Viewport::create();

    vp->setCamera    (_mgr->getCamera());
    vp->setBackground(clientvp->getBackground());
    vp->setRoot      (clientvp->getRoot());
    vp->setSize      (0,0, 1,1);

    // the connection between this client and the servers
    _cluster_win = OSG::MultiDisplayWindow::create();

    for(OSG::UInt32 i=0;i<_pipenames.size();++i)
        _cluster_win->editMFServers()->push_back(_pipenames[i]);
    // dummy size for navigator
    _cluster_win->setSize(300,300);
    _cluster_win->addPort(vp);


        bool isGlobal = false;
        m_syncBarrier = OSG::Barrier::get("CAVEManager.sync", isGlobal);
        m_appThread   = 
dynamic_cast<OSG::Thread*>(OSG::ThreadManager::getAppThread());
        m_connThread  = 
OSG::dynamic_pointer_cast<OSG::Thread>(OSG::ThreadManager::the()->getThread("CAVEManager.connection",
 isGlobal));
        m_lock  = OSG::Lock::get("CAVEManager.lock", isGlobal);

    OSG::commitChanges();

        m_connThread->runFunction(threadfunc, 
OSG::Thread::getCurrentAspect()+1, NULL); //create a new thread working on a 
different aspect as the one on the main thread

        m_syncBarrier->enter(2);
        m_syncBarrier->enter(2);
}

static void disconnectCluster(void)
{
    _cluster_win = NULL;
}

//
// GLUT callback functions
//



// redraw the window
void display(void)
{
    // redraw the client window
    _mgr->redraw();
    OSG::commitChanges();

    try
    {
        if(_cluster_win != NULL)
        {
            // redraw the server windows
            _cluster_win->render(_mgr->getRenderAction());
        }
    }
    
    catch(OSG_STDEXCEPTION_NAMESPACE::exception &)
    {
        //printf("error: '%s'\n", e.what());
        printf("ClusterServer was killed!\n");

        _cluster_win = NULL;
    } 
    
    OSG::commitChanges();
    OSG::clearChangeList();
}

// react to size changes
void reshape(int w, int h)
{
    glutPostRedisplay();
}

// react to mouse button presses
void mouse(int button, int state, int x, int y)
{
    if (state)
        _mgr->mouseButtonRelease(button, x, y);
    else
        _mgr->mouseButtonPress(button, x, y);

    glutPostRedisplay();
}

// react to mouse motions with pressed buttons
void motion(int x, int y)
{
    _mgr->mouseMove(x, y);

    glutPostRedisplay();
}

// react to keys
void keyboard(unsigned char k, int x, int y)
{
    switch(k)
    {
        case 27:    
        {
            _mgr         = NULL;

            _client_win  = NULL;
            _cluster_win = NULL;
            _root        = NULL;

            OSG::osgExit();
            exit(0);
        }
        case 'n':
            while(_root->getNChildren() > 0)
                _root->subChild(_root->getChild(0));

            glutPostRedisplay();
        break;
        case 'l':
        {
            OSG::NodeUnrecPtr scene = 
                OSG::SceneFileHandler::the()->read("tie.wrl", NULL);

            if(scene != NULL)
            {
                _root->addChild(scene);

                _mgr->showAll();

                glutPostRedisplay();
            }
        }
        break;
        case 't':
        {
            OSG::NodeUnrecPtr scene = OSG::makeTorus(.5, 2, 16, 16);

            _root->addChild(scene);

            _mgr->showAll();

            glutPostRedisplay();
        }
        break;
        case 'c':
            connectCluster();
        break;
        case 'd':
            disconnectCluster();
        break;
    }
}

// setup the GLUT library which handles the windows for us
int setupGLUT(int *argc, char *argv[])
{
    glutInit(argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
    
    int winid = glutCreateWindow("OpenSG");
    
    glutReshapeFunc(reshape);
    glutDisplayFunc(display);
    glutMouseFunc(mouse);
    glutMotionFunc(motion);
    glutKeyboardFunc(keyboard);
    glutIdleFunc(poll);

    return winid;
}
------------------------------------------------------------------------------
Monitor your physical, virtual and cloud infrastructure from a single
web console. Get in-depth insight into apps, servers, databases, vmware,
SAP, cloud infrastructure, etc. Download 30-day Free Trial.
Pricing starts from $795 for 25 servers or applications!
http://p.sf.net/sfu/zoho_dev2dev_nov
_______________________________________________
Opensg-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensg-users

Reply via email to