Как определить находится ли поток в критической секции из самого этого потока? То есть мне нужно знать выполняется ли текущий код в пределах критической секции или нет. Возможно ли это вообще?
Поставить брейк поинт в критическую секцию. Или принтить id(или name) потока в Output, при входе в критическую секцию. Вариантов много.
Мне нужно это сделать из этого самого потока, причем желательно без использования сторонних ресурсов. Ключеваяособенность: Этот код будет исполняться в классе-предке, поэтому он не знает поместил ли наследник этот вызов в критическую секцию или нет. И по этому же он не может при входе в секцию поставить никакую пометку.
Судя по объявлению критической секции в дельфи могу предположить что OwningThread - хэндл потока находящегося внутри секции, LockCount - количество залоченных потоков, а RecursionCount - количество локов текущим потоком Уточни в мсдн
GhostOnline, спасибо, покурю MSDN на эту тему. Но проблема в том, что критическая секция создается в наследнике, и предок о ней просто не знает. Соответственно получить ссылку на _RTL_CRITICAL_SECTION тоже не может. Задолбался уже, весь мозг сломал
Ну заведи в предке абстрактный метод определяющий находится ли поток в КС и возвращающий булевый тип, а в наследнике переопредели его. Тогда в предке можно вызывать его не открывая крит. секцию, делов-то
Я думал над этим. В принципе я могу поступить еще проще - добавить в ThreadInfo еще одно поле. Но я надеялся что есть способ определения вообще без пометок. дебаг-апишка какая или еще что подобное
Зачем так сложно? Судя по задачи, мы можем просто на вход в критическую секцию присвоить некоторому значению Flag значение True, при выходе - False. Если Flag равняется True, - значит поток в критической секции, иначе, - нет. Вот тебе и все решение твоей задачи...
Не выйдет. Возникнет race condition по этой переменной. Лучше попробовать такое решение (напишу псевдокодом, ок? ) Code: // идентификатор критической секции critical_section cs; .... // Здесь какой-то код, работающий с этой критической секцией void Foo() { enter_critical_section(&cs); // do smth leave_critical_section(&cs); } // А здесь - наш код, проверяющий, // занята или свободна ли сейчас критическая секция void Bar() { bool result = try_enter_critical_section(&cs); if(!result) { // В критической секции находится какой-то поток. } else { // Критическая секция была свободна // теперь она занята нашим потоком. leave_critical_section(&cs); } } UPD: Пардон, проглядел вот это: В этом случае ответ простой - пересмотреть архитектуру. Если классу-предку необходимо знать, находится ли данный вызов в критической секции или нет - значит, класс-наследник должен ему эту информацию предоставить: Code: class BaseClass { protected: void Foo() { if(IsInCriticalSection()) printf("In a critical section\n"); else prinft("Not in a critical section\n"); } virtual bool IsInCriticalSection() = 0; } class DerivedClass : BaseClass { public void Bar() { EnterCriticalSection(); // Вызов в критической секции Foo(); LeaveCriticalSection(); // Вызов вне критической секции Foo(); } protected: virtual bool IsInCriticalSection() { return mutexSstate; } private: void EnterCriticalSection() { ASSERT(mutexSstate== false); mutex->enter(); mutexSstate= true; } void LeaveCriticalSection() { ASSERT(mutexSstate== true); mutex->leave(); mutexSstate= false; } CMutex* mutex; bool mutexSstate = false; }
Согласен. Я пропустил пост топикстартера, где он уточнял, что его интересует состояние текущего потока. Из первого поста я решил, что его интересует состояние другого потока. Свой ответ я отредактировал Хотя если такизх вызовов функции может быть несколько одновременно, из разных потоков - эту переменную придется делать thread local.
Ну вы ребята даете Прочитай пост №8, это решение уже предлагалось. Такое решение - первое что приходит в голову обычно. Этим самым эта переменную надо делать глобальной, а ТС же юзает только поля класса как я понял. Т.е. предок ничего не должен знать о наследнике и его крит. секциях, инкапсуляция какбэ.
Немного поясню для чего мне это надо: У предка есть функция GetData, которая пытается получиль значение из некоего источника. При этом в источнике может не быть данных, тогда функция усыпляет текущий поток, то есть фактически вызывающй поток засыпает и остается внутри функции. Затем его можно разбудить (это уже другая история) и он продолжит попытки чтения из источника. Наследники обычно вызывают GetData напрямую и проблем не возникает. Однако однажды мне пришлось сделать вызов из критической секции. При этом если в источнике данных нет, то поток засыпает. А поскольку он находится в критической секции, то все остальные потоки тормозят на входе в нее. Поэтому мне нужно внутри GetData как-то узнавать находится ли этот вызов внутри критической секции, чтобы не усыплять поток
Усыплять поток надо так, что бы он ждал прихода данных в критической секции при этом не блокируя её. Если так то... Code: using System; using System.Diagnostics; using System.Threading; using System.Collections; namespace MonitorCS1 { class MonitorSample { private bool isDataRecived = false; public void FirstThread() { GetData(); } public void SecondThread() { GetData(); } public void GetData() { lock (this) { //try recive data //... //... if (!isDataRecived) { isDataRecived = true; //предположим что Data получена когда мы зайдём в метод второй раз Monitor.Wait(this); //отдаём обект синхронизации, //поток ждёт Pulse не блокируя вход в критическую секцию } else { Monitor.PulseAll(this); // говорим всем потокам которые ждут, что дата получена } // read data } } static void Main(string[] args) { MonitorSample test = new MonitorSample(); Thread tFirst = new Thread(test.FirstThread); Thread tSecond = new Thread(test.SecondThread); tFirst.Start(); tSecond.Start(); test.GetData(); tFirst.Join(); tSecond.Join(); } } }