[moved to core for discussion]

        Hello all,

Carsten Neumann wrote:
With only one ref count shared across all aspect copies I'm not sure if this can be fixed in 1.x, I'm currently double checking that it works as expected in 2.0.

attached is the 2.0 version of Marc's program; it crashes in Image::changed in the render thread. The problem comes from SimpleTexturedMaterial. It creates the TextureObjChunk for the Image with createLocal, but since the image comes from the app it is known across aspects, but it's parent (the TexObjChunk) exists only in one aspect. I think the right fix is to put the objects SimpleTexturedMaterial creates into (internal) fields and have them synced normally. In general this means if an object is created with createLocal(), it must not point to something created with create().
Any ideas if it is possible to relax that or check/enforce it?

        Cheers,
                Carsten
#ifdef OSG_BUILD_ACTIVE

#include <OSGSimpleSceneManager.h>
#include <OSGSimpleTexturedMaterial.h>
#include <OSGNameAttachment.h>
#include <OSGSimpleGeometry.h>
#include <OSGGLUTWindow.h>
#include <OSGGLUT.h>
#include <OSGMaterialGroup.h>

#else // OSG_BUILD_ACTIVE

#include <OpenSG/OSGSimpleSceneManager.h>
#include <OpenSG/OSGSimpleTexturedMaterial.h>
#include <OpenSG/OSGNameAttachment.h>
#include <OpenSG/OSGSimpleGeometry.h>
#include <OpenSG/OSGGLUTWindow.h>
#include <OpenSG/OSGGLUT.h>
#include <OpenSG/OSGMaterialGroup.h>

#endif // OSG_BUILD_ACTIVE

OSG::SimpleSceneManager *mgr;
OSG::NodeUnrecPtr scene;
OSG::Thread* renderThread;
OSG::Thread* creationThread;
OSG::Barrier* syncBarrier;
volatile bool syncNeeded;

OSG::UInt32 fcStoreInitialSize = 0;

int setupGLUT( int *argc, char *argv[] );

void printOSGInstances(const std::string &prefix)
{
    OSG::UInt32 liveFC         = 0;
    OSG::UInt32 liveFCInAspect = 0;
    OSG::UInt32 fcStoreSize    = OSG::FieldContainerFactory::the()->getNumContainers();

    std::cout << prefix << "FieldContainerFactory::size(): "
              << (fcStoreSize - fcStoreInitialSize) << std::endl;

    for(OSG::UInt32 i = fcStoreInitialSize; i < fcStoreSize; ++i)
    {
        OSG::FieldContainer *fc = OSG::FieldContainerFactory::the()->getContainer(i);
        OSG::AspectStore    *as = OSG::FieldContainerFactory::the()->getContainerHandler(i);
        
        if(as != NULL)
        {
            ++liveFC;

            std::cout << prefix << "Detected live FC " << i;

            OSG::UInt32 numAspects = as->getNumAspects();
            for(OSG::UInt32 j = 0; j < numAspects; ++j)
            {
                std::cout << " (" << (j+1) << "/" << numAspects << ") rc ";
                if(as->getPtr(j) != NULL)
                    std::cout << as->getPtr(j)->getRefCount();
                else
                    std::cout << "N/A";
            }

            std::cout << "\n";
        }

        if(fc != NULL)
        {
            ++liveFCInAspect;

            std::cout << prefix 
                      << "Detected live FC " << fc->getTypeName() 
                      << " id: " << fc->getId()
                      << " " << fc
                      << " rc: " << fc->getRefCount() << std::endl;
        }
    }

    std::cout << prefix
              <<  "liveFC " << liveFC
              << " liveFCInAspect " << liveFCInAspect 
              << " store size " << (fcStoreSize - fcStoreInitialSize) << std::endl;
}


OSG::NodeTransitPtr createScenegraph(void)
{
    OSG::NodeUnrecPtr n = OSG::Node::create();
    n->setCore(OSG::Group::create());

    return OSG::NodeTransitPtr(n);
}


// executed by each geometry creation thread
void create(void *args)
{
    syncBarrier->enter(2);
    renderThread->getChangeList()->applyNoClear();
    syncBarrier->enter(2);

    // (1)
    {
        OSG::NodeRecPtr node = OSG::Node::create();
        syncNeeded = true;
        std::cout << "(1a) pre-sync  ==============================================\n";
        printOSGInstances("createThread: ");
        syncBarrier->enter(2);
        syncNeeded = false;
        syncBarrier->enter(2);
        std::cout << "(1a) post-sync ==============================================\n";
        printOSGInstances("createThread: ");

        OSG::GeometryRecPtr geo = OSG::Geometry::create();
        node->setCore(geo);

        OSG::commitChanges();

        syncNeeded = true;
        std::cout <<  "(1b) pre-sync  ==============================================\n";
        printOSGInstances("createThread: ");
        syncBarrier->enter(2);
        syncNeeded = false;
        syncBarrier->enter(2);
        std::cout << "(1b) post-sync ===============================================\n";
        printOSGInstances("createThread: ");
    }

    OSG::commitChanges();

    syncNeeded = true;
    std::cout << "(1c) pre-sync  ==============================================\n";
    printOSGInstances("createThread: ");
    syncBarrier->enter(2);
    syncNeeded = false;
    syncBarrier->enter(2);
    std::cout << "(1c) post-sync ==============================================\n";
    printOSGInstances("createThread: ");

    // (2)
    {
        OSG::NodeRecPtr node = OSG::Node::create();
        syncNeeded = true;
        std::cout << "(2a) pre-sync  ==============================================\n";
        printOSGInstances("createThread: ");
        syncBarrier->enter(2);
        syncNeeded = false;
        syncBarrier->enter(2);
        std::cout << "(2a) post-sync ==============================================\n";
        printOSGInstances("createThread: ");

        OSG::GeometryRecPtr         geo = OSG::Geometry        ::create();
        OSG::GeoPnt3fPropertyRecPtr pos = OSG::GeoPnt3fProperty::create();
       
        geo->setPositions(pos);
        node->setCore(geo);

        OSG::commitChanges();

        syncNeeded = true;
        std::cout << "(2b) pre-sync  ==============================================\n";
        printOSGInstances("createThread: ");
        syncBarrier->enter(2);
        syncNeeded = false;
        syncBarrier->enter(2);
        std::cout << "(2b) post-sync ==============================================\n";
        printOSGInstances("createThread: ");
    }

    OSG::commitChanges();

    syncNeeded = true;
    std::cout << "(2c) pre-sync  ==============================================\n";
    printOSGInstances("createThread: ");
    syncBarrier->enter(2);
    syncNeeded = false;
    syncBarrier->enter(2);
    std::cout << "(2c) post-sync ==============================================\n";
    printOSGInstances("createThread: "); // crash here!
    std::cout << std::endl;

    // (3)
    for (unsigned int i=0; i<20; i++)
    {
#if 1
        OSG::NodeRecPtr node = OSG::Node::create();

        syncNeeded = true;
        if((i > 0) && (i % 10 == 0))
        {
            std::cout << "(3a) pre-sync (" << i << ") ==============================================\n";
            printOSGInstances("createThread: ");
        }
        syncBarrier->enter(2);
        syncNeeded = false;
        syncBarrier->enter(2);
        if((i > 0) && (i % 100 == 0))
        {
            std::cout << "(3a) post-sync (" << i << ") ==============================================\n";
            printOSGInstances("createThread: ");
        }

        OSG::GeometryRecPtr boxGeo = OSG::makeBoxGeo(20, 20, 20, 20, 20, 20);
        node->setCore(boxGeo);

        OSG::commitChanges();

        syncNeeded = true;
        if((i > 0) && (i % 10 == 0))
        {
            std::cout << "(3b) pre-sync (" << i << ") ==============================================\n";
            printOSGInstances("createThread: ");
        }
        syncBarrier->enter(2);
        syncNeeded = false;
        syncBarrier->enter(2);
        if((i > 0) && (i % 10 == 0))
        {
            std::cout << "(3b) post-sync (" << i << ") ==============================================\n";
            printOSGInstances("createThread: ");
        }
#endif

        OSG::commitChanges();

#if 0
        {
            OSG::NodeRecPtr node = OSG::Node::create();
            std::cout << "(4a) pre-sync  ==============================================\n";
            printOSGInstances("createThread: ");
            syncNeeded = true;
            syncBarrier->enter(2);
            syncNeeded = false;
            syncBarrier->enter(2);
            std::cout << "(4a) post-sync ==============================================\n";
            printOSGInstances("createThread: ");
            
            OSG::SimpleTexturedMaterialRecPtr mat = OSG::SimpleTexturedMaterial::create();
            OSG::ImageRefPtr img = OSG::Image::create();
            mat->setImage(img);

            OSG::MaterialGroupRecPtr mat_grp = OSG::MaterialGroup::create();
            mat_grp->setMaterial(mat);

            node->setCore(mat_grp);

            OSG::commitChanges();

            std::cout << "(4b) pre-sync  ==============================================\n";
            printOSGInstances("createThread: ");
            syncNeeded = true;
            syncBarrier->enter(2);
            syncNeeded = false;
            syncBarrier->enter(2);
            std::cout << "(4b) post-sync ==============================================\n";
            printOSGInstances("createThread: ");
        }

        OSG::commitChanges();

        syncNeeded = true;
        std::cout << "(4c) pre-sync  ==============================================\n";
        printOSGInstances("createThread: ");
        syncBarrier->enter(2);
        syncNeeded = false;
        syncBarrier->enter(2);
        std::cout << "(4c) post-sync ==============================================\n";
        printOSGInstances("createThread: ");

        syncNeeded = true;
        std::cout << "(4d) pre-sync  ==============================================\n";
        printOSGInstances("createThread: ");
        syncBarrier->enter(2);
        syncNeeded = false;
        syncBarrier->enter(2);
        std::cout << "(4d) post-sync ==============================================\n";
        printOSGInstances("createThread: ");
#endif
    }

    OSG::commitChanges();

    syncNeeded = true;
    std::cout << "(3c) pre-sync  ==============================================\n";
    printOSGInstances("createThread: ");
    syncBarrier->enter(2);
    syncNeeded = false;
    syncBarrier->enter(2);
    std::cout << "(3c) post-sync ==============================================\n";
    printOSGInstances("createThread: ");

#if 1
    {
        OSG::NodeRecPtr node = OSG::Node::create();
        std::cout << "(4a) pre-sync  ==============================================\n";
        printOSGInstances("createThread: ");
        syncNeeded = true;
        syncBarrier->enter(2);
        syncNeeded = false;
        syncBarrier->enter(2);
        std::cout << "(4a) post-sync ==============================================\n";
        printOSGInstances("createThread: ");

        OSG::SimpleTexturedMaterialRecPtr mat = OSG::SimpleTexturedMaterial::create();
        OSG::ImageRecPtr img = OSG::Image::create();
        mat->setImage(img);
        
        std::cout << "(4 post STM create) ==============================================\n";
        printOSGInstances("createThread: ");

        OSG::MaterialGroupRecPtr mat_grp = OSG::MaterialGroup::create();
        mat_grp->setMaterial(mat);

        std::cout << "(4 post MG create) ==============================================\n";
        printOSGInstances("createThread: ");

        node->setCore(mat_grp);

        OSG::commitChanges();

        std::cout << "(4b) pre-sync  ==============================================\n";
        printOSGInstances("createThread: ");
        syncNeeded = true;
        syncBarrier->enter(2);
        syncNeeded = false;
        syncBarrier->enter(2);
        std::cout << "(4b) post-sync ==============================================\n";
        printOSGInstances("createThread: ");
    }

    OSG::commitChanges();

    syncNeeded = true;
    std::cout << "(4c) pre-sync  ==============================================\n";
    printOSGInstances("createThread: ");
    syncBarrier->enter(2);
    syncNeeded = false;
    syncBarrier->enter(2);
    std::cout << "(4c) post-sync ==============================================\n";
    printOSGInstances("createThread: ");

    syncNeeded = true;
    std::cout << "(4d) pre-sync  ==============================================\n";
    printOSGInstances("createThread: ");
    syncBarrier->enter(2);
    syncNeeded = false;
    syncBarrier->enter(2);
    std::cout << "(4d) post-sync ==============================================\n";
    printOSGInstances("createThread: ");
#endif
}


int main(int argc, char *argv[])
{
    OSG::osgInit(argc, argv);

    int winid = setupGLUT(&argc, argv);
    OSG::GLUTWindowRecPtr gwin = OSG::GLUTWindow::create();

    gwin->setGlutId(winid);
    gwin->init();

    scene = createScenegraph();

    mgr = new OSG::SimpleSceneManager;
    mgr->setWindow(gwin );
    mgr->setRoot (scene);
    mgr->setStatistics(true);
    mgr->showAll();

    syncBarrier = OSG::Barrier::get("syncBarrier1");
    renderThread = dynamic_cast<OSG::Thread *>(OSG::ThreadManager::getAppThread());
    syncNeeded = false;

    // start the threads
    creationThread = dynamic_cast<OSG::Thread *>(OSG::ThreadManager::the()->getThread("creationThread"));
    creationThread->runFunction(create, 1, NULL);
       
    OSG::commitChanges();

    // wait for the creation threads to sync over changes
    syncBarrier->enter(2);
    syncBarrier->enter(2);

    // clear changes - they are synced to aspect 1 now
    OSG::Thread::getCurrentChangeList()->clear();

    fcStoreInitialSize = OSG::FieldContainerFactory::the()->getNumContainers();

    mgr->getCamera()->setNear( 0.5 );
    mgr->getCamera()->setFar( 15000 );

    OSG::commitChanges();
    
    glutMainLoop();

    return 0;
}

void display(void)
{
    // check thread for available changes
    if(syncNeeded == true)
    {
        syncBarrier->enter(2);
        printOSGInstances("renderThread: pre sync: ");
        creationThread->getChangeList()->applyAndClear();
        printOSGInstances("renderThread: post sync: ");
        syncBarrier->enter(2);
    }

    mgr->redraw();

    OSG::commitChanges();
    renderThread->getChangeList()->clear();
}


void reshape(int w, int h)
{
    mgr->resize(w, h);
    glutPostRedisplay();
}

void mouse(int button, int state, int x, int y)
{
    if (state)
        mgr->mouseButtonRelease(button, x, y);
    else
        mgr->mouseButtonPress(button, x, y);

    glutPostRedisplay();
}

void motion(int x, int y)
{
    mgr->mouseMove(x, y);
    glutPostRedisplay();
}

int setupGLUT(int *argc, char *argv[])
{
    glutInit(argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);

    int winid = glutCreateWindow("OpenSG Multithreading Test");

    glutDisplayFunc(display);
    glutMouseFunc(mouse);
    glutMotionFunc(motion);
    glutReshapeFunc(reshape);
    glutIdleFunc(display);

    return winid;
}
------------------------------------------------------------------------------
Crystal Reports - New Free Runtime and 30 Day Trial
Check out the new simplified licensing option that enables unlimited
royalty-free distribution of the report engine for externally facing 
server and web deployment.
http://p.sf.net/sfu/businessobjects
_______________________________________________
Opensg-core mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensg-core

Reply via email to