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