I have the following code written in C++/CX:
TaskPool^ TaskPool::Instance::get()
{
// Prevent acquiring the critical section for a static initialization
// after it's been properly initialized.
if (TaskPool::_instance == nullptr) {
static CRITICAL_SECTION section;
CriticalSection lock(§ion);
if (TaskPool::_instance == nullptr) {
_instance = ref new TaskPool();
InitializeCriticalSection(GetCriticalSection());
}
}
return _instance;
}
TaskPool^ TaskPool::_instance;
CRITICAL_SECTION TaskPool::_criticalSection;
void Threading::TaskPool::TaskRun(Concurrency::task<void> & task)
{
Log::LogMessage(this->GetType()->FullName, Level::Debug, "TaskRun [entering]");
EnterCriticalSection(GetCriticalSection());
Log::LogMessage(this->GetType()->FullName, Level::Debug, "TaskRun [entered]");
create_task(task).then([this]() {
Log::LogMessage(this->GetType()->FullName, Level::Debug, "TaskRun [leaving]");
LeaveCriticalSection(GetCriticalSection());
Log::LogMessage(this->GetType()->FullName, Level::Debug, "TaskRun [left]");
});
}
TaskPool
is a task dispatcher that uses a CRITICAL_SECTION
to dispatch concorrent tasks synchronously. I've read here and confirmed in several other places that critical sections are reentrant. However, I'm failing to replicate this behaviour.
Threading.TaskPool <Debug> TaskRun [entering]
Threading.TaskPool <Debug> TaskRun [entered]
Threading.TaskPool <Debug> TaskRun [leaving]
Threading.TaskPool <Debug> TaskRun [left]
Threading.TaskPool <Debug> TaskRun [entering]
Threading.TaskPool <Debug> TaskRun [entering]
As you can see several tasks are being dispatched. However, even though the first task seems to work well, other tasks added to the pool are not being dispatched. For some reason, the critical section is not entered and the thread seems to hang. If the critical sections are recursive, what else could explain this behaviour?