Russian Qt Forum
Май 03, 2024, 09:44 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 [2] 3 4 5   Вниз
  Печать  
Автор Тема: Некорректное выполнение  (Прочитано 21521 раз)
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #15 : Ноябрь 25, 2014, 12:48 »

Покажите как "разбуженная мама" наполняет тарелку, я объясню что имею ввиду.
Код
C++ (Qt)
void Mom::fill()
{
   m_plate.setPlums( 100 );
}
 
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #16 : Ноябрь 25, 2014, 12:53 »

Покажите как "разбуженная мама" наполняет тарелку, я объясню что имею ввиду.
Код
C++ (Qt)
void Mom::fill()
{
   m_plate.setPlums( 100 );
}
 
Я просил "разбуженную" и "снова засыпающую" (а не просто рисование методов  Улыбающийся)
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #17 : Ноябрь 25, 2014, 12:56 »

Я просил "разбуженную" и "снова засыпающую" (а не просто рисование методов  Улыбающийся)
Я пока так далеко не думал. Улыбающийся
Жду реакции Alexu007.

Но могу вам сразу сказать, если я правильно понял, к чему вы начали этот разговор, то это не все необходимые мутексы (в тарелке). Понадобятся и другие средства синхронизации.
« Последнее редактирование: Ноябрь 25, 2014, 13:03 от Old » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #18 : Ноябрь 25, 2014, 13:30 »

Жду реакции Alexu007.
Там пареньку в первый раз трудно придется, это ему не goto. Ну посмотрим, может выплывет...

Но могу вам сразу сказать, если я правильно понял, к чему вы начали этот разговор, то это не все необходимые мутексы (в тарелке). Понадобятся и другие средства синхронизации.
А зачем? Это та же очередь, та же схема (Q)WaitCondition, только извлекающий еще может будить,
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #19 : Ноябрь 25, 2014, 13:33 »

А зачем?
Пока не знаю, но детей много и будить они могут толпой, а положить мама должна один раз.

Тут бы вообще хорошо подошел семафор: мама добавляет - дети убавляют, но все равно нужно атомарно проверять количество и звать маму, иначе может получиться так, что child проверил тарелку, там пусто, заснул, мама положила новых слив, он проснулся и давай заново звать маму, а сливы уже на тарелке. Все равно нужно это контролировать.
« Последнее редактирование: Ноябрь 25, 2014, 13:44 от Old » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #20 : Ноябрь 25, 2014, 14:54 »

Тут бы вообще хорошо подошел семафор: мама добавляет - дети убавляют, но все равно нужно атомарно проверять количество и звать маму, иначе может получиться так, что child проверил тарелку, там пусто, заснул, мама положила новых слив, он проснулся и давай заново звать маму, а сливы уже на тарелке. Все равно нужно это контролировать.
Да, хотелось бы напр так
Код
C++ (Qt)
void ChildThread::run( void )
{
while (doEat) {
  childSemaphore.acquire();
  if (!childSemaphore.available())
    mamaSemaphore.release();
}
}
Но так пробьет. "Близок локоть да не укусишь"

А что же так поредели ряды обсуждающих? Судя по др тредам, "многопоточностью" владеют все, а тут какая-то детская задачка со сливами....  Улыбающийся
Записан
Alexu007
Гость
« Ответ #21 : Ноябрь 25, 2014, 18:44 »

Самое простое - зовёт маму тот, кому не хватило сливы. То есть отправляет сигнал маме. Мама наполняет тарелку.

Алгоритм голодных детей детей такой: пробуют взять сливу. Если слив нет - зовут маму. Снова пробуют взять сливу - и так далее.

Алгоритм мамы: получает сигнал - проверяет пуста ли тарелка - если пуста, наполняет - если не пуста, игнорирует сигнал.

У детей получаются бесконечные циклы, останавливать потоки не надо. Только в конце программы. Мама вообще может быть функцией, которая вызывается в слоте, связанном с сигналами голодных детей. Но не очень понятно, где должен быть этот слот, если несколько потоков. Ему тоже свой поток создавать?

Пока ещё не решился начать... сложновато как то.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #22 : Ноябрь 26, 2014, 11:51 »

Самое простое - зовёт маму тот, кому не хватило сливы. То есть отправляет сигнал маме. Мама наполняет тарелку.

Алгоритм голодных детей детей такой: пробуют взять сливу. Если слив нет - зовут маму. Снова пробуют взять сливу - и так далее.

Алгоритм мамы: получает сигнал - проверяет пуста ли тарелка - если пуста, наполняет - если не пуста, игнорирует сигнал.

У детей получаются бесконечные циклы, останавливать потоки не надо. Только в конце программы.
Это (неудачный) план обойтись без всякой синхронизации, просто налепив бесконечные циклы. В итоге 21 нитка молотит по-пустому, вероятно загрузив проц до упора. Др словами куча детей орет на маму которая сбивается с ног  Улыбающийся

В таких задачах всегда имеется ввиду что нитка/поток ожидает пока для нее нет работы. Поэтому то что Вы изложили - не решение.   
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #23 : Ноябрь 26, 2014, 17:37 »

Ладно, реализация на одном мутексе, содержательная часть
Код
C++ (Qt)
void ChildThread::run( void )
{
while (doEat) {
  mutex.lock();
  while (numPlum == 0) {
   condition.wait(&mutex);
   if (!doEat) {
     mutex.unlock();
     return;
   }
  }
  --numPlum;
  if (!numPlum)
   condition.wakeAll(&mutex);
  mutex.unlock();
  // здесь задержка, статистика
}
}
 
void MamaThread::run( void )
{
while (doEat) {
  QMutexLocker lock(&mutex);
  while (numPlum > 0) {
   condition.wat(&mutex);
   if (!doEat) return;
  }
  numPlum = maxPlum;  // const int maxPlum = 100
  condition.wakeAll(&mutex);
}
}
 
void StopEat( void )
{
 doEat = false;
 QMutexLocker lock(&mutex);
 condition.wakeAll();
}
Критикуем, опровергаем - ну или хотя бы задаем вопросы  Улыбающийся
« Последнее редактирование: Ноябрь 27, 2014, 10:11 от Igors » Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #24 : Ноябрь 26, 2014, 17:45 »

Ваша беда в том, что вы целеустремленно стараетесь избегать QMutexLocker.
Правда непонятно почему. Ну и имеете проблемы от которых он избавляет.

Я бы использовал две условных переменных для ребёнка и для мамы, тогда дети не будили бы друг друга криками "Мамаааааа!".
« Последнее редактирование: Ноябрь 26, 2014, 17:49 от Old » Записан
Alexu007
Гость
« Ответ #25 : Ноябрь 26, 2014, 17:50 »

Ну почему? Большую часть времени дети сыты и переваривают сливу. В это время работает таймер или цикл с паузами - для каждого ребёнка свой. Потом слива заканчивается и ребёнок лезет в тарелку за следующей. А если останавливать процессы - то кто будет считать, когда их пора включать?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #26 : Ноябрь 26, 2014, 18:01 »

Ваша беда в том, что вы целеустремленно стараетесь избегать QMutexLocker.
Правда непонятно почему. Ну и имеете проблемы от которых он избавляет.
Да, исправил, спасибо

Я бы использовал две условных переменных для ребёнка и для мамы, тогда дети не будили бы друг друга криками "Мамаааааа!".
Можно и 2 (Ваша реализация?), может еще лучше маму на семафор - дело вкуса. Зато у меня всего 1 мутекс, а "ложные побудки" неопасны (тем более если большинство еще едят свою сливу).   
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #27 : Ноябрь 26, 2014, 18:07 »

Ну почему? Большую часть времени дети сыты и переваривают сливу. В это время работает таймер или цикл с паузами - для каждого ребёнка свой. Потом слива заканчивается и ребёнок лезет в тарелку за следующей. А если останавливать процессы - то кто будет считать, когда их пора включать?
Синхронизация - это, грубо говоря, стоп/останов. Это должно работать железно, без всяких предположений. Напр мама ушилась (встретила др интересного мужчину) на сутки или двое. Все это время 20 детей должны спать на мутексе (а не гавкать сигналами). Ясно?
Записан
Satansoft
Гость
« Ответ #28 : Ноябрь 27, 2014, 02:32 »

Я рад, что мой вопрос повеселил присутствующих и они ударились в концепцию "У каждого свой код", однако с того времени проект переделывался 6 раз и многое переосмыслено, код стал чище и графику с логикой разделил, снова вопрос дня, почему объявление указателя на требуемый класс вызывает ошибку doesn't name of type (про хедер не шутить)

Что я сделал: минимум 10 раз переписал вручную подключение хедера, юзнул после ctrl+click, написал пременную-указатель с заглавной и пробовал пихать в namespace этот класс - всё тщетно...

На вопрос "Почему QThread не юзаю" отвечу, что параллельно пишу этот код и на чистом Qt, и хоть он более послушно выполняется, там так же проблема с объявлением указателя на класс и не ясно как массив тредов формировать, проинформируете?

cannibals.h
Код:
#ifndef CANNIBALS_H
#define CANNIBALS_H
#include "mainwindow.h"
#include <QThread>
#include <thread>
#include <mutex>
#include <time.h>

class Cannibals : public QThread
{
    Q_OBJECT
public:
    explicit Cannibals(QObject *parent = 0);
    void Cooking();
    void Dinner();
    void Dinner_a(int);

private:
    std::thread Cook;
    std::mutex eating;
    int food=10;

signals:
    void NumberChanged(int);

public slots:

};

#endif // CANNIBALS_H

cannibals.cpp
Код:
#include "cannibals.h"
#include "mainwindow.h"
#define M 100

Cannibals::Cannibals(QObject *parent) :
    QThread(parent)
{
}

void Cannibals::Cooking()
{
     food=M;
}

void Cannibals::Dinner_a(int z)
    {
        eating.lock();
        for(int i=0; i<z;i++){
        Dinner();}
        eating.unlock();
    }

void Cannibals::Dinner()
{
    if(food!=0){
    emit NumberChanged(food);
    --food;}
    else
    Cook = std::thread(&Cannibals::Cooking, this);
    Cook.join();

    msleep(rand()%2000);
}

mainwindow.h (косяк в Cannibals *Foo;)
Код:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "cannibals.h"
#include <ui_mainwindow.h>
#include <QMainWindow>
#include <thread>
#define N 20


namespace Ui {
class MainWindow;}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
     Cannibals *Foo;

private slots:
    void on_pushButton_clicked();

private:
    Ui::MainWindow *ui;
    std::thread Cannibal[N];

public slots:
    void OnNumberChanged (int);
};

#endif // MAINWINDOW_H

mainwindow.cpp
Код:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#define N 20
#define M 100
#define P (M/N)

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    connect(Foo,SIGNAL(NumberChanged(int)),this,SLOT(OnNumberChanged(int)));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_clicked()
{

            for(int i=0;i<N;i++)
                    {
                       Cannibal[i] = std::thread(&Cannibals::Dinner_a, Foo, P);
                    }

            for(int i=0;i<N;i++)
            {
             Cannibal[i].join();
            }
}

void MainWindow::OnNumberChanged(int Num)
{
    ui->listWidget->clear();
    ui->pushButton->setEnabled(false);
    ui->listWidget->addItem(QString(Num) + " cannibal ate");
}
« Последнее редактирование: Ноябрь 27, 2014, 03:42 от Satansoft » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #29 : Ноябрь 27, 2014, 11:19 »

снова вопрос дня, почему объявление указателя на требуемый класс вызывает ошибку doesn't name of type (про хедер не шутить)
Выложите проект, тогда посмотрим

однако с того времени проект переделывался 6 раз и многое переосмыслено, код стал чище и графику с логикой разделил,
Видимо переосмысление касалось только UI и/или С++ 11. Что делает Ваш код: запускает 20 ниток, каждая поедает 5 слив и.. завершается. Причем счетчик слив у каждой свой. Но ведь это совсем не то что требовалось.
Записан
Страниц: 1 [2] 3 4 5   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.205 секунд. Запросов: 22.