I get a data structure like this:
struct My_data
{
MyArray<float> points;
MyArray<float> normals;
MyArray<float> uvCoords;
};
This function can be used to free them:
void ClearAlembicData(My_data* myData)
{
myData->points.clear();
myData->normals.clear();
myData->uvCoords.clear();
}
I want to asynchronously clean the myData so that the program will not wait util all the xxx.clear() are done. Here is my actual code:
My_data myData;
myData.point.push_back(point);
myData.nomals.push_back(nomals);
myData.uvCorrds.push_back(uvCorrds);
ClearAlembicData(&myData);
myData.point.push_back(point);
myData.nomals.push_back(nomals);
myData.uvCorrds.push_back(uvCorrds);
Could you show me how to do it in C ? thanks
CodePudding user response:
Depending on the definition of MyArray
, this will either cause undefined behavior or be completely pointless.
If the container is thread-safe, it will block your push_back
while the clear
is being executed in the other thread (making the 'clearing it asynchronously' completely pointless), if it is not, you are introducing a race condition, which might even end up crashing your program, because you would be concurrently manipulating a shared resource. (Not a good idea).
If you still want to do it, here is a way that might work:
- Make 'myData' into a pointer and operate on that.
- Upon wanting to clear, store that pointer in another pointer variable and replace the pointer with
new My_Data
. - Pass the stored pointer to your asynchronous 'free' function.
- Continue to work with your new data structure in the original thread.
This way, you are not working on a shared resource and asynchronous freeing becomes feasible.
As for 'how to', if you've got C 11, something like this would work (Pseudo-Code).
My_data *myData = new My_data();
myData->point.push_back(point);
myData->nomals.push_back(nomals);
myData->uvCorrds.push_back(uvCorrds);
std::thread([=](){ ClearAlembicData(myData); delete myData; }).detach();
myData = new My_data()
myData->point.push_back(point);
myData->nomals.push_back(nomals);
myData->uvCorrds.push_back(uvCorrds);
delete myData;
CodePudding user response:
One of the solutions, implement MyArray::swap(MyArray&)
. Then
void ClearAlembicData(My_data* myData)
{
MyArray<float> old_points;
MyArray<float> old_normal;
MyArray<float> old_coords;
// Fast swap, myData arrays become empty
myData->points.swap(old_points);
myData->normals.clear(old_normals);
myData->uvCoords.clear(old_coords);
// Assumed to be passed to async function
old_points.clear();
old_normals.clear();
old_coords.clear();
}
There is no enough information about MyArray
abilities, such as support of move semantics, a real function clear, thus this is just an idea.
CodePudding user response:
If MyArray
is a wrapper around std::vector
, know that the clear()
operation is O(1) as float
is trivially destructible and the compiler can eliminate the loop that destroys elements individually.
If it is not, consider implementing MyArray.clear()
such that it marks the container as having a non-zero capacity yet zero contents. As stated above, std::vector
accomplishes this by simply setting slots_available = capacity
.