News:

As usual while waiting for the next release - don't forget to check the nightly builds in the forum.

Main Menu

potential dead lock pattern in CC?

Started by ollydbg, October 01, 2014, 12:53:21 PM

Previous topic - Next topic

ollydbg

Dead lock sometimes happens, I guess it is in CC.
I try to find some pattern which are the answers describe in What are common reasons for deadlocks?


void cbThreadPool::AddTask(cbThreadedTask *task, bool autodelete)
{
 if (!task)
   return;

 wxMutexLocker lock(m_Mutex);

 m_tasksQueue.push_back(cbThreadedTaskElement(task, autodelete));
 m_taskAdded = true;

 // we are in batch mode, so no need to awake the idle thread
 // m_workingThreads < m_concurrentThreads means there are some threads in idle mode (no task assigned)
 if (!m_batching && m_workingThreads < m_concurrentThreads)
   AwakeNeeded();
}


In main thread:
In void Parser::OnBatchTimer(cb_unused wxTimerEvent& event)

   bool send_event          = true;
   bool sendStartParseEvent = false;
   if (   !m_BatchParseFiles.empty()
       || !m_PredefinedMacros.IsEmpty() )
   {
       CC_LOCKER_TRACK_P_MTX_LOCK(ParserCommon::s_ParserMutex)

       ParserThreadedTask* thread = new ParserThreadedTask(this, ParserCommon::s_ParserMutex);
       TRACE(_T("Parser::OnBatchTimer(): Adding a ParserThreadedTask thread to m_Pool."));
       m_Pool.AddTask(thread, true); //once this function is called, the thread will be executed from the pool.

       if (ParserCommon::s_CurrentParser)
           send_event = false;
       else // Have not done any batch parsing yet -> assign parser
       {
           ParserCommon::s_CurrentParser = this;
           m_StopWatch.Start(); // reset timer
           sendStartParseEvent = true;
       }

       CC_LOCKER_TRACK_P_MTX_UNLOCK(ParserCommon::s_ParserMutex)
   }


Or

bool Parser::Done()
{
   CC_LOCKER_TRACK_P_MTX_LOCK(ParserCommon::s_ParserMutex)

   bool done = m_BatchParseFiles.empty()
               && m_PredefinedMacros.IsEmpty()
               && !m_NeedMarkFileAsLocal
               && m_Pool.Done();

   CC_LOCKER_TRACK_P_MTX_UNLOCK(ParserCommon::s_ParserMutex)

   return done;
}


In worker thread:
int ParserThreadedTask::Execute()

   CC_LOCKER_TRACK_P_MTX_UNLOCK(m_ParserMutex);

   if (m_Parser->m_IgnoreThreadEvents)
       m_Parser->m_IsFirstBatch = true;

   TRACE(_T("ParserThreadedTask::Execute(): Parse source files"));
   while (!batchFiles.empty())
   {
       TRACE(_T("-ParserThreadedTask::Execute(): Parse %s"), batchFiles.front().wx_str());
       m_Parser->Parse(batchFiles.front()); // bool isLocal = true, bool locked = false
       batchFiles.pop_front();
   }

   CC_LOCKER_TRACK_P_MTX_LOCK(m_ParserMutex)


All the patterns are:

lock the parser mutex
lock the pool
release the pool
release the parser mutex


Is it the bad code pattern which may cause dead lock?

EDIT
: It looks like the answer is NO. ;)

If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.