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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Параллельное выполнение потоков, Debian pthread.h 
:(
    Опции темы
mephis
Дата 7.5.2012, 01:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Здравствуйте. нужно написать программу, которая лезет в БД, проверяет значения в ячейках и запускает таймер (время = значение ячейки) в отдельном потоке. потоки должны выполняться параллельно.
Код

/* 
 * File:   Deamon.h
 * Author: mephis
 *
 * Created on 27 Апрель 2012 г., 10:18
 */

#include <mysql/mysql.h>
#include <vector>
#include "Timer.h"
#include <stdlib.h>
#include <pthread.h>

#ifndef DEAMON_H
#define    DEAMON_H

class Deamon {
public:
    Deamon();
    Deamon(const Deamon& orig);
    virtual ~Deamon();
    bool connectDB(char* host, char* name, char* password, char* database);
    void checkDB();
    void setTimers();
    static void* threadFunction(void* arg);    
private:
    MYSQL *connection;
    MYSQL_RES *result;
    MYSQL_ROW row;
    long time;
    int id;
    int alarm;
    int number;
    std::vector<Timer> curTimer;
};

#endif    /* DEAMON_H */

Код

#include "Deamon.h"

using namespace std;

Deamon::Deamon() {
}

Deamon::Deamon(const Deamon& orig) {
}

Deamon::~Deamon() {
}

bool Deamon::connectDB(char* host, char* name, char* password, char* database){
    this->connection = mysql_init(NULL);
    if(!mysql_real_connect(this->connection, host, name, password, database, 3306, NULL, 0)){
        cout << "MySQL connection fail!" << endl;
    }
    else{
        cout << "MySQL connection success!" << endl;
    }
    
    mysql_query(this->connection, "SELECT * FROM `test timers`");
    this->result = mysql_use_result(this->connection);
    this->number = 0;
    pthread_t myThread[5];
    while ((row = mysql_fetch_row(this->result)) != NULL){
        Timer* tempTimer = new Timer();
        tempTimer->setId(atoi(row[0]));
        tempTimer->setTime(atol(row[1]));
        this->curTimer.push_back(*tempTimer);
        pthread_create(&myThread[this->number-1], NULL, threadFunction, this);
        pthread_join(myThread[this->number-1], NULL);
        this->number++;
    }
    cout << this->curTimer.size();
    return true;
}



void* Deamon::threadFunction(void* arg){
    Deamon* threadDmn = ((Deamon*)(arg));
        threadDmn->curTimer.at(threadDmn->number).startTimer();
}


в таком варианте потоки запускаются и отрабатывают по очереди. если закоментить pthread_join, то таймеры не запускаются. как решить проблему?
PM MAIL   Вверх
boostcoder
Дата 7.5.2012, 10:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


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

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



убери pthread_join() и используй барьер.

Добавлено через 45 секунд
после while()
PM WWW   Вверх
xvr
Дата 7.5.2012, 11:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Передавать в pthread_create this в качестве параметра для создаваемого thread'а - плохая идейя. У вас все thread'ы передерутся за этот this, т.к. нет никакой гарантии, что Deamon::threadFunction прочтет данные оттуда раньше, чем цикл while в Deamon::connectDB их перезапишет для следующего потока.
Во вторых - надеюсь, что вызов threadDmn->curTimer.at(threadDmn->number).startTimer(); блокируется, иначе у вас все запущенные потоки немедленно завершаться, до наступления заданного timeout'а (а если так и задумывалось, то зачем вообще нужны потоки?)

PM MAIL   Вверх
mephis
Дата 7.5.2012, 20:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(boostcoder @ 7.5.2012,  10:26)
убери pthread_join() и используй барьер.

Добавлено @ 10:26
после while()

можно подробнее объяснить, как это нужно делать?
PM MAIL   Вверх
boostcoder
Дата 7.5.2012, 21:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


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

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



гуглить:
pthread_barrier_init()
pthread_barrier_wait()
pthread_barrier_destroy()

PM WWW   Вверх
mephis
Дата 8.5.2012, 09:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Код

#include "Deamon.h"

using namespace std;

Deamon::Deamon() {
}

Deamon::Deamon(const Deamon& orig) {
}

Deamon::~Deamon() {
}

bool Deamon::connectDB(char* host, char* name, char* password, char* database){
    this->connection = mysql_init(NULL);
    if(!mysql_real_connect(this->connection, host, name, password, database, 3306, NULL, 0)){
        cout << "MySQL connection fail!" << endl;
    }
    else{
        cout << "MySQL connection success!" << endl;
    }
    
    mysql_query(this->connection, "SELECT * FROM `test timers`");
    this->result = mysql_use_result(this->connection);
    this->number = 0;
    pthread_t myThread[5];
    pthread_barrier_init(&this->bar, NULL, 5);
    while ((row = mysql_fetch_row(this->result)) != NULL){
        Timer* tempTimer = new Timer();
        tempTimer->setId(atoi(row[0]));
        tempTimer->setTime(atol(row[1]));
        this->curTimer.push_back(*tempTimer);
        pthread_create(&myThread[this->number], NULL, threadFunction, this);
        this->number++;
    }
    pthread_barrier_destroy(&this->bar);
    sleep(10);
}



void* Deamon::threadFunction(void* arg){
    Deamon* threadDmn = ((Deamon*)(arg));
        threadDmn->curTimer.at(threadDmn->number-1).startTimer();
                pthread_barrier_wait(&threadDmn->bar);
}


переделал программу, используя барьеры. в дебаг режиме всё работает как часы, а вот в обычном - проблема. как уже заметил товарищ xvr, у меня number инкрементируется раньше, чем заканчивает выполнение pthread_create, поэтому в последней итерации я выхожу за пределы массива myThread и ловлю сегфолт. посоветуйте, пожалуйста, как эту проблему решить.
PM MAIL   Вверх
boostcoder
Дата 8.5.2012, 13:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


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

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



для начала, pthread_barrier_wait() перемести в Deamon::connectDB() после цикла.
PM WWW   Вверх
mephis
Дата 8.5.2012, 13:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(boostcoder @ 8.5.2012,  13:22)
для начала, pthread_barrier_wait() перемести в Deamon::connectDB() после цикла.

когда я перемещаю его под while(), таймеры вообще не запускаются.

извиняюсь за криворукость, не туда вставлял. работает.

Это сообщение отредактировал(а) mephis - 8.5.2012, 13:42
PM MAIL   Вверх
boostcoder
Дата 8.5.2012, 13:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


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

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



Цитата(mephis @  8.5.2012,  13:35 Найти цитируемый пост)
работает.

ошибка с number тоже пропала?
PM WWW   Вверх
mephis
Дата 8.5.2012, 13:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(boostcoder @ 8.5.2012,  13:47)
Цитата(mephis @  8.5.2012,  13:35 Найти цитируемый пост)
работает.

ошибка с number тоже пропала?

нет.
как я понимаю, пока выполняется pthread_create, происходит инкремент number и в функцию попадает уже увеличенное на 1 значение . я обошел это таким способом:
Код

void* Deamon::threadFunction(void* arg){
    Deamon* threadDmn = ((Deamon*)(arg));
    threadDmn->number--;
    threadDmn->curTimer.at(threadDmn->number).startTimer();
}

но я опасаюсь, что на менее/более быстрых процессорах это всё полетит к чертям и будет путаница. поэтому хочу найти нормальное решение проблемы.
PM MAIL   Вверх
boostcoder
Дата 8.5.2012, 14:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


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

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



что-то не въезжаю...
твой код расщитан на пять потоков. т.е. ты уверен что в БД всегда пять записей?

PM WWW   Вверх
mephis
Дата 8.5.2012, 16:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(boostcoder @ 8.5.2012,  14:45)
что-то не въезжаю...
твой код расщитан на пять потоков. т.е. ты уверен что в БД всегда пять записей?

нет, там могут быть от 1 до 5 записей.
PM MAIL   Вверх
boostcoder
Дата 8.5.2012, 16:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


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

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



т.е. не больше пяти? никогда?

Добавлено через 4 минуты и 21 секунду
а number тебе в какие моменты инкрементировать нужно?
PM WWW   Вверх
mephis
Дата 8.5.2012, 17:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(boostcoder @ 8.5.2012,  16:55)
т.е. не больше пяти? никогда?

честно говоря,  в базе может быть сколько угодно записей и на каждую запись требуется таймер.
но пока я делаю фиксированную длину. поэтому сейчас да - не больше 5.

Добавлено через 50 секунд
Цитата(boostcoder @ 8.5.2012,  16:55)
т.е. не больше пяти? никогда?

Добавлено @ 17:00
а number тебе в какие моменты инкрементировать нужно?

number инкрементировать нужно после того, как отработал pthread_create.
PM MAIL   Вверх
boostcoder
Дата 8.5.2012, 17:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


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

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



Цитата(mephis @  8.5.2012,  17:01 Найти цитируемый пост)
после того, как отработал pthread_create. 

сейчас оно так и есть.

не понимаю, в чем проблема?

PM WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Программирование под Unix/Linux"
xvr
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • Не забывайте пользоваться кнопкой "Код".
  • Вопросы мобильной разработки тут
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к разделу форума. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

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

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


 




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


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

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