Hi,

I have a problem with reference counting when using threads. Either my 
program crashes or leaks memory.

3 situations (see code below in create(...)):
(1)     Everything works like expected, node and geometry are deleted 
correctly, no problem here.

(2)     Similar to (1), but I add a property to the geometry, but the 
program crashes during the last printOSGInstances() call
        error message: access violation in 
DynamicLoad.exe!osg::AttachmentContainerPtr::dcast<osg::FieldContainerPtr>(osg::FieldContainerPtr
 
oIn={...})  Zeile 56 + 0x4e Bytes

(3)     Assume the printOSGInstances() function is wrong, I tried utilize 
the task manager to see if there are any memory leaks, and the memory 
usage grows steady up and never get freed.

What am I doing wrong?
When I run the code in a single thread application, everything works fine. 
I use OpenSG 1.8 (debug and optimized) under Windows and VS 2005.

Thanks!
Marc



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

OSG_USING_NAMESPACE

SimpleSceneManager *mgr;
NodePtr scene;
Thread* renderThread;
Thread* creationThread;
Barrier* syncBarrier;
bool syncNeeded;

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

unsigned int fcStoreSize = 0;

void printOSGInstances()
{
        const std::vector<FieldContainerPtr> &fcs = 
                *FieldContainerFactory::the()->getFieldContainerStore();
        std::cout << "FieldContainerStore size: " << fcs.size() << 
std::endl;

        int notNull = 0;
        for(unsigned int i=fcStoreSize;i<fcs.size();++i)
        {
                FieldContainerPtr fc = fcs[i];
                if(fc != NullFC)
                {
                        notNull++;
                        AttachmentContainerPtr ac = 
AttachmentContainerPtr::dcast(fc);
                        if ( ac == NullFC )
                        {
                                AttachmentPtr a = AttachmentPtr::dcast( fc 
);
                                if ( a != NullFC )
                                {
                                        FieldContainerPtr dad = NullFC;

                                        if ( a->getParents().size() > 0 )
                                        {
                                                dad = 
a->getParents().getValue(0);
                                        }

                                        ac = 
AttachmentContainerPtr::dcast(dad);
                                }
                        }

                        const osg::Char8 * name = OSG::getName( ac );

                        if (  name != NULL )
                        {
                                printf( "Detected live FC %s (%s) %p 
refcount %d!\n", 
                                        fc->getTypeName(), name, 
fc.getCPtr(), fc.getRefCount());
                        }
                        else
                        {
                                printf( "Detected live FC %s %p refcount 
%d!\n", 
                                        fc->getTypeName(), fc.getCPtr(), 
fc.getRefCount() );
                        }

                        SHLChunkPtr shader = SHLChunkPtr::dcast( fc );
                        if (shader!=NullFC)
                        {
                                printf( "-- vertex program: %s\n", 
                                        shader->getVertexProgram().c_str() 
);
                                printf( "-- fragment program: %s\n", 
 shader->getFragmentProgram().c_str() );
                        }
                }
        }

        printf( "%d out of %d FC's are not destroyed\n", notNull, 
                fcs.size()-fcStoreSize );
}

NodePtr createScenegraph()
{
        NodePtr n = Node::create();
        beginEditCP(n);
        n->setCore(Group::create());
        endEditCP(n);

        return n;
}


// executed by each geometry creation thread
void create(void *args)
{
        osg::FieldContainerPtr pProto = 
osg::Geometry::getClassType().getPrototype();
        osg::GeometryPtr pGeoProto = osg::GeometryPtr::dcast(pProto);

        if(pGeoProto != NullFC)
        {
                pGeoProto->setIgnoreGLForAspect(osg::Thread::getAspect());
        }

        pProto = osg::TextureChunk::getClassType().getPrototype();
        osg::TextureChunkPtr pTexChunkProto = 
osg::TextureChunkPtr::dcast(pProto);

        if(pTexChunkProto != NullFC)
        {
 pTexChunkProto->setIgnoreGLForAspect(osg::Thread::getAspect());
        }

        syncBarrier->enter(2);
        renderThread->getChangeList()->apply();
        syncBarrier->enter(2);

        // (1)
        {
                NodeRefPtr node = NodeRefPtr(Node::create());
                printOSGInstances();
                syncNeeded = true;
                syncBarrier->enter(2);
                syncNeeded = false;
                syncBarrier->enter(2);
                printOSGInstances();

                GeometryPtr geo = Geometry::create();
                beginEditCP(node);
                node->setCore(geo);
                endEditCP(node);

                printOSGInstances();
                syncNeeded = true;
                syncBarrier->enter(2);
                syncNeeded = false;
                syncBarrier->enter(2);
                printOSGInstances();
        }
        printOSGInstances();
        syncNeeded = true;
        syncBarrier->enter(2);
        syncNeeded = false;
        syncBarrier->enter(2);
        printOSGInstances();

        // (2)
        {
                NodeRefPtr node = NodeRefPtr(Node::create());
                printOSGInstances();
                syncNeeded = true;
                syncBarrier->enter(2);
                syncNeeded = false;
                syncBarrier->enter(2);
                printOSGInstances();

                GeometryPtr geo = Geometry::create();
                beginEditCP(geo);
                geo->setPositions(GeoPositions3f::create());
                endEditCP(geo);
                beginEditCP(node);
                node->setCore(geo);
                endEditCP(node);

                printOSGInstances();
                syncNeeded = true;
                syncBarrier->enter(2);
                syncNeeded = false;
                syncBarrier->enter(2);
                printOSGInstances();
        }
        printOSGInstances();
        syncNeeded = true;
        syncBarrier->enter(2);
        syncNeeded = false;
        syncBarrier->enter(2);
        printOSGInstances(); // crash here!

        // (3)
        for (unsigned int i=0; i<1000; i++)
        {
                NodeRefPtr node = NodeRefPtr(Node::create());
                syncNeeded = true;
                syncBarrier->enter(2);
                syncNeeded = false;
                syncBarrier->enter(2);

                beginEditCP(node);
                node->setCore(makeBoxGeo(20, 20, 20, 20, 20, 20));
                endEditCP(node);

                syncNeeded = true;
                syncBarrier->enter(2);
                syncNeeded = false;
                syncBarrier->enter(2);
        }
        syncNeeded = true;
        syncBarrier->enter(2);
        syncNeeded = false;
        syncBarrier->enter(2);
}


int main(int argc, char *argv[])
{
#if OSG_MINOR_VERSION > 2
        ChangeList::setReadWriteDefault();
#endif
        osgInit(argc, argv);

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

        beginEditCP(gwin);
        gwin->setId(winid);
        endEditCP(gwin);

        gwin->init();

        scene = createScenegraph();

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

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

        // start the threads
        creationThread = dynamic_cast<Thread 
*>(ThreadManager::the()->getThread("creationThread"));
        creationThread->runFunction(create, 1, NULL);
 
        // wait for the creation threads to sync over changes
        syncBarrier->enter(2);
        syncBarrier->enter(2);

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

        fcStoreSize = 
FieldContainerFactory::the()->getFieldContainerStore()->size();

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

        glutMainLoop();

        return 0;
}

void display(void)
{
        // check thread for available changes
        if(syncNeeded == true)
        {
                syncBarrier->enter(2);
                creationThread->getChangeList()->applyAndClear();
                syncBarrier->enter(2);
        }

        mgr->redraw();
        renderThread->getChangeList()->clearAll();
}


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;
}
------------------------------------------------------------------------------
OpenSolaris 2009.06 is a cutting edge operating system for enterprises 
looking to deploy the next generation of Solaris that includes the latest 
innovations from Sun and the OpenSource community. Download a copy and 
enjoy capabilities such as Networking, Storage and Virtualization. 
Go to: http://p.sf.net/sfu/opensolaris-get
_______________________________________________
Opensg-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensg-users

Reply via email to