I am creating a thread from main thread with an dynamic allocated object as an argument. But if we are deleting this dynamic memory allocated object in main thread then how can we find out a object is deleted in created thread.
main thread code :
int CLocalReader::Run()
{
TReaderArgument *readerArg = new TReaderArgument;
readerArg->iFinished = &theFinishedACE;
readerArg->iSelf = this;
#ifdef WIN32
if (ACE_Thread::spawn((ACE_THR_FUNC)LocalReaderFunc, readerArg) == -1)
{
ACE_DEBUG((LM_DEBUG,"Could not start reader\n"));
delete readerArg;
readerArg = NULL;
}
#else
if (ACE_Thread_Manager::instance()->spawn(ACE_THR_FUNC (LocalReaderFunc), readerArg, THR_NEW_LWP | THR_DETACHED) < 0)
{
ACE_DEBUG((LM_DEBUG,"Could not start reader\n"));
delete readerArg;
readerArg = NULL;
}
#endif
return KErrNone;
}
static void *ReaderFunc(void *arg)
{
ASSERT(arg);
ACE_Thread::yield();
ACE_OS::sleep(ACE_Time_Value(0, STARTUP_TIME));
TReaderArgument *rarg = (TReaderArgument *)arg;
CLocalReader *self = static_cast<CLocalReader *>(rarg->iSelf);
int *finished = rarg->iFinished;
while (!(*finished))
{
if( self->GetData() != KErrorNone )
{
ACE_DEBUG((LM_DEBUG, "%D LocalReader : Error receiving data\n"));
}
}
return 0;
}
if in above code , this object is deleted then how we can check in thread function self object is deleted
Use reference counting like in COM. When the main thread is done with the object, it can set a flag "deleted" and release the object. The object will not be deleted yet, because the thread is still holding the reference count. But, the thread can check the flag and release the object if the flag is set. The reference count will drop to 0 and the object will commit suicide by calling delete this;
Related
I wrote a simple function that flushes to a file in a thread, so it does not block the main thread:
void MultiChannelDiskRecordingWav::flush() {
size_t amountToWrite = mWriteCursorFrames*mChannelCount;
for (size_t i = 0; i < amountToWrite; i++) {
tempWriteBuffer[i] = writeBuffer[i];
}
auto flush = [this, capturedWriteCursorFrames = mWriteCursorFrames, capturedChannelCount = mChannelCount](){
{
std::unique_lock<std::mutex>lk{recordingFileMutex};
std::vector<float> floats(tempWriteBuffer, tempWriteBuffer + mWriteCursorFrames*mChannelCount);
recordingFile.Write(floats);
bytesWritten += capturedWriteCursorFrames*capturedChannelCount*sizeof(float);
}
};
flushThread = std::make_unique<std::thread>(flush);
}
I'm getting a crash with these functions in the backtrace:
(_ZSt9terminatev+52)
(_ZNSt6__ndk16threadD1Ev+24)
(_ZN28MultiChannelDiskRecordingWav5flushEv+268)
which translate to
(std::terminate() 52)
(std::__ndk1::thread::~thread() 24)
(MultiChannelDiskRecordingWav::flush() 268)
Why is the thread being deleted? I'm not moving it, I'm creating inside an std::unique_ptr
On this line:
flushThread = std::make_unique<std::thread>(flush);
You are creating a new std::unique_ptr<std::thread> and assigning it to an existing std::unique_ptr<std::thread> named flushThread. When flushThread is assigned to, it will destroy any std::thread that it already holds. It is that existing std::thread that is being destroyed, not the new std::thread that you just created.
When a std::thread object is destroyed, its destructor will call std::terminate() if the thread is joinable(). So, you will have to do something like this to ensure that the existing thread is finished before you create the new thred:
if (flushThread) flushThread->join(); // <-- add this
flushThread = std::make_unique<std::thread>(flush);
I'm creating a Resource Manager for my game engine. Basically it have an unordered_map that stores the path of the resource as key and as value it stores the loaded resource.
This is the code responsible for loading assets.
std::shared_ptr<T> LoadAsset(const String& _path)
{
if (auto asset = m_assets.find(_path); asset != m_assets.end()) {
return std::static_pointer_cast<T>(asset->second);
}
auto asset = std::move(LoadAssetInternal(_path));
if (!asset) {
return nullptr;
}
m_assets[_path] = std::move(asset);
return std::static_pointer_cast<T>(m_assets[_path]);
}
The problem is that when I call the LoadAsset method, the returned shared_ptr variable always has 2 strong ref when I delete the variable holding the resource the ref count goes to 1 and the resource is never freed by the end of the program.
Exemple:
auto tex = LoadAsset<Texture>("Data/Textures/Foo.tga"); // Strong refs = 2
tex = nullptr; // Strong refs = 1 and the loaded Foo.tga is never freed.
Just create a function that runs at the end of your games main loop. Something like this
void PurgeAssets() {
for (auto i = m_assets.begin(); i != m_assets.end();) {
if (i->second.unique()) {
i = m_assets.erase(i);
}
else {
++i;
}
}
}
First, how D create parallel foreach (underlying logic)?
int main(string[] args)
{
int[] arr;
arr.length = 100000000;
/* Why it is working?, it's simple foreach which working with
reference to int from arr, parallel function return ParallelForeach!R
(ParallelForeach!int[]), but I don't know what it is.
Parallel function is part od phobos library, not D builtin function, then what
kind of magic is used for this? */
foreach (ref e;parallel(arr))
{
e = 100;
}
foreach (ref e;parallel(arr))
{
e *= e;
}
return 0;
}
And second, why it is slower then simple foreach?
Finally, If I create my own taskPool (and don't use global taskPool object), program never end. Why?
parallel returns a struct (of type ParallelForeach) that implements the opApply(int delegate(...)) foreach overload.
when called the struct submits a parallel function to the private submitAndExecute which submits the same task to all threads in the pool.
this then does:
scope(failure)
{
// If an exception is thrown, all threads should bail.
atomicStore(shouldContinue, false);
}
while (atomicLoad(shouldContinue))
{
immutable myUnitIndex = atomicOp!"+="(workUnitIndex, 1);
immutable start = workUnitSize * myUnitIndex;
if(start >= len)
{
atomicStore(shouldContinue, false);
break;
}
immutable end = min(len, start + workUnitSize);
foreach(i; start..end)
{
static if(withIndex)
{
if(dg(i, range[i])) foreachErr();
}
else
{
if(dg(range[i])) foreachErr();
}
}
}
where workUnitIndex and shouldContinue are shared variables and dg is the foreach delegate
The reason it is slower is simply because of the overhead required to pass the function to the threads in the pool and atomically accessing the shared variables.
the reason your custom pool doesn't shut down is likely you don't shut down the threadpool with finish
This code runs successfully and MQStruct constructor initialized the values as well, I can see in ExecuteThread function but in TestFunction, I get the garbage values for MQStruct.
I am passing address of struct "&MQStructObj" to _beginthreadex for parameters and This is the problem I guess
struct MQStruct {
MQStruct()
{
pointer=NULL;
serviceName=NULL;
durability=0;
msgType=0;
msgHeader=0;
msgId=NULL;
payload=NULL;
payloadSize=0;
ttl=0;
priority=0;
}
void* pointer;
wchar_t *serviceName;
int durability;
int msgType;
int msgHeader;
wchar_t *msgId;
wchar_t *payload;
int payloadSize;
int ttl;
int priority;
};
int ExecuteThread() {
HANDLE heartBeatThread;
unsigned int hbThreadID;
int result = 0;
MQStruct MQStructObj;
MQStructObj.pointer=this;
heartBeatThread = (HANDLE)_beginthreadex(NULL, 0 , &TestFunction, &MQStructObj, 0/*CREATE_SUSPENDED*/, &hbThreadID);
if ( heartBeatThread == 0 )
{
result = -1;
LogEvent(DEBUG_LOG,0, "Fail to create thread");
}
CloseHandle(heartBeatThread);
return result;
}
You guessed correctly.
You're passing the address of a local variable to your thread-proc-startup, then leaving scope (and destroying the object in the process). References to this object in your thread proc are there-after undefined behavior.
Dynamically allocate one with new and let the thread proc delete it.
MQStructObj is declared on the stack so will go out of scope and potentially be overwritten as soon as ExecuteThread completes.
If you want to use a stack object here, you'll need to add some synchronisation to allow your new thread to copy from MQStructObj before ExecuteThread returns.
Alternatively, normally preferably, you could allocate MQStructObj dynamically and leave the new thread to clean it up at its leisure
MQStruct* MQStructObj = new MQStruct();
MQStructObj->pointer=this;
heartBeatThread = (HANDLE)_beginthreadex(NULL, 0 , &TestFunction, MQStructObj, 0, &hbThreadID);
if ( heartBeatThread == 0 ) { // error
delete MQStructObj;
result = -1;
}
// ownership of MQStructObj transferred to new thread
I have working on multithreaded application I am passing IMAGETHREADINFO structure in thread here nSock is showing garbage value. What is the problem here.pointer to IMAGETHREADINFO is declared as member variable of CServerConnectionMgr class.
typedef struct
{
int nScok;
CServerConnectionMgr* pConMgr;
}IMAGETHREADINFO;
void StartImageThread(SOCKET nSock)
{
stThreadInfo = new IMAGETHREADINFO;
stThreadInfo.pConMgr = this;
stThreadInfo.nScok = nSock;
m_hRecordImageThread = CreateThread ( NULL,0, (LPTHREAD_START_ROUTINE)StreamImageThread,(void*)&stThreadInfo, 0,&m_nRecordImageThreadID);
if ( NULL == m_hRecordImageThread)
{
return;
}
int CServerConnectionMgr::StreamImageThread(void *args)
{
IMAGETHREADINFO *pImageThreadInfo = (IMAGETHREADINFO*)&args;
}
This is variable pImageThreadInfo->nSock showing some garbage value
This pImageThreadInfo->pConMgr is coming correctly
I this is showing wrong value
(void*)&stThreadInfo is a pointer to the stThreadInfo pointer. You likely want to remove the &
And then, also change IMAGETHREADINFO *pImageThreadInfo = (IMAGETHREADINFO*)&args;, remove the &