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

Войти
 
  Начало Форум WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  
  Просмотр сообщений
Страниц: 1 ... 113 114 [115] 116 117 ... 140
1711  Qt / Многопоточное программирование, процессы / AtomicData или механизм атомарной операции записи данных : Март 24, 2011, 03:48
Вечер добрый)

Хочу спросить у бывалых в многопоточном программировании совета)
Ситуация следующая:
Имеется один поток, который пишет данные (в некотурую структуру) и есть несколько потоков, которые эти данные читают.
Сами данные представляются в виде класса и ссылка на объект этого класса передаётся пишущему и читающим потокам.
Ясно, что операция записи в общем случае не атомарна и могут возникнуть неприятности если один или более читающих потоков будут считывать даные, одновременно с записью их пишущим потоком.
Использовать mutex тоже не очень рационально, поскольку доступ к данным для чтения будет доступен только одному потоку.

Написать класс, который должен эту проблему решить, но есть сомнения...
Вот сам класс:
Код
C++ (Qt)
#ifndef ATOMICDATA_H
#define ATOMICDATA_H
 
template <class T>
class AtomicData
{
public:
   AtomicData() : m_flag(0) {}
   AtomicData(const T &data) : m_flag(0), m_data(data) {}
   AtomicData(const AtomicData<T> &other) : m_flag(0), m_data(other.get()) {}
   void set(const T &data) {
       while (m_flag) {}
       m_flag = 1;
       m_data = data;
       m_flag = 0;
   }
   T get() const {
       while (m_flag & 1) {}
       m_flag = 2;
       T data = m_data;
       m_flag = 0;
       return data;
   }
private:
   mutable volatile char m_flag;
   T m_data;
   AtomicData<T> &operator=(const AtomicData<T> &);
};
 
#endif // ATOMICDATA_H
 
 
Суть в том, что операция с char - атомарны (на сколько мне известно) и перед тем как считать или записать данные мы взводим соответствующий флаг m_flag.
Значения:
m_flag = 0 - никто не пишет, никто не читает;
m_flag = 1 - кто-то пишет (читать запрещено).
m_flag = 2 - кто-то читает (запись запрещена, читать можно).

примечание: mutable - нужно чтоб метод get() можно было сделать const;
volatile - чтоб компилятор не оптимизировал m_flag.

Собственно вопрос: По фен-шую ли такое решение или есть грабли?

Спасибо за внимание)

P.S. пишу ядро и не хотелось бы завязывать его на сторонних библиотеках, Qt использую для ГУЯ только. 
1712  Qt / Вопросы новичков / Re: Установка Qt с помощью qt-sdk-win-opensource-2010.05 : Март 23, 2011, 23:57
Не make, а
mingw32-make

P.S. Сейчас модно скачивать готовый SDK, а программы собирать из консоли?  Улыбающийся
1713  Разное / Юмор / Re: Даже инопланетяне хотят в Россию : Март 23, 2011, 21:06
Блин, как надоел весь этот дебилизм  Грустный
Особено обидно видеть такое отношение к своей стране - просто Рашка. Пипец, если у нашего народа такое отношение, то скоро все превратимся в стадо овец...

Надо смотреть правильные фильмы. Умели же у нас делать подобные шедевры :
http://www.youtube.com/watch?v=Bq0NAGbrVG8
http://www.youtube.com/watch?v=X8hexpFJebQ&feature=related 
1714  Qt / Вопросы новичков / Re: Отключить отображение консоли на экране. : Март 23, 2011, 19:36
Можно выводить информацию, например в QTextEdit или ещё куда.
Что позволит не только динамически прятать и показывать её (вашу псевдо консоль), но и всё на что фантазии хватит)
1715  Qt / Пользовательский интерфейс (GUI) / Re: Не работают сигналы и слоты : Март 23, 2011, 14:23
У вас должно работать три экшена:
1) openAct
2) exitAct
3) aboutAct

Всё остальное делайте сами)
На Ubuntu действительно все работает, а на Seven x64 нет  Непонимающий
Что за хрень? Улыбающийся

На Семерке даже не запускается констуктор:
Код:
MainWindow::MainWindow(QWidget *parent):QMainWindow(parent)
{
    setupUi(this);
    createActions();
    loadFile ("settings.ini");
 
}
Нет причин, чтобы не работало под виндой.. Вы ничего не напутали случаем?
Очистите весь проект и соберите заново.
1716  Qt / Пользовательский интерфейс (GUI) / Re: Не работают сигналы и слоты : Март 23, 2011, 14:04
У вас должно работать три экшена:
1) openAct
2) exitAct
3) aboutAct

Всё остальное делайте сами)
1717  Qt / Пользовательский интерфейс (GUI) / Re: Не работают сигналы и слоты : Март 23, 2011, 14:01
Подправил слегка ваш проект и всё заработало Подмигивающий
А теперь Вы нам скажите, что вы сделали не так и почему сейчас всё работает?))
Да и сейчас не работает, что я сейчас делаю не так?  Непонимающий
Могу скинуть экзешник...
Да, а у меня работает  Непонимающий
У меня Linux, экзешник не запустится...
Моментик, щас проверю ещё разок.
1718  Qt / Пользовательский интерфейс (GUI) / Re: Не работают сигналы и слоты : Март 23, 2011, 13:42
Ничего удивительного в том, что не работают у вас сигналы)

Подправил слегка ваш проект и всё заработало Подмигивающий

А теперь Вы нам скажите, что вы сделали не так и почему сейчас всё работает?))
1719  Программирование / С/C++ / Re: тип size_t и сравнение указателей : Март 21, 2011, 13:56
Да, хочу добавить вот что:
Запустил Ваш тест в release и в debug версии со следующим изменением кода:
Код
C++ (Qt)
void TestVirtual( const QVector <CBase *> & vec )
{
   QTime begT = QTime::currentTime();
 
       int sum = 0;
       for (int i = 0; i < vec.size(); ++i) {
               CBase * base = vec[i];
               for (size_t j = 0; j < NUM_CALL; ++j)
                       sum += base->typeVirtual(); // Без изменений
       }
 
       int msecs = begT.msecsTo(QTime::currentTime());
   qDebug() << "TestVirtual time(sec): " << (msecs / 1000.0f) << "sum =" << sum;
}
 
void TestNonVirtual( const QVector <CBase *> & vec )
{
   QTime begT = QTime::currentTime();
 
       int sum = 0;
       for (int i = 0; i < vec.size(); ++i) {
               CBase * base = vec[i];
               for (size_t j = 0; j < NUM_CALL; ++j) {
                        sum += base->typeNonVirtual(); // Для сравнения: оставим только вызов не виртуальной функции
               }
       }
 
       int msecs = begT.msecsTo(QTime::currentTime());
   qDebug() << "TestNonVirtual time(sec): " << (msecs / 1000.0f) << "sum =" << sum;
}
 
Посмотрим, для начала, какую ошибку мы допускаем пренебрегая временем вызова не виртуальной функции. Т.е. сейчас мы сравниваем вирт. и не вирт. функции при прочих равных условиях.
Результат (release):
Код
C++ (Qt)
TestVirtual time(sec):  0.673 sum = 157286400
TestNonVirtual time(sec):  0 sum = 157286400
 
А в debug:
Код
C++ (Qt)
TestVirtual time(sec):  1.529 sum = 157286400
TestNonVirtual time(sec):  0.995 sum = 157286400
 
Сравнивая, можно сделать вывод, что оптимизатор не так просто обмануть, во всяком случае на трюк с суммированием он не ведётся))

Теперь запомним это отношение: время вирт.ф / время не вирт. ф. = 1.529/0.995 = 1.54

И запустим в debug Ваш изначальный вариант:
Код
C++ (Qt)
TestVirtual time(sec):  1.696 sum = 157286400
TestNonVirtual time(sec):  5.348 sum = 157286400
 
Теперь, вспоминая, что время TestNonVirtual нужно поделить на два:
t = 5.348/2 = 2.674
и далее его ещё нужно поделить на отношение, которое было найдено выше, т.е. на 1.54:
В результате имеем:
Код
C++ (Qt)
TestVirtual time(sec):  1.696
TestNonVirtual time(sec):  1.736
 
Отношение этих значений есть: 1.736/1.696 =1.02
Что находится в хорошем согласии с моими результатами в debug версии. 
1720  Программирование / С/C++ / Re: тип size_t и сравнение указателей : Март 21, 2011, 12:52
И всё же я считаю, что Ваш тест не совсем чист:
Во-первых, как Вы уже заметили, dynamic_cast в функции TestNonVirtual вызывается дважды.
Во-вторых,
Код
C++ (Qt)
void TestVirtual( const QVector <CBase *> & vec )
{
   QTime begT = QTime::currentTime();
 
       int sum = 0;
       for (int i = 0; i < vec.size(); ++i) {
               CBase * base = vec[i];
               for (size_t j = 0; j < NUM_CALL; ++j)
                       sum += base->typeVirtual(); // Один вызов виртуальной функции
       }
 
       int msecs = begT.msecsTo(QTime::currentTime());
   qDebug() << "TestVirtual time(sec): " << (msecs / 1000.0f) << "sum =" << sum;
}
 
void TestNonVirtual( const QVector <CBase *> & vec )
{
   QTime begT = QTime::currentTime();
 
       int sum = 0;
       for (int i = 0; i < vec.size(); ++i) {
               CBase * base = vec[i];
               for (size_t j = 0; j < NUM_CALL; ++j) {
                       CBaseA * a = dynamic_cast<CBaseA *> (base); // Раз: вызов dynamic_cast
                       if (a)
                               sum += a->typeNonVirtual(); // + Нужно учитывать дополнительное время от вызова обычной функции
                       else {
                               CBaseB * b = dynamic_cast<CBaseB *> (base); // Два: Вызов dynamic_cast
                               if (b)
                                       sum += b->typeNonVirtual(); // Не учитываем добавочное время от этой операции?
                       }
 
               }
       }
 
       int msecs = begT.msecsTo(QTime::currentTime());
   qDebug() << "TestNonVirtual time(sec): " << (msecs / 1000.0f) << "sum =" << sum;
}
 
В функции TestVirtual Виртуальная функция вызывается один (T_v - время вызова виртуальной функции) раз + время на суммирование (T_sum). Всё хорошо.
В функции TestNonVirtual Дважды вызывается dynamic_cast (T_dyn - время вызова) + время вызова не виртуальной функции (T_nv) и + операция суммирования (T_sum).

Я хочу сказать, что нужно сравнивать чистый вызов dynamic_cast и чистый вызов виртуальной функции. Зачем вообще все эти операции суммирования? Оптимизатор можно просто отключить) Например в debug версии.
Кстати, в debug версии мой тест показывает следующие результаты (при трёх запусках):
Код
C++ (Qt)
dynamic_cast:    (1.56, 1.54, 1.54) sec;  <t> = 1.547 sec
virtual_fun:          (1.49, 1.49, 1.48) sec;  <t> = 1.487 sec
 
И получается, что виртуальная функция быстрее dynamic_cast (в данном конкретном случае) в 1.04 раз.
1721  Qt / Вопросы новичков / Re: Сигнал close : Март 20, 2011, 23:05
Ой да ладно вам)) Какая мелочь, подумаешь не написал он этих функций)
Компилятор и нормальная ID + Qt должны в таких ситуациях сами дописывать код)
Живём в 21 веке и до сих пор приходится спрашивать с удивлением на форуме: а что это прога не компилится  Непонимающий
Безобразие, товарищи!

Ну можно и без сарказма, все же я еще новичок
Не, ну Вы так совсем обленитесь)) Надо хоть попытаться поискать ответ самому, прежде чем вопрошать к публике) Смысл тогда во всём?
1722  Программирование / С/C++ / Re: тип size_t и сравнение указателей : Март 20, 2011, 22:41
Цитировать
Ну давайте немного поспорим. Можно покритиковать Ваш кусочек кода?  Улыбающийся Вот прямо "близлежащий"
Ну я исчо учусь)
Потом этот тест я написал на коленках за минут 10 чисто для себя, чтоб потом его нафиг удалить))
У меня ещё техника не доведена до такого автоматизма, чтоб так прям сразу, даже простой тест, писать идеологически правильно))
Логичнее критиковать то, откуда непосредственно ноги растут: libssc)

Цитировать
Так что негусто ни с "уважением к читающему" ни с "архитектурой". Однако вынужден признать: с демагогией - все отлично  Улыбающийся
Я исправлюсь  Улыбающийся  
1723  Программирование / С/C++ / Re: тип size_t и сравнение указателей : Март 20, 2011, 21:33
2 m_ax: попробуй увеличить иерархию наследования и рассматривать динамик-каст самого последнего потомка к самой первой базе.
Не спорю, вполне вероятно, что при этом ситуация может изменится, но мне как то фиолетово)
У меня реально используется обин базовый класс и два наследуемые от него. Раньше я считал, что в моём случае (пример приведённый выше лишь отражает общую картину) dynamic_cast - очень медленная штука по сравнению с вызовом виртуальной функции, однако, как оказалось для беспокойства нет причин и я оставил вариант с dynamic_cast.   
1724  Qt / Вопросы новичков / Re: Сигнал close : Март 20, 2011, 21:18
Ой да ладно вам)) Какая мелочь, подумаешь не написал он этих функций)
Компилятор и нормальная ID + Qt должны в таких ситуациях сами дописывать код)
Живём в 21 веке и до сих пор приходится спрашивать с удивлением на форуме: а что это прога не компилится  Непонимающий
Безобразие, товарищи!
1725  Программирование / С/C++ / Re: тип size_t и сравнение указателей : Март 20, 2011, 20:42
Код
C++ (Qt)
void test_virtual_fun(ListBase &l) {
   Iter it = l.begin();
   for(; it != l.end(); ++it) {
       if ((*it)->type() == TYPE_F) { // Один вызов виртуального метода
           DerivedF *obj = static_cast<DerivedF*>(*it); // Пренебрегаем издержками на вызов static_cast
           obj->myFunc(); // один вызов не виртуального метода!
       }
   }
}
 
На момент вызова myFunc() obj имеет тип DerivedF - значит никто не мешает компилятору вызвать DerivedF::myFunc() явно, минуя виртуальщину. Просто вызывайте (*it)->myFunc, пусть разбирается
Да нет же, myFunc() - не виртуальная функция) Я бы мог её и не писать вообще, результат бы не изменился. И кстати, я не могу вызвать (*it)->muFunc() поскольку класс Base не имеет этого метода.
Идея теста была сравнить что быстрей: dynamic_cast или вызов виртуальной функции.
Conclusions:
Хотя в данном случае dynamic_cast оказался быстрее, забивать голову и тратить время на подобные оптимизации - бредовая идея)
Лучше потратить его (время) на обдумывание архитектуры и рассмотрения возможных вариантов её расширения в будущем)

Код:
4) Спорно/проблематично кто там больше "затуманивает". Часто текст превращается в демонстрацию знания C++ и автор озабочен не содержательной частью а лишь той самой "формальной грамотностью". Продравшись через все навороты обнаруживается, что дела-то "пшик", ф-циональность слаба. А бывает и наоборот
Формальная грамотность, формальная грамотность.. Грамотность при написании кода - это элементарное уважение к читающему код и залог безопасности (не маловажный факт). Понты, по мне - это когда в коде встречаются сплошь и рядом сомнительные хаки и прочие грабли, на которые разве что не наступит (и то сомнительно) сам автор, в то время, как истинная причина всего этого безобразия - плохая архитектура и чрезмерный С-консерватизм.  Улыбающийся     
 
Страниц: 1 ... 113 114 [115] 116 117 ... 140

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