Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Потоки WinApi и GCC, Обуздание потоков 
:(
    Опции темы
NYX
Дата 13.7.2012, 21:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 165
Регистрация: 9.1.2007
Где: Россия, Москва

Репутация: нет
Всего: нет



Всем привет! Код
Код

// Внешние включения
#include <cstdio>
#include <string>
using std::string;
#include <windows.h>

// Библиотечные включения
// ...

/********************************************************************/
// Эксперементальный код

class Threaded {
public:

    Threaded(string String) {
        _T_Argument = String;
        _TreadCompleted = false;
        DWORD ThreadID = 0;
        HANDLE ThreadHandle = CreateThread(NULL, 0, _Thread, this, 0, &ThreadID);
    }
    
    ~Threaded() {
        // Здесь можно поставить коунтер, одна итерация которого будет равна 1 микросекунде. И если
        // каунтер > X принудительно завершать поток. Так же вдовесок использовать флаг, который
        // предварительно оценке каунтера попробует завершить поток изнутри (с учетом непопадания
        // в такт, поток может не завершиться и продолжать чота делать. В таком случае, оценка каунтера
        // может 100% гарантировать нормальность в условии что приложение уже счас вот закроется, и
        // ждет только вот этот или несколько подобных потоков с фразой: "ну давай уже хоть как то отрубайся"
        while(!_TreadCompleted)
            Sleep(1);
        Sleep(100);
    }
    
private:

    bool _TreadCompleted;
    
    string _T_Argument;
    
    static DWORD WINAPI _Thread(LPVOID Argument) {
        Threaded *Parent = reinterpret_cast<Threaded*>(Argument);
        for (unsigned int Index = 0; Index < Parent->_T_Argument.length(); Index++)
            printf("%c", Parent->_T_Argument[Index]);
        printf("\n");
        Parent->_TreadCompleted = true;
        return 0;
    }
};

/********************************************************************/
int main(int argc, char** argv) {
    Threaded Thread1("Thread 1");
    printf("Thread 1 completed\n");
    Threaded Thread2("Thread 2");
    printf("Thread 2 completed\n");
    Threaded Thread3("Thread 3");
    printf("Thread 3 completed\n");
    Threaded Thread4("Thread 4");
    printf("Thread 4 completed\n");
    Threaded Thread5("Thread 5");
    printf("Thread 5 completed\n");
    Threaded Thread6("Thread 6");
    printf("Thread 6 completed\n");
    
    return 0;
}


Работает! Но, есть несколько вопросов, ответы на которые в принципе можно найти, капнув в дебаггере, предварительно вкурив в низкий уровень (в котором я очень слаб)... в общем, кому не лень уделить время, буду непомерно отблагодарен   smile 

* Можно ли утверждать, что отмена Sleep в деструкторе класса Threaded не повлечет за собой трудностей? Конкретизирую - после завершения потока, ОС уничтожает все-про-все и может ли в этот "переходный" момент как то пострадать основной поток при условии что он уже завершается или завершился?

* Как я понимаю, статическая функция-член класса является ОБРАЗЦОМ потока, который создает ОС при вызове CreateThread? То есть можно утверждать, что N классов = N потоков?

* как себя поведет класс если создать его экземпляр через new? Много там кошмаров будет?

Небольшое пояснение - зачем мне это? На данный момент есть такая задача: "написать файлер на подобии стека заданий". То есть, некий класс,
который предварительно принимает задания на действия и после вызова Start задания в стеке класса выполняются. Например вот так:
1) QueryRead(&UnsignedInt, sizeof(unsigned int));
2) QueryRead(&AnsiString, &UnsignedInt);
3) QueryStart(&Percent);
где прототип QueryRead позволяет использовать в качестве первого аргумента указатель на данное В которое надо прочитать данное из файла,
в качестве второго аргумента либо размер читаемого данного, либо указатель на значение размера (который может указывать на ранее прочитанное
данное). А так же и QueryRead(???) который может по результату чтения, как то преобразовывать данные и тутже записывать их куда то. И еще-еще
QueryPosition(unsigned long long *Pos, bool Direction)... в общем вот такая увлекательная механика smile Такой класс в данный момент мне жизненно необходим, так как я смогу читать определенные форматы исходя из парсинга ДОКУМЕНТАЦИИ формата. И фактически, разбор например BMP данных можно будет выполнить с помощью какого то простенького описания во внешнем файле smile Для реализации такого класса задумал использовать:

* Стек заданий - размещает через new структурку в которой описывается задание. Стек является порядком заданий.
* Поток, который - "один объект, один поток", являющийся членом-функцией класса.

В итоге должен получится вот такой вот объект, которых можно было бы сделать например штук пять в одной функции и пока выполняются потоки, функция оценивала бы процент выполнения заданий для всех ИЗВЕСТНЫХ пяти потоков + возможно выполняла бы какие то дополнительные расчеты, например обращалась бы к БД блин или чонить типо того.

(?) В будущем, если все это месиво из кода окажется минимально правильным, я смогу сделать что то вроди ПАЗЛА между объектами класса и что то на подобии пула этих объектов потока, что бы как то более-менее контролировать эту массу зомбо-потоков. Реализация на данный момент не интересует, пока что важны исключительно те моменты которые в списке выше smile
Заранево благодарствую всем уделившим время! smile

Это сообщение отредактировал(а) NYX - 13.7.2012, 21:23
--------------------
'long long long' is too long for GC
PM   Вверх
borisbn
Дата 13.7.2012, 22:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Цитата(NYX @  13.7.2012,  21:17 Найти цитируемый пост)
Можно ли утверждать, что отмена Sleep в деструкторе класса Threaded не повлечет за собой трудностей?

Sleep там просто не нужен. Есть Же функции WaitFor...

Цитата(NYX @  13.7.2012,  21:17 Найти цитируемый пост)
То есть можно утверждать, что N классов = N потоков?

т.к. в конструкторе вызывается CreateThread - то, в принципе, можно

Цитата(NYX @  13.7.2012,  21:17 Найти цитируемый пост)
есть, некий класс,
который предварительно принимает задания на действия и после вызова Start задания в стеке класса выполняются

изобретаешь велосипед, ИМХО. Я не очень силён в бусте, но там есть такая штука - asio - судя по тому, что я про неё читал, ты пытаешься сделать её жалкое подобие. Надеюсь boostcoder подключится к обсуждению и более внятно и аргументировано расскажет про азио


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Randajad
Дата 13.7.2012, 23:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 295
Регистрация: 15.3.2012

Репутация: 8
Всего: 8



asio::io_service это называется из буста. Занятная штука, плюс, оно само может использовать столько потоков, сколько вы ему дадите. Довольно удобно. Когда-то давно сталкивался с ней для своих нужд, но уже все потерялось и примеров не приведу. smile

PM MAIL   Вверх
borisbn
Дата 13.7.2012, 23:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Цитата(Randajad @  13.7.2012,  23:10 Найти цитируемый пост)
asio::io_service

ага.... я, конечно, его имел в виду, а не весь asio


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
NYX
Дата 13.7.2012, 23:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 165
Регистрация: 9.1.2007
Где: Россия, Москва

Репутация: нет
Всего: нет



Эт да, велосипед. Но велосипед изобрести хочется smile так, чисто для себя. Всегда побаивался потоков, а счас решил напрямую в лоб с ними бороться. С бустом не знаком, но наслышан про де-факто стандартной библиотеки. А буст на открытом исходнике? И ваще про НИЗЫ потоков в винде где то есть инфомрация? принципиальная схема так-сказать, где не код простого примера с поверхностным описание под кофе, а как бы рассусоливание с максимальным углублением....? Может книга какая есть? У меня под рукой есть Щупак, в бумажном варианте, там как бы мало углублений.

Это сообщение отредактировал(а) NYX - 14.7.2012, 00:51
--------------------
'long long long' is too long for GC
PM   Вверх
boostcoder
Дата 14.7.2012, 00:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(NYX @  13.7.2012,  23:45 Найти цитируемый пост)
буст на открытом исходнике?

разумеется =)

Цитата(NYX @  13.7.2012,  23:45 Найти цитируемый пост)
велосипед изобрести хочется

"ох и не легкая это работа, из болота тащить бегемота" (с)

PM WWW   Вверх
NYX
Дата 14.7.2012, 00:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 165
Регистрация: 9.1.2007
Где: Россия, Москва

Репутация: нет
Всего: нет



C WaitForSingleObject должно быть так?

Код

    ~Threaded() {
        unsigned int i; // Чисто для бестолковой итерации
        while(WaitForSingleObject(ThreadHandle, 1)) // проверяем объект ThreadHandle в течении 1 милисекунды
                                                                                // если не АЛЁ, получаем 00000102L оно же WAIT_TIMEOUT ???
            i--; // бестолковая итерация
    }


или тот же ВаитФор в if с ожиданием напр. 1 секунды и если что либо кроме нуля, то уже валить поток принудительно перед завершением главного процесса? Опять таки, не планируется прежде временное завершение... оно нужно скорее на случай подвишивания главного потока во время выхода из программы. иного случая просто не планируется.
--------------------
'long long long' is too long for GC
PM   Вверх
boostcoder
Дата 14.7.2012, 01:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(NYX @  14.7.2012,  00:51 Найти цитируемый пост)
должно быть так?

зачем гадаешь? в описании же все сказано.

PM WWW   Вверх
Dem_max
Дата 14.7.2012, 07:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1780
Регистрация: 12.4.2007

Репутация: 4
Всего: 39



я бы добавил следующие функции
bool StartThread(сюда передаем указатель на функцию которую нужно выполнять в потоке); запускает поток.
ExitThread(void); // послать сигнал пользовательской функции на завершение потока.
bool Terminate(void); // завершить поток принудительно.
bool WaitForExitThread(int WaitTime); // функция ожидания завершения потока, вызывается после ExitThread();
int GetExitCode(void); // Возвращает код завершения функции потока.
bool IsStarted(void); // проверяет запущен ли поток


--------------------
Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte")
PM MAIL   Вверх
NYX
Дата 15.7.2012, 01:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 165
Регистрация: 9.1.2007
Где: Россия, Москва

Репутация: нет
Всего: нет



А значение для GetExitcodeThread где хранится? Есть какой либо риск потерять возвращаемое данное? Напр. в случае разрушения потока каким либо нежелательным образом? Ну, что нибудь рядовое... бывает? Пока что проблем вроди бы не наблюдается у меня, вызываю взятие результа сразу после того как ВэитФор укажет что поток иссяк smile Это как в деструкторе класса так и в функции Stop (остановка потока принудительным образом через терминэйтТреад с кодом эксита = 0)

Это сообщение отредактировал(а) NYX - 15.7.2012, 01:37
--------------------
'long long long' is too long for GC
PM   Вверх
Dem_max
Дата 15.7.2012, 04:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1780
Регистрация: 12.4.2007

Репутация: 4
Всего: 39



Кстати забыл сказать, крайне не рекомендую создавать поток в конструкторе класса, а то ты можешь в одном классе объявить несколько объектов Threaded, то при создании класса у тебя создадутся несколько нитей(потоков) и будут сразу выполнять действия, хотя эти действия должны допустим выполняться по нажатию кнопки пользователем.


--------------------
Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte")
PM MAIL   Вверх
NYX
Дата 15.7.2012, 14:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 165
Регистрация: 9.1.2007
Где: Россия, Москва

Репутация: нет
Всего: нет



А если создавать в конструкторе в замороженном состоянии и размораживать поток по вызову Start например? В таком случае, выполнение потока будет более резвым, нежели "пока создастся, пока туда-сюда...". А как бы подготовить поток к запуску... и сам запуск делать только по принуждению? Я принципе на данный момент я так и реализовал. Кстати, столкнулся с некой траблой...  не буду погружать в глубины, возник только один вопрос. Деструктор, он же может в своем теле использовать данные-методы-функции своего класса? Просто у меня такая фишка... в деструкторе оттягивается уничтожение объекта само собой до момента пока поток рабочий (жив или заморожен).... но в конструкторе поток заморожен, и если не вызвать Start, прога само собой виснет в ожидании завершения потока. Я в деструкторе повесил Start если поток не запущен (проверяется флаг, состояние которого выставляется в самом потоке) и если флаг false, то он ставится в true вызывается Start и сам поток в момент УСТАНОВКИ флага так же проверяет его состояние и если он ранее установлен в true то поток сразу же завершается. Если false, то ставит true и продолжает выполнение с подвызовом. Это предотвращает выполнение подвызова потока - та самая юзерская функция которая вызывается объектом-потока. В общем механизм вроди бы рабочий, однако Start не срабатывает O_O я вот думаю, может в деструкторе дело? ОллиДбг показывает что поток в момент деструктора еще заморожен и есть.. .не убит. Но пощему то чот не срабатывает.

Это сообщение отредактировал(а) NYX - 15.7.2012, 15:31
--------------------
'long long long' is too long for GC
PM   Вверх
Dem_max
Дата 15.7.2012, 16:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1780
Регистрация: 12.4.2007

Репутация: 4
Всего: 39



Цитата

А если создавать в конструкторе в замороженном состоянии и размораживать поток по вызову Start например? В таком случае, выполнение потока будет более резвым, нежели "пока создастся, пока туда-сюда...". 

собственно так и сделано у Borland

Цитата

В основной программе создайте объект этого потокового класса
 // создаем поток в приостановленном состоянии (true), запущенном (false)

TMyThread *Thr = new TMyThread(true); // в приостановленном 

Если вы заметили, в конструкторе есть параметр bool CreateSuspended, если при создании
 объекта этот параметр имеет значение false, поток сразу - при создании объекта начнет свою работу,
 то есть начнется выполнение кода в методе Execute(), если параметр bool CreateSuspended true, будет создан
 поток в приостановленном состоянии, для запуска потока вам требуется применить методом Resume()
Thr->Resume();


Цитата

Деструктор, он же может в своем теле использовать данные-методы-функции своего класса?

все может использовано что объявлено в классе


Цитата

ОллиДбг показывает что поток в момент деструктора еще заморожен и есть.. .не убит. Но пощему то чот не срабатывает.


Для деструктора:
Проверяй валиден ли хэндл потока, если да посылай сигнал завершения потока, дожидайся заврешение потока по конкретному таймауту, если таймаут истек делай Terminate потока.

Это сообщение отредактировал(а) Dem_max - 15.7.2012, 16:21


--------------------
Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte")
PM MAIL   Вверх
NYX
Дата 15.7.2012, 18:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 165
Регистрация: 9.1.2007
Где: Россия, Москва

Репутация: нет
Всего: нет



Де жути пугают использования TerminateThread, боюсь как бы потом не было таких ошибок... которые непойми откудасыпятся. Начитался ужасов про все виды завершения кроме естественного выхода из потока по завершению. А еще вопрос, вот полчуается как.... если распаралелить и пустить все потоки в разнобой, они ведь будут быстрее выполняться чем если их сонхронизировать? И прирост производительности, навскидку будет невысоким если синхронизировать ВСЕ потоки включая главный?
--------------------
'long long long' is too long for GC
PM   Вверх
Randajad
Дата 15.7.2012, 18:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 295
Регистрация: 15.3.2012

Репутация: 8
Всего: 8



Зависит от частоты синхронизаций. Если они у вас все делать синхронно будут - прироста нет.
Не вижу проблемы для создания потоков. На их создание уходит не такое уж и большое время.

Если использовать std:: или boost::thread, то никаких termitate не нужно.

Это сообщение отредактировал(а) Randajad - 15.7.2012, 18:27
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1018 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.