LINUX.ORG.RU

вопрос к профи


0

2

Добрый день, помогите пожалуйста!

С помощью Qt пишу приложение, со следующей архитектурой:

1)ГУИ-поток; 2)поток обработки №1; 3) поток обработки №2;

все три потока интенсивно ИСПОЛЬЗУЮТ и ИЗМЕНЯЮТ разделяемые переменные, которые представляют собой контейнеры содержащие «сложные» указатели на объекты классов и различные массивы с данными.

вопрос:

где и как объявить разделяемые переменные, чтобы не было ошибок памяти, при конкурирующих потоках?

сам я думаю объявить в ГУИ-потоке, и доступ к ним осуществлять через указатель на главную форму. плюс синхронизация через мьютексы или семафоры.

подскажите грамотное решение для таких случаев, стоит ли разделить приложение на процессы?

сам я думаю объявить в ГУИ-потоке, и доступ к ним осуществлять через указатель на главную форму

Лучше вынеси в отдельный класс, и указатель на инстанс отдай в каждый поток.

no-dashi ★★★★★
()

и доступ к ним осуществлять через указатель на главную форму

Дельфи головного мозга.

Miguel ★★★★★
()

подскажите грамотное решение для таких случаев, стоит ли разделить приложение на процессы?

Нет.

плюс синхронизация через мьютексы или семафоры.

мьютексы

UVV ★★★★★
()

интенсивно ИСПОЛЬЗУЮТ и ИЗМЕНЯЮТ

может даже RW Lock, если несколько параллельных читателей

nerdogeek
()
Ответ на: комментарий от no-dashi

я же этот класс(или указатель на него, если динамически) помещу в public секции класса гуи-формы. получается доступ все равно будет через указатель на гуи-форму, тогда для чего переносить в отдельный класс? для читабельности?

boriska503
() автор топика
Ответ на: комментарий от boriska503

я же этот класс(или указатель на него, если динамически) помещу в public секции класса гуи-формы

У тебя появляется глобальная переменная - экземпляр формы. Глобальные переменные (и static-члены класса как вариант глобальной переменной) это источник 50% всех багов и проблем. Если есть возможность - а у тебя ЕСТЬ возможность, от них надо избавляться, поэтому создай контекст приложения и передавай этот контекст в конструкторы обработчиков нитей, основной формы и т.п.

class AppContext {
    string var1;
    int var2;
}

class MyForm extends Form {
    AppContext ctx;
    public MyForm(AppContext ctx) { super(); context = ctx; }
    public void DoSomething() {
       context.someMethod1();
    }
}

clas MyThreaded extends Runnable {
    AppContext context;
    public MyThreaded(AppContext ctx) { context = ctx; }
    public void Run() {
       context.someMethod2();
    }
}

int main() {
    AppContext ctx = new AppContext();
    (new MyForm(ctx)).show();
    (new Thread(new MyRunnable(ctx))).start();
    (new Thread(new MyRunnable(ctx))).start();
}

Эта методика позволяет отделить логику тредов от формы, превратить приложение в неинтерактивное с околонулевыми затратами, превратить приложение в многоэкземплярное - МНОГО ОДИНАКОВЫХ ФОРМ, ВНЕЗАПНО!!! Например, если твое приложение работает с базой данных, оно в твоей версии будет работать всегда только с одной базой, а в моей - в со сколь угодно большим количеством баз. А нити могут работать вообще без формы. У тебя такого не получится

Ты не первый кто пытается изобрести велосипед с треугольными колесами - может стоит взять круглые колеса, и поступить как тебе советуют более опытные люди?

no-dashi ★★★★★
()

используй mvc или хотя бы observer pattern.

invy ★★★★★
()
Ответ на: комментарий от no-dashi

А не лучше ли будет создать статический объект и брать указатель на инстанс? Если не трудно, прошу объяснить как лучше (чисто для себя).

Sakura
()
Ответ на: комментарий от Sakura

А не лучше ли будет создать статический объект

Это то же самое, что «глобальная переменная объектного типа». Единственное существенно отличие глобальной переменной от static-атрибута - второй проще найти.

class A {
    public static A instance;
    public void doSomething() {}
}
...
A.instance.doSomething();

и чем это отличается от

global A global_a;
...
global_a.doSomething();
???

no-dashi ★★★★★
()
Последнее исправление: no-dashi (всего исправлений: 1)

профи
Qt

anonymous
()

Создавай в куче и используй read-write locks. Технически из какого потока не важно, но обычно стараются разделить гуи от логики программы.

maggotroot
()

где и как объявить разделяемые переменные, чтобы не было ошибок памяти, при конкурирующих потоках?

Очевидно, не использовать разделяемые переменные, а использовать IPC, например, ZeroMQ, у которого есть неплохой биндинг для Qt (nzmqt).

unfo ★★★★★
()

1)ГУИ-поток; 2)поток обработки №1; 3) поток обработки №2;

все три потока интенсивно ИСПОЛЬЗУЮТ и ИЗМЕНЯЮТ разделяемые переменные, которые представляют собой контейнеры содержащие «сложные» указатели на объекты классов и различные массивы с данными.

вопрос:
где и как объявить разделяемые переменные, чтобы не было ошибок памяти, при конкурирующих потоках?

Посмотри на предмет использования паттерна Singleton (Одиночка). Он решит тебе проблему размещения данных. А мьютексы обеспечат синхронизацию переменных/объектов от одновременного доступа из потоков.

oblfan
()
Ответ на: комментарий от oblfan

Посмотри на предмет использования паттерна Singleton (Одиночка). Он решит тебе проблему размещения данных

И добавит проблемы с многопоточностью, если приготовить неправильно.

invy ★★★★★
()
class Data
{
  Mutex mutex_;
  ...
 public:
  void change_prop1(...) {
    MutexLocker m(mutex_);
    ...
  }
  void change_prop2(...) {
    MutexLocker m(mutex_);
    ...
  }
  ...
};

class Thread1;
class Thread2;
class MainWidget
{
  Data data_;
  Thread1 *t1_;
  Thread2 *t2_;
 public:
   MainWidget() 
     :data_(),
     t1_(new Thread1(this, data_)),
     t2_(new Thread2(this, data_)) {}
};

как-то так

nanoolinux ★★★★
()
Ответ на: комментарий от oblfan

singleton это то же самое, что и статический чего-то там. дизейн ущербен по определению.

nanoolinux ★★★★
()

Данные вынести в ОТДЕЛЬНУЮ библиотеку. Никак не связывать с формами и другими визульными объектами. Покрыть тестами :) В качестве хранилища экземпляра - либо синглетон, либо просто глобальная статическая переменная.

vromanov ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.