На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Обратите внимание:
1. Прежде чем начать новую тему или отправить сообщение, убедитесь, что вы не нарушаете правил форума!
2. Обязательно воспользуйтесь поиском. Возможно, Ваш вопрос уже обсуждали. Полезные ссылки приведены ниже.
3. Темы с просьбой выполнить какую-либо работу за автора в этом разделе не обсуждаются.
4. Используйте теги [ code=cpp ] ...текст программы... [ /code ] для выделения текста программы подсветкой.
5. Помните, здесь телепатов нет. Старайтесь формулировать свой вопрос максимально грамотно и чётко: Как правильно задавать вопросы
6. Запрещено отвечать в темы месячной и более давности без веских на то причин.

Полезные ссылки:
user posted image FAQ Сайта (C++) user posted image FAQ Форума user posted image Наши Исходники user posted image Поиск по Разделу user posted image MSDN Library Online (Windows Driver Kit) user posted image Google

Ваше мнение о модераторах: user posted image B.V.
Модераторы: B.V.
Страницы: (4) 1 2 [3] 4  все  ( Перейти к последнему сообщению )  
> Критические секции , крэш
    Не, я про историю их создания. В MSDN явно говорится, что EnterCriticalSection() в доXPёвом окружении может бросить исключение в случае критически малого количества памяти, но не говорится, какого.

    P.S. Однако оно упоминается в InitializeCriticalSection() в подобной же ситуации, и это STATUS_NO_MEMORY. Причём с Висты оно там уже устранено, скорее всего посредством как раз предсозданного ключевого события.
      Цитата Qraizer @
      Ну и в заключение. Нехрен вообще возиться со счётчиками.

      Вот и я об этом.
      Прежде, чем их делать, поинтересуемся ценой вопроса.
      Эта цена - 5 функциональных строк, а именно:
      1. Запуск остановленного процесса
      2. Преобразование ID в строку
      3. Сложение 2-х строк - постоянного имени + ID
      4. Создание именованного объекта синхронизации
      5. Запуск процесса
      ---
      Невыгодно связываться с чем-то ещё. Просто нет необходимости.
        По-твоему, получение hex-значения из командной строки и преобразование в HANDLE сложнее?
          Цитата Qraizer @
          По-твоему, получение hex-значения из командной строки и преобразование в HANDLE сложнее?

          Нет. Но это значение ещё где-то надо брать, в виде общего счётчика.
          А в многопоточном приложении - ещё и общей критической секции для этого счётчика.
          Нет удобства делать классы, объединённые этими статическими членами.
          я бы сделал, если бы иного пути не было.
          Именно этот вариант получается при наличии CREATE_SUSPENDED.
          Всё логично.

          Добавлено
          Цитата Олег М @
          Зачем очереди нужна ссылка на обработчик?

          я хочу, чтобы при удачном добавлении элемента в очередь,
          автоматически возбуждалось событие. Чтобы этой деятельностью
          больше никто не занимался.
            Да какая разница: командная строка или CREATE_SUSPENDED? Кому как удобнее.
            Командная строка тоже может быть забита какими-то параметрами. Тогда можно, конечно, сделать CreateFileMapping+MapViewOfFile (для передачи хендла), но проще ли это?
            Я не понимаю, почему такой негатив к CREATE_SUSPENDED... Что в нём плохого?
              Почему негатив-то? Просто ему не удаётся найти незаменимого применения, от чего от выглядит ненужным.
                Цитата Qraizer @
                Всё это не актуально. Просто любой CREATE_SUSPENDED легко заменяется на WaitFor...() при старте.
                Ты хочешь сказать, на CreateEvent + if (ошибка) + WaitForSingleObject + if (ошибка) ExitThread + висящий event (либо надо придумывать куда ещё CloseHandle засунуть, например, делать счётчик, который будет уменьшаться через atomic-инструкции)?
                Очень удобно, спору нет :)

                Добавлено
                Есть достаточно вещей, которые не являются незаменимыми, но являются более удобными, чем другие.
                  А ты точно меня читал?
                    Цитата Jin X @
                    Да какая разница: командная строка или CREATE_SUSPENDED? Кому как удобнее.
                    Командная строка тоже может быть забита какими-то параметрами. Тогда можно, конечно, сделать CreateFileMapping+MapViewOfFile (для передачи хендла), но проще ли это?
                    Я не понимаю, почему такой негатив к CREATE_SUSPENDED... Что в нём плохого?


                    Тот пример, который привёл ЫукпШ - это пример того, как размазать логику тонким слоем по разным модулям.
                    Единственное для чего может понадобиться CREATE_SUSPENDED - это установить какие-то свойства процесса/потока до его запуска.
                    Причём, в std::thread и pthreads вообще нет возможности создать поток остановленным.
                      Цитата Qraizer @
                      А ты точно меня читал?
                      Ну цитата ж твоя :)
                      А как иначе использовать WaitFor для того, чтобы запустить "дополнительные" потоки после инициализации чего-либо из "главного" потока?
                      Я говорю о необратимой инициализации типа удаления файла, передачи данных по сети. Которая не нужна в случае неудачной инициализации.

                      p.s. Кстати, я ещё забыл добавить в сценарий...
                      Цитата Jin X @
                      CreateEvent + if (ошибка) + WaitForSingleObject + if (ошибка) ExitThread + висящий event
                      обработку ситуации, когда инициализация не удалась...

                      Добавлено
                      Ну или когда нужно стартовать все потоки с idle-приоритетом.
                        Цитата Jin X @
                        А как иначе использовать WaitFor для того, чтобы запустить "дополнительные" потоки после инициализации чего-либо из "главного" потока?
                        Во-первых, зачем запускать поток, который ещё надо будет извне подкрутить? Почему бы не подкрутить до запуска? Во-вторых, если поток должен инициализироваться сам, то аварийный выход – это будет его задача, и выполняться она должна в неспящем состоянии. О чём вообще вопрос?
                        Цитата Jin X @
                        p.s. Кстати, я ещё забыл добавить в сценарий...
                        Тут и там выше я не понял, что это значит. Необходимые события создаются по-любому, и если что-то пошло не так, приложение не может функционировать дальше. Все сторонние инициализации выполняются по старту, до запуска любого потока. О чём вопрос?
                        Цитата Jin X @
                        либо надо придумывать куда ещё CloseHandle засунуть, например, делать счётчик, который будет уменьшаться через atomic-инструкции
                        Все деинициализации выполняются по выходу, после завершения любых потоков. Зачем счётчики? В чём проблема?
                          Qraizer, конкретная задача: запустить 10 потоков с idle приоритетом. Чтобы они сразу были idle. Как это сделать без SUSPEND_THREAD?
                            Пусть каждая делает себе в начале MainThreadProc(), до начала любых полезных действий. Один нормалприорити стэйтмент сложно будет пережить?

                            Добавлено
                            ExpandedWrap disabled
                              // Структура с информацией о потоках
                              struct ThreadInfo
                              {
                                HANDLE hThread[THREAD_COUNT];         // хендлы потоков
                                HANDLE evPause[THREAD_COUNT];         // хендлы событий о паузах
                              };
                               
                              ThreadInfo ioThreads;                   // информация о потоках
                              CRITICAL_SECTION CriticalSection;       // объект критической секции
                              HANDLE events[2];                       // общие события: "поступили данные для обработки" и "сигнал выхода"
                               
                              DWORD WINAPI MainThreadProc(LPVOID lpParam)
                              {
                                int idx = (int)lpParam;               // наш индекс в массивах
                               
                                SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_IDLE);
                               
                                for (;;)
                                {
                                  if (WaitForSingleObject(ioThreads.evPause[idx], INFINITE) == WAIT_FAILED) break; // обработка паузы
                                  if (WaitForMultipleObjects(2, events, FALSE, INFINITE)  == WAIT_OBJECT_0) break; // одно из двух событий
                               
                                  // Выполнение основной процедуры цикла
                                  ioThreadProc[idx]();
                                }
                                ExitThread(WaitForSingleObject(evExit, 0) == 0 ? 0 : 1);
                              }
                               
                              int CreateThreads()
                              {
                                int i;
                               
                                for (i = 0; i < THREAD_COUNT; ++i)
                                {
                                  ioThreads.evPause[i] = CreateEvent (NULL, TRUE, TRUE, NULL);       // событие паузы (signaled == нет паузы)
                                  // старт нитки
                                  if (ioThreads.evPause[i]!= NULL)
                                    ioThreads.hThread[i] = CreateThread(NULL, 0, &MainThreadProc, LPVOID(i), 0, NULL);
                                  if (ioThreads.hThread[i] == NULL)   // по ошибке досрочно прекращаем
                                  {
                                    CloseHandle(ioThreads.evPause[i]);
                                    break;
                                  }
                                }
                                return i;                             // возвращаем количество запущенных ниток
                              }
                               
                              bool FinishThreads(int Wait = FINISH_THREADS_WAIT_TIME, bool Force = FALSE)
                              {
                                SetEvent(evExit);                     // всем выход
                               
                                int result = WaitForMultipleObjects(amount, ioThreads.hThread, TRUE, Wait); // ждём завершения потоков
                               
                                if (result == WAIT_TIMEOUT && Force)  // если послушались за отведённое время И заставляют
                                  for (int i = 0; i < amount; ++i)
                                    if (WaitForSingleObject(ioThreads.hThread[i], 0) == WAIT_TIMEOUT) // проверяем статус ...
                                      TerminateThread(ioThreads.hThread[i], 1);                       // ... и стопаем
                               
                                for (int i = 0; i < amount; ++i)
                                {
                                  CloseHandle(ioThreads.evPause[i]);
                                  CloseHandle(ioThreads.hThread[i]);
                                }
                               
                                return (result == WAIT_OBJECT_0);
                              }
                               
                              void ContinueThread(int idx)
                              {
                                SetEvent(ioThreads.evPause[idx]);
                              }
                               
                              void StopThread(int idx)
                              {
                                ResetEvent(ioThreads.evPause[idx]);
                              }
                               
                              int main()
                              {
                                InitializeCriticalSection(&CriticalSection);
                                evData = CreateEvent(NULL, FALSE,FALSE, NULL);
                                evExit = CreateEvent(NULL, TRUE, FALSE, NULL);
                               
                                // Создание и запуск потоков
                                if (evData == NULL || evExit == NULL) goto quit;
                                events[0] = evExit;
                                events[1] = evData;
                                amount = CreateThreads();
                               
                                /* ... */
                               
                                ForceFinishThreads();
                               
                              quit:
                                CloseHandle(evExit);
                                CloseHandle(evData);
                                DeleteCriticalSection(&CriticalSection);
                              }


                            Добавлено
                            Не проверял. Даже не компилил. :-?
                            Сообщение отредактировано: Qraizer -
                              Qraizer, ok :)
                                Архитектура немного странная. С одной стороны, нитки запускаются для выполнения каких-то действий, которые вроде бы не зависят от того, какая конкретно нитка отреагирует на какое конкретно действие, но с другой – в приложение заложена архитектура пониточного управления. В условиях полной взаимозаменяемости ниток это кажется избыточным. Либо нитки всё-таки каждая с особенностями, но тогда и передача данных на обработку должна быть направленной, либо нет необходимости паузить отдельные конкретные нитки, но возможно есть необходимость сразу все. Тогда достаточно будет одного события evPause, и код будет немного проще.

                                Добавлено
                                P.S. Подправил код. Неверно пауза обрабатывалась.

                                Добавлено
                                P.P.S. Ошибок было... не одна.
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (4) 1 2 [3] 4  все


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0513 ]   [ 17 queries used ]   [ Generated: 28.03.24, 22:03 GMT ]