-
-
Notifications
You must be signed in to change notification settings - Fork 955
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
OgreTerrainGroup thread safety regarding Terrain creation #587
Conversation
This change also kind of makes |
I am not very familiar with the Terrain component API. Is |
if (it != mTerrainLoadRequests.end()) | ||
{ | ||
// We would like to abort the request here but WorkQueue does not provide proper tools for this | ||
// (the data we need will be destroyed if we call abortRequest()). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
which data are you referring to here? As far as I can see abortRequest()
will only delete ResourceRequest::loadParams
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are probably referring to the TerrainSlot*
. Would calling abortRequest() and immediately deleting it here work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're correct that the problem is TerrainSlot*
. It can't be deleted however since Terrain*
would also be deleted and that is used in the thread. If WorkQueue
provided a method to abort request if it was not being processed right now it would be fine. That way we would have tools to abort all other requests except the one that's currently being processed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WorkQueue
has function abortPendingRequestsByChannel(uint16 channel)
so if there was function like abortPendingRequest(RequestID id)
as well it could be done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if there was function like abortPendingRequest(RequestID id) as well it could be done.
this will probably be useful for others as well. So I would prefer this solution over the currently proposed workaround.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll make this change but currently I'm a bit busy so it might take a few days.
I think @sinbad meant |
I would not assume that this is intentional. At some point he just made everything virtual (Java style). |
* Added separate function to abort pending requests. * Renamed TerrainLoadRequests to TerrainPrepareRequests. * Removed obsolete LoadRequest::loadingTaskNum.
This should work now. Disappointingly I found out that calling |
Actually there could be at least semi-remedy to this if TerrainGroup had |
freeTerrainSlotInstance(lreq.slot); | ||
return; | ||
} | ||
freeTerrainSlotInstance(lreq.slot); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should be return; after the free here. I'll try if this fixes the neighbour issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok that did not fix the issue, unfortunately.
Making |
👍 from my side. Is this ready to merge? |
Yes this is ready. |
after this merge the "Terrain" sample crashes. Can you reproduce? t == NULL here: ogre/Samples/Terrain/include/Terrain.h Lines 778 to 786 in 12b4b40
|
Yes, it crashes for me too. Instances taken from |
Root::getSingleton().getWorkQueue()->addRequest( | ||
mWorkQueueChannel, WORKQUEUE_LOAD_REQUEST, | ||
Any(req), 0, synchronous); | ||
mTerrainPrepareRequests.insert(TerrainPrepareRequestMap::value_type(slot, id)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the problem line. When synchronous is true it won't go into background thread and there won't be anything in mTerrainPrepareRequests
so it will be deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
local fix:
TerrainPrepareRequestMap::iterator iter =
mTerrainPrepareRequests.insert(TerrainPrepareRequestMap::value_type(slot, 0)).first;
iter->second = Root::getSingleton().getWorkQueue()->addRequest(
mWorkQueueChannel, WORKQUEUE_LOAD_REQUEST, Any(req), 0, synchronous);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can't insert to that iterator at that point anymore since it will be invalid at that point. This is how I'd fix it:
std::pair<TerrainPrepareRequestMap::iterator, bool> ret = mTerrainPrepareRequests.insert(TerrainPrepareRequestMap::value_type(slot, 0));
assert(ret.second == true);
WorkQueue::RequestID id =
Root::getSingleton().getWorkQueue()->addRequest(
mWorkQueueChannel, WORKQUEUE_LOAD_REQUEST,
Any(req), 0, synchronous);
if (!synchronous)
ret.first->second = id;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok this fix stops Terrain
sample from crashing at start.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah.. yes.. I figured. seems to be properly fixed this way
inserting in mTerrainPrepareRequests after doing a synchronous request is too late. But even when fixing this, the sample crashes on shutdown. Please investigate. |
What is the proper way to merge that change as well? I pushed it to the same branch that you've already merged. |
you have to create a new pull-request using the same branch. |
TerrainGroup will use Terrain instance inside thread but allows destroying it while it's being processed in the thread.