Страниц: 1 [2] 3 4 5
  Печать  
Автор Тема: Работа через USB с FlirOne Gen 2  (Прочитано 4748 раз)
darkelf
QOR.Moderator
*****
Offline Offline

Сообщений: 256


Просмотр профиля
« Ответ #15 : Марта 20, 2017, 03:06:45 pm »

Цитировать
Сорри, не совсем понял, что должен был выкинуть компилятор?

Да очень простую вещь:

bool done=false;

while(1)
{
 if (done==true) break;
}

Компилятор выбросит if (done==true) break; так как он видит, что done не меняется. При этом если done будет volatile, то компилятор эту строчку не выбросит. Либо если этот контроль будет внутри заблокированного мютекса.

Цитировать
По-моему тут есть объяснение почему в обвёртке

Вот, я и написал, что мютекс - это барьер памяти. Это совершенно особая вещь для компилятора.
из того, что было написано по той ссылке - барьерами памяти является любой вызов функции, а то, что при этом pthread_mutex_*(), имхо, это дело десятое. Например Вы можете сделать свои функции обвёртки над мутексами и про то, что это были pthread_mutex_*() узнает только линковщик, а если подгрузить библиотеку динамически dlopen()/dladdr(), то и он не узнает.
Записан
lastcross
Full Member
***
Offline Offline

Сообщений: 224


Просмотр профиля
« Ответ #16 : Марта 20, 2017, 03:07:01 pm »

Цитировать
Вы ограничиваетесь исключительно теми платформами, которые ваш любимый Си++ 11 поддерживают и отчего-то полагаете, что так везде?
Вы пишите на языке С++, компилятор гарантирует выполнение конкретных его стандартов (если не гарантирует - то это like C++, и по каким он правилам играет - разбирайтесь отдельно). Компилятор может "расширять/дополнять" поведение языка, если стандарт в этом направлении ему это не запрещает. Но если запрещает явно или четко прописывает поведение - то компилятор не вправе его нарушать. Иначе он не соответствует стандарту.
Почему я "решил" что так "везде"? Да потому, что стандарт на то и стандарт - чтобы унифицировать и зафиксировать поведение.
 

Цитировать
А как по-вашему компилятор соображает, что переменная внутри .. Пример:
Например так (что собственно и должно быть) - переменная ваша статическая (то есть глобальная). Она не принадлежит ни одному из блоков вызова, а значит может/вправе изменятся извне. Такую переменную он не вправе выкинуть (ИМХО). Ну или приведите обратные доказательства этому.
И да, порядок присвоения/чтения без мютекса не гарантирован - но переменная не будет выброшена.

Цитировать
Ничего там нет про volatile. А знаете почему? Потому что это статья совсем о другом - о memory ordering. При этом volatile на memory ordering не влияет никак (опять же - уверенное ИМХО, хотите убедить в обратном - дайте ссылку).

Цитировать
Так мютекс не просто объект ядра, мютекс реализует вот какой механизм. И вот именно поэтому и не нужен volatile внутри мютекса. И компилятор (а не только ядро) всё это знают.
Возможно я не корректно выразился прошлый раз - да, не только ядро. Но это никак не "улучшает" отношение к volatile.

Цитировать
Но когда вы начнёте писать для микроконтроллеров
В примере (с переменной) нет никакого намека на код для микроконтроллеров. Обсуждать сферического коня в вакууме  неинтересно.

Цитировать
Как это? "ixa – неустойчивый массив целых, причем каждый элемент такого массива считается неустойчивым. "

Тут соглашусь - я не прав, при таком объявлении - да.

Цитировать
Вообще-то, мы с этого и начинали..
Опять же, в этом моменте был я невнимателен - у Вас массив с волатильными данными. Но присваивание - не волатильное.
Записан
da-nie
Full Member
***
Offline Offline

Сообщений: 167



Просмотр профиля
« Ответ #17 : Марта 20, 2017, 03:48:10 pm »

Цитировать
из того, что было написано по той ссылке - барьерами памяти является любой вызов функции, а то, что при этом pthread_mutex_*(), имхо, это дело десятое.

Ну прочтите ж вы ссылку, что я давал! Там написано, какие вообще эти барьеры бывают. Мютекс - это барьер захвата/освобождения.

Цитировать
Например так (что собственно и должно быть) - переменная ваша статическая (то есть глобальная). Она не принадлежит ни одному из блоков вызова, а значит может/вправе изменятся извне. Такую переменную он не вправе выкинуть (ИМХО). Ну или приведите обратные доказательства этому.

А вы откомпилируйте без мютекса на -o3 и гляньте, что будет в асме. Smiley Думаю, компилятор вас удивит.

Цитировать
Ничего там нет про volatile. А знаете почему? Потому что это статья совсем о другом - о memory ordering. При этом volatile на memory ordering не влияет никак (опять же - уверенное ИМХО, хотите убедить в обратном - дайте ссылку).

Во-первых, статью я давал для показа, что из себя представляет мютекс, а не volatile. А во-вторых, Volatile тоже является барьером памяти. Просто вбейте в гугле "volatile барьер памяти" и всё найдётся сразу же.

Например:

Цитировать
В Visual C++ оно имеет следующие свойства:

1) Уберегает volatile-переменную от агрессивной оптимизации компилятора.
Например, в результате оптимизации компилятор мог бы поместить переменную в
регистр, и тогда ее изменения были бы не видны другим потокам (т.к. у каждого
потока свой набор регистров). volatile защищает от этого, заставляя компилятор
каждый раз при обращении к volatile-переменной генерировать чтение и запись в
соответствующую ячейку памяти, даже если это явно невыгодно и связано с
потерей эффективности. Это называется видимость (visiblilty). Форсирование
чтения и запись в память при обращении к volatile-объекту чрезвычайно важно
для одного из пунктов ниже.

2) Ставит барьер компилятора (compiler barrier).
Компилятор не переупорядочивает обращения к volatile-переменным.
В результате, если мы пишем "int volatile a = 100; int volatile b = 200;",
то можем быть уверенными, что в сгенерированном коде запись в "a"
гарантированно будет находиться до записи в "b". Аналогичного эффекта
можно достичь, применяя специальные макросы - _ReadBarrier, _WriteBarrier и
_ReadWriteBarrier. Подчеркну, что это лишь компиляторный барьер, на
уровне CPU все равно возможно переупорядочивание (см. ниже).

3) Чтение и запись в volatile-переменную ставит неполный барьер памяти на
архитектурах IA-32 и AMD64 (acquire and release semantics). Это, так сказать,
небольшой, но приятный побочный эффект volatile, благодаря которому в некоторых
случаях можно обойтись без установки явных барьеров памяти - mfence, xchg и т.п.
Барьеры памяти, если кто не в курсе, нужны, чтобы гарантировать порядок доступа к
памяти на уровне CPU. Например, на упомянутых архитектурах последовательность
операций write-read может быть выполнена, как read-write, и код, который от этого
порядка зависит, может поломаться. Если интересует, могу дать несколько ссылок.

4) Вопреки распостраненному мнению, volatile не обеспечивает атомарности, он
связан лишь с видимостью.
Например, на 32-битных архитектурах доступ к 64-битной переменной не атомарен, и
volatile здесь не помощник.

Цитировать
В примере (с переменной) нет никакого намека на код для микроконтроллеров. Обсуждать сферического коня в вакууме  неинтересно.

Вы можете такой же код запустить под DOS (там прерывания позволяют с собой работать напрямую по-честному) и всё будет то же самое. Впрочем, под QNX тоже можно проверить.

Цитировать
Возможно я не корректно выразился прошлый раз - да, не только ядро. Но это никак не "улучшает" отношение к volatile.

Всё дело в том, что вы ходите по кругу и меняете отношение к volatile кого-то абстрактного, не меня. Smiley Я ведь вам уже объяснил, что да как и с volatile и с мютексом, и отношение к атомарным операциям тоже показал. Так кому вы объясняете вашу нелюбовь к volatile? Мне? Зачем? Я и так абсолютно точно знаю, как этот volatile влияет на результат компиляции и точно также я отлично знаю, что даст atomic и мютекс (я ассемблер x86, конечно, за десятилетия подзабыл, но в целом как работает процессор я понимаю). Поэтому давайте просто забудьте про volatile, пока не столкнётесь с аппаратурой (для записи в память устройств, как верно вспомнил darkelf) или при обработке прерываний без поддержки ОС. Smiley

Новое обновление программы. Smiley
Записан

И день и ночь в пути
lastcross
Full Member
***
Offline Offline

Сообщений: 224


Просмотр профиля
« Ответ #18 : Марта 20, 2017, 05:13:06 pm »

Цитировать
Всё дело в том, что вы ходите по кругу
Цитировать
Volatile тоже является барьером памяти. Просто вбейте в гугле "volatile барьер памяти" и всё найдётся сразу же.

Вбил и впервых трех ссылках вот вам ответ - ЯЗЫК НЕ ГАРАНТИРУЕТ вам никаких барьеров с volatile. Смотрим тут и тут для примера. В вашем компиляторе есть? Поздравляю. Но попробуете пересобрать другим - ваших барьеров может и не быть.

Цитировать
А вы откомпилируйте без мютекса на -o3 и гляньте, что будет в асме. Smiley Думаю, компилятор вас удивит.

Откомпилировал в MSVS2013 с Ox (full optimization) под win8.1 x64 такой код:
Код:
#include "stdafx.h"
#include <iostream>
#include <string>
#include <chrono>
#include <thread>

bool isDone = false;
int Value = 0;


void firstThread()
{
 std::this_thread::sleep_for(std::chrono::seconds(2));
 while (true)
 {
  if (isDone)
  {
   Value = 20;
   break;
  }
 }
}

void secondThread()
{
 std::this_thread::sleep_for(std::chrono::seconds(1));
 isDone = true;
}

int _tmain(int argc, _TCHAR* argv[])
{
 Value = 10;
 std::thread first(firstThread);
 std::thread second(secondThread);
 first.join();
 second.join();

 std::cout << "isDone: " << isDone << std::endl << "Value: " << Value << std::endl;
 return 0;
}


Получил вот такой вывод:
Цитировать
isDone: 1
Value: 20
Что я делаю не так (наблюдения подсказали что переменные не отброшены)? Ассемблер - показывает что проверка и изменение значения присутствуют. Что еще предоставить?)

Цитировать
В Visual C++ оно имеет следующие свойства:
Вот зачем Вы про студию? Ну не надо же было.. А впрочем почитайте на досуге что они сами пишут, чем читать о них от третьих лиц - https://msdn.microsoft.com/ru-ru/library/12a04hfd.aspx
Обратите внимание на настоятельные рекомендации, и то как они по умолчанию работают с volatile (специальные опции для этого у студийного компилятора есть).

Ну и под конец - я не хочу Вас ни в чем разочаровывать. Мне это тоже незачем). Считаете что volatile должен влиять на memory ordering - ну и Бог с Вами!) Мне показалось просто что Вы спрашивали - я же отвечал (подтверждая ссылками).
Я точно знаю что такое поведение не гарантировано, и чтобы обеспечить его я уж лучше буду использовать переносимые, стандартные и гарантированные механизмы нежели "пришитый нитками" к volatile.
Вам же желаю успехов в этом деле!
« Последнее редактирование: Марта 20, 2017, 05:23:21 pm от lastcross » Записан
lastcross
Full Member
***
Offline Offline

Сообщений: 224


Просмотр профиля
« Ответ #19 : Марта 20, 2017, 06:59:41 pm »

Что я делаю не так
Тут отвечу сам - забыл указать инструкции относительно предварительного изменение isDone в secondThread(). Вызов конечно он оптимизирует, проверка на if будет выкинута компилятором. В этом Вы правы, хотя откровенно сказать - я не утверждал обратное. Я почему-то понял что вы настаиваете на исключении всей переменной из кода (с этим готов был поспорить).

Но ок - исключается строчка if, volatile все равно не решит вопрос memory order переносимо при использовании в multithreading (только для конкретных наборов компиляторов, под конкретный набор платформ). А это значит что без принудительного (мютекс и т.д.) барьера - он использование volatile может быть опасно (при смене компилятора или платформы), а с доп. барьером - он как минимум избыточен (и в добавок может влиять на производительность).
« Последнее редактирование: Марта 20, 2017, 07:09:10 pm от lastcross » Записан
da-nie
Full Member
***
Offline Offline

Сообщений: 167



Просмотр профиля
« Ответ #20 : Марта 20, 2017, 07:34:27 pm »

Цитировать
ЯЗЫК НЕ ГАРАНТИРУЕТ

Язык, надо полагать, много чего вам не гарантирует. Те же атомарные операции далеко не на всех процессорах вообще возможны в полном объёме, указанном в Open MP (интересно, как вы атомарно на Z80 сложите два 32 битных числа Smiley ). Но на платформе x86 volatile барьер памяти создаёт. Или вам нужно, чтобы создавал везде и всегда? Ну так подобная категоричность вряд ли уместна. На вашем компьютере volatile создаёт барьер памяти и точка.
И, если не трудно, ссылки на английский не надо - я ведь предупредил, что мои знания английского весьма низкие. Я не понимаю, что там написано и что в комментариях ответили. Тем не менее, как минимум барьер компилятора (я их, вообще говоря, с барьерами памяти не разделяю - на любом процессоре, который умеет переставлять инструкции это практически одно и то же) volatile создаёт. Уж не знаю, написано это в стандарте языка или нет, но любой (почти Smiley AVR GCC, например, этого не знает Smiley ) компилятор точно знает, что порядок volatile нарушать НЕЛЬЗЯ.

Цитировать
Откомпилировал в MSVS2013 с Ox (full optimization) под win8.1 x64 такой код:

Ну, стало быть, так просто нужного эффекта не добиться. Но рано или поздно компилятор выбросит этот блок. Запустил на VC6. Какую оптимизацию не выбирай, код получается вот таким:
Код:
0040101E loc_40101E:                             ; CODE XREF: _WinMain@16+36j
0040101E                 mov     eax, 1
00401023                 test    eax, eax
00401025                 jz      short loc_401038 - while (1)
00401027                 xor     ecx, ecx
00401029                 mov     cl, byte_4054C0 - переменная done
0040102F                 cmp     ecx, 1
00401032                 jnz     short loc_401036
00401034                 jmp     short loc_401038 - на выход
00401036 loc_401036:                             ; CODE XREF: _WinMain@16+32j
00401036                 jmp     short loc_40101E

Это while(1) {if (done==true) break;}
Но вообще говоря, пример, который я привёл, классический. И он 100% рано или поздно сработает. Только нужно попасть в условия, когда компилятор не будет while(1) заменять на запись 1 в регистр, обнуление и сравнение с 0. Так что даже не сомневайтесь, приведённый пример - классика ошибок в ПО при параллельной работе с данными.

Цитировать
Обратите внимание на настоятельные рекомендации, и то как они по умолчанию работают с volatile (специальные опции для этого у студийного компилятора есть).

От того, что не на x86 барьер памяти не нужен, вовсе не следует, что volatile там будет себя вести как-то иначе. Да, он там не будет барьером памяти (если вы на это надеетесь), но барьер компилятора всё равно остаётся. Всё, что по вашей ссылке написано важного, так это ссылка вот на что:
"/volatile:ms ... Семантика получения и освобождения гарантируется при переменном обращении. Однако этот параметр также заставляет компилятор генерировать барьеры памяти оборудования, которые могут добавлять значительную нагрузку на ARM и другие архитектуры со слабым упорядочиванием памяти."

Цитировать
Я точно знаю что такое поведение не гарантировано,

Какое именно поведение? Отсутствие кэширования переменной? Ну так оно как раз гарантировано.

Цитировать
Вам же желаю успехов в этом деле!

Спасибо. Smiley Вам тоже успехов в ваших делах.
« Последнее редактирование: Марта 20, 2017, 07:39:44 pm от da-nie » Записан

И день и ночь в пути
da-nie
Full Member
***
Offline Offline

Сообщений: 167



Просмотр профиля
« Ответ #21 : Марта 20, 2017, 07:38:37 pm »

Цитировать
Тут отвечу сам - забыл указать инструкции относительно предварительного изменение

О! Вам удалось! А мне пока не удалось заставить VC6 это оптимизировать...  Cool (Да, я люблю именно VC6, как ни странно Smiley ). Smiley

Цитировать
использование volatile может быть опасно


Всё верно! Его никто так не использует без атомарности. Просто я на автомате похерил, что мютексу не нужен volatile, вот и вся причина, зачем я его захотел внести во все общие переменные. А потом задумался, почему же я никогда так не делал. И вспомнил, почему. Smiley
Записан

И день и ночь в пути
darkelf
QOR.Moderator
*****
Offline Offline

Сообщений: 256


Просмотр профиля
« Ответ #22 : Марта 20, 2017, 08:32:07 pm »

Цитировать
из того, что было написано по той ссылке - барьерами памяти является любой вызов функции, а то, что при этом pthread_mutex_*(), имхо, это дело десятое.

Ну прочтите ж вы ссылку, что я давал! Там написано, какие вообще эти барьеры бывают. Мютекс - это барьер захвата/освобождения.

Во-первых, статью я давал для показа, что из себя представляет мютекс, а не volatile. А во-вторых, Volatile тоже является барьером памяти. Просто вбейте в гугле "volatile барьер памяти" и всё найдётся сразу же.
Например, тут пишут, что volatile не является барьером памяти. Эта Функциональность, как и сказал lastcross была привязана только в майкрософтовском компиляторе, и очень даже нестандартна.

Вот и в Wikipedia пишут - "The keyword volatile does not guarantee a memory barrier to enforce cache-consistency.". Кстати, для 86 архитектуры пришлось придумывать команду mfence, чтобы гарантировать барьеры памяти на уровне команд, а в компиляторах сначала приходилось обходиться разными asm volatile("" ::: "memory"), а начиная с C11/C++11 - более цивилизовано - функции atomic_signal_fence(memory_order_acq_rel) и atomic_thread_fence(memory_order_acq_rel) - см здесь.

А вызовы функций, думаю любых, командой call, барьером являются, иначе-бы могли происходить такие интересные вещи как вызов функции до вычисления всех входных её аргументов.
« Последнее редактирование: Марта 20, 2017, 11:23:33 pm от darkelf » Записан
da-nie
Full Member
***
Offline Offline

Сообщений: 167



Просмотр профиля
« Ответ #23 : Марта 20, 2017, 09:04:56 pm »

Цитировать
Эта Функциональность, как и сказал lastcross была привязана только в майкрософтовском компиляторе,

Ну, я и не обещал повсеместности. Smiley Вообще говоря, я читал мнение, что volatile как раз обеспечивает привязку аппаратуры к языку - практику к теории. Если Си++ не озаботился жёсткими гарантиями барьера, а без них код конкретного процессора (а x86 имеет для этого море возможностей) может вести себя непредсказуемо, то компилятор будет просто вынужден ставить барьер.
Записан

И день и ночь в пути
lastcross
Full Member
***
Offline Offline

Сообщений: 224


Просмотр профиля
« Ответ #24 : Марта 21, 2017, 02:29:49 pm »

Язык, надо полагать, много чего вам не гарантирует. Те же атомарные операции далеко не на всех процессорах вообще возможны в полном объёме, указанном в Open MP (интересно, как вы атомарно на Z80 сложите два 32 битных числа Smiley ).
Заявление компилятора о поддержке стандарта языка и являются нужными гарантиями. Если у компилятора заявленно поддержка например с++11 в полном объеме и он так же заявил что может собрать под нужную Вам платформу, то использования внутри кода например std::mutex дают Вам полное основания ожидать, что конкретные барьеры памяти будут реализованы внутри исполняемого кода. Потому как это требование языка и компилятор подписался о их поддержке.
Если компилятор не в полной мере поддерживает стандарт (или вообще не поддерживает необходимый для реализации) - вы вправе использовать сторонние библиотеки. Но тогда гарантии возлагаются на библиотеку, которая будет реализовывать необходимый вам функционал. Потому как правило библиотека выпускается с учетом языка/компиляторов/платформ которые будут ее использовать. Пример POSIX-овские thread-ы.

Ну все это очевидно же). Но дело в том что мы обсуждаем volatile - а поведение этого ключевого слова в стандарте не изменялось ну оооочень давно (с 2003 точно, я бы сказал практически неизменно, учитывая что о многопоточности стандарт вообще до ++11 практически ничего не упоминал/гарантировал)

Поэтому, мое лично мнение - вам повезло с компилятором и Ваши ожидания относительно volatile он оправдывает.
Я это все говорю относительно своего опыта. На текущем проекте, который собирается под MSVS2013 в определенном объеме кода раскидано использование volatile. Ну исторически, кто-то решил так "гарантировать" передачу "флага" между потоками. Разумеется студия собирает по умолчанию все это с вставкой барьеров. А при попытке собрать другим компилятором - получаем забавный неуловимый, никому не нужный геморрой времени исполнения.

Цитировать
ссылки на английский не надо

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

Цитировать
Тем не менее, как минимум барьер компилятора volatile создаёт
Обобщенно - компилятор НЕ ОПТИМИЗИРУЕТ переменную/код с модификатором volatile. Барьер вставлять от компилятора никто не требует. Порядок гарантировать от него опять же, никто не требует. А следовательно компилятор МОЖЕТ НЕ вставлять барьер и МОЖЕТ НАРУШАТЬ порядок с волатильностью.

Почему мой ответ имеет "обобщенный" характер - потому как изначально вы спрашивали общее поведение volatile для пользовательских типов. А это жестко прописано в стандарте (использование через volatile методы/наличие своего оператора присваивания и тд). Стандарт жестко в этом ограничивает компилятор (При этом не ограничивает в том как именно это будет реализовано с барьерами или без).
Если обобщенный ответ Вам не интересен - пользуйтесь конкретным поведением конкретного компилятора. А если вдруг решите сменить компилятор - может быть вспомните про "требования" и "гарантии" )


Цитировать
От того, что не на x86 барьер памяти не нужен...

Ох.. Имелось ввиду из ссылки иммено это:
Цитировать
Блок, относящийся к стандарту ISO
Если вы знакомы с ключевым словом C# volatile или разбираетесь в поведении volatile в более ранних версиях Visual C++, вам необходимо учитывать, что в стандарте ISO для языка C++11 ключевое слово volatile отличается. В Visual Studio такое ключевое слово поддерживается, если установлен параметр компилятора /volatile:iso. (Для архитектуры ARM он установлен по умолчанию). Ключевое слово volatile в коде, создаваемом согласно стандарту ISO для языка C ++11, должно использоваться только для аппаратного доступа; его использование для взаимодействия между потоками не допускается. Для взаимодействия между потоками необходимо использовать такие механизмы, как std::atomic<T> из стандартной библиотеки шаблонов C++.

Если Вас интригует что там указано С++11, я могу напрячься и найти за Вас описание и в ранних версиях в стандарте. Но оно будет в оригинале и на английском.

Цитировать
Всё, что по вашей ссылке написано важного, так это ссылка вот на что
А вот это как раз - попытка компилятора "расширить" поведение volatile, так как стандарт не ограничивает его в этом. Любой компилятор может как дополнить любым "разумным" для себя кодом, так и не делать этого вовсе.

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

Цитировать
Какое именно поведение? Отсутствие кэширования переменной? Ну так оно как раз гарантировано.
Гарантии языка относительно "автоматических" барьеров памяти, а следовательно и порядка (а не только кэширование/исключение кода) для volatile. Например для std::mutex - они (гарантии) в стандарте прописаны. Для volatile в языке их нет

« Последнее редактирование: Марта 21, 2017, 02:36:24 pm от lastcross » Записан
da-nie
Full Member
***
Offline Offline

Сообщений: 167



Просмотр профиля
« Ответ #25 : Марта 21, 2017, 03:44:17 pm »

Цитировать
Заявление компилятора о поддержке стандарта языка и являются нужными гарантиями.

На практике мы имеем разные трактовки long double у разных компиляторов (Borland и Microsoft, например), неопределённый char (который то знаковый, то беззнаковый, но чаще всего знаковый), массивы нулевой длины, пустые структуры, которые в Си (их там вообще-то не было, но сделали) имеют sizeof()=0, а в Си++ sizeof()=1 (!), ну и на закуску невозможность строить переносимый код в принципе (даже между Unix-системами - то библиотеки названы иначе, то формат функций другой, то в структурах нет полей, которые есть в исходной системе). Поэтому лучше всё же рассматривать связку компилятор-ОС-процессор и забыть о какой-либо полной переносимости. Всё равно она не достигается.
А уж сколько расширений языка Си в компиляторах (практически в любых), думаю, вы представляете? Интересно, для кого они делаются? Наверное, авторы ждут эти расширения в следующем стандарте? Скажем, макросы с переменным количеством аргументов появились в gcc до принятия C99 и Си++ 11. В общем, если всё это есть, значит, оно кому-то нужно.

Цитировать
Потому как правило библиотека выпускается с учетом языка/компиляторов/платформ которые будут ее использовать. Пример POSIX-овские thread-ы.

Угу. Вот ваш POSIX:
Код:
pthread_attr_t pt_attr;
pthread_attr_init(&pt_attr);
pthread_attr_setdetachstate(&pt_attr,PTHREAD_CREATE_DETACHED);
pthread_attr_setinheritsched(&pt_attr,PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedpolicy(&pt_attr,SCHED_RR);
pt_attr.param.sched_priority=15;  - а вот этого поля в Linux нет.
И на практике мы имеем тот же зоопарк.

Цитировать
Если обобщенный ответ Вам не интересен - пользуйтесь конкретным поведением конкретного компилятора. А если вдруг решите сменить компилятор - может быть вспомните про "требования" и "гарантии" )

Положим, я не использую volatile для задания очерёдности действий. Что касается барьера, ну что ж, раз стандарт его не гарантирует, то подождём, когда начнёт гарантировать. Впрочем, большинство компиляторов на этот случай поддерживают вот что: asm volatile ("" ::: «memory»);

Цитировать
Гарантии языка относительно "автоматических" барьеров памяти, а следовательно и порядка (а не только кэширование/исключение кода) для volatile. Например для std::mutex - они (гарантии) в стандарте прописаны. Для volatile в языке их нет

Ну нет, так нет. Cool Язык вообще несовершенен. Выбирайте тот компилятор, где есть и который точно об этом скажет. Smiley Как я уже выше написал, если есть расширение языка, значит, оно зачем-то нужно, нет?

Что касается правильного использования volatile, я вам его описал в личке ещё вчера.

Кстати, с atomic тоже можно сделать забавные ошибки: https://habrahabr.ru/post/155507/  Smiley
« Последнее редактирование: Марта 21, 2017, 07:11:05 pm от da-nie » Записан

И день и ночь в пути
lastcross
Full Member
***
Offline Offline

Сообщений: 224


Просмотр профиля
« Ответ #26 : Марта 23, 2017, 06:27:49 pm »

На практике мы имеем разные трактовки long double у разных компиляторов (Borland и Microsoft, например), неопределённый char (который то знаковый, то без знаковый, но чаще всего знаковый)
Очень много перечислено, по каждому пункту можно дать ответ. Но боюсь что правильно было бы давать вне текущей Вашей темы (топика).
Например, стандарт (насколько мне известно) гарантировал всегда размер только одного типа - это char (байт). Остальное все отдавал на откуп компиляторам. Поэтому как правило, если разрабатывалась некая платформо-независимая библиотека, то она учитывала эти требования языка. С появлением например С++11 (и старше) для таких вещей, где размер типа и знаковость важна есть такое http://en.cppreference.com/w/cpp/types/integer

Цитировать
ну и на закуску невозможность строить переносимый код в принципе (даже между Unix-системами - то библиотеки названы иначе, то формат функций другой, то в структурах нет полей, которые есть в исходной системе).
Задачи бывают разные, и реализация переносимости тоже. С вами не согласится boost, QT, wxWidgets и еще много чего, openSSL, openSSH, libCurl и тд.
Так что вы не правы - переносимый код уже существует много лет

Цитировать
В общем, если всё это есть, значит, оно кому-то нужно.
Разумеется, оно кому-то нужно, вводят это не просто так - а потому что это потребовалось (для своих целей/библиотек или по требованию пользователей). Но пользуясь этими средствами всегда нужно помнить, что они скорее всего окажутся не переносимы. И хорошо если при переносе другой компилятор Вам скажет - "эй, я не понимаю что это и как мне с этим работать. Для меня это ошибка!". А ведь может например и ничего не сказать (как c volatile) - молча проглотить и не проставить нужный memory_order (ну потому что - никто от него этого и не требует, а значит вправе и не делать лишних движений). И все, и ждите - "какая такая Америка? Ничего не знаю!"


Цитировать
Угу. Вот ваш POSIX:
....
И на практике мы имеем тот же зоопарк.

Ключевое слово как правило. Откровенно, POSIX - давно пользовался, привел его просто в качестве примера переносимости. Допускаю что может иметь специфику работы от платформы к платформы. Но это - нормально, как ни странно Вам может показаться. Решение должно распространятся от общего к частному, от абстракции к имплементации. И если имплементация оказывает сильное влияние на абстракцию - то скорее всего такое решение нельзя назвать общим/переносимым. Другими словами, добиться переносимости кода не получается не потому, что не возможно это сделать в принципе, а потому что для решения не нашли достаточную абстракцию.
Ну нет например сигналов (Unix) в Windows. Зная что Вам нужно переносить решение на эту платформу, Вы скорее всего найдете подходящую абстракцию, реализация которой будет отличатся в сборке в зависимости от платформы, либо же вообще найдете другие переносимые способы взаимодействия.
Ну это вроде и очевидные вещи - то ли дело использовать WinApi ReadFile и мучатся с переносимостью и реализацией на каждой платформе, а то просто использовать std::fstream или fread/fwrite, а может вообще boost::asio или poco - и вообще покрывать большинство решений с файлами, последовательными портами и сокетами.


Цитировать
Выбирайте тот компилятор, где есть и который точно об этом скажет.
Я исхожу сначала из языка (его 100% гарантий) и библиотек, и в последнюю очередь полагаюсь на расширение предлагаемые компилятором.



Цитировать
Кстати, с atomic тоже можно сделать забавные ошибки: https://habrahabr.ru/post/155507/
Забавные ошибки можно сделать в любом месте с любым инструментом. Если человек, например не знает, что любые операции с переалацированием вектора (а это вставка, удаление элементов, ресайз и фактическое копирование) приводят к инвалидации  итераторов этого вектора - то такой человек сам себе злобный доктор. Это не проблемы языка. А в статье - человек показал нарочный пример при не верном использовании memory_order.

Ну и самое главное - я уже в который раз считаю что для подобных "споров" нужно создавать отдельную ветку с дискуссиями. А то Ваше первоначальное сообщение слегка "затерялось".
« Последнее редактирование: Марта 23, 2017, 06:43:08 pm от lastcross » Записан
da-nie
Full Member
***
Offline Offline

Сообщений: 167



Просмотр профиля
« Ответ #27 : Марта 23, 2017, 07:20:32 pm »

Цитировать
Очень много перечислено, по каждому пункту можно дать ответ.

Ответ тут очень простой: Си - помойка, которую надстраивают из года в год. И все эти "недосказанности" в стандарте это только подтверждают. "Ой, типы старые плохие, там int разной размерности, давайте срочно исправлять. Придумаем, int32_t! Ой, а библиотечные функции возвращают int - они старые, для них оставим int."  Grin

Цитировать
С вами не согласится boost, QT, wxWidgets и еще много чего, openSSL, openSSH, libCurl и тд.
Так что вы не правы - переносимый код уже существует много лет

О! Qt! В 2005 написал я приложение для Qt. Запускаем в современном Linux -а вот и не работает (нет библиотеки той старой версии в системе). Ладно, какой там Qt у нас? 5? Перекомпилируем. Ой, ошибка на ошибке - нет таких классов, а если есть, то методы названы иначе. Офигенная переносимость.  Grin А чего это для Windows 98, написанное в 2000-м приложение в Windows 10 работает и даже перекомпилируется? Даже не знаю.  Grin

Цитировать
А ведь может например и ничего не сказать (как c volatile) - молча проглотить и не проставить нужный memory_order (ну потому что - никто от него этого и не требует, а значит вправе и не делать лишних движений). И все, и ждите - "какая такая Америка? Ничего не знаю!"

Как я применяю volatile, ошибок не будет нигде и никогда. Wink

Цитировать
Ну нет например сигналов (Unix) в Windows

Возьмём сокеты - они есть и там и там. Возьмём функцию select. Чему там первый-то параметр равен у нас? Максимальный номер сокета+1? Это в Unix. А в Windows он равен 0 и не используется. Так и пишут:
Цитировать
int select(int nfds,                         // Не используется (оставлен для совместимости)
           fd_set FAR *readfds,              // множество сокетов, проверяемых на готовность к чтению
           fd_set FAR *writefds,             // множество сокетов, проверяемых на готовность к отсылке
           fd_set FAR *exceptfds,            // множество сокетов, проверяемых на ошибку/OOB данные
           const struct timeval FAR *timeout // Таймаут проверки
);
Переносим приложение из Windows - и вуаля, не работает в Unix.

Цитировать
Ну это вроде и очевидные вещи - то ли дело использовать WinApi ReadFile и мучиться с переносимостью и реализацией на каждой платформе,

Вот после таких вот "универсальных" библиотек программы весят мегабайты и требуют гигабайты. Wink Если вы пишете под Windows - используйте Win32 API и MFC (тот же ReadFile умеет, например, асинхронное чтение,а CreateFile умеет открывать файл с самыми разными особенностями (что делать, если файл занят другой программой, может ли дескриптор файла наследоваться дочерними процессами и так далее). Это существенно сократит размер программы и увеличит её скорость.

Цитировать
Я исхожу сначала из языка (его 100% гарантий) и библиотек, и в последнюю очередь полагаюсь на расширение предлагаемые компилятором.

Любая платформа имеет особенности, которые раскрываются именно компилятором и его возможностями. Зачем нужны массивы нулевой длины структурах? Очень удобно накладывать на принятые данные переменной длины и с определённым заголовком, особенно, на микроконтроллерах.

Цитировать
А в статье - человек показал нарочный пример при не верном использовании memory_order.

Не вы ли подавали atomic как безопасный к использованию? Wink

Цитировать
Ну и самое главное - я уже в который раз считаю что для подобных "споров" нужно создавать отдельную ветку с дискуссиями. А то Ваше первоначальное сообщение слегка "затерялось".

Ну тогда будем считать, что каждый остался при своём мнении. А холивар мне не нужен.
Что касается исходной темы, вряд ли кто-нибудь найдётся, кто сможет хоть что-то сказать про USBD в QNX. А программу я и так периодически обновляю и выкладывают.
« Последнее редактирование: Марта 23, 2017, 07:36:35 pm от da-nie » Записан

И день и ночь в пути
da-nie
Full Member
***
Offline Offline

Сообщений: 167



Просмотр профиля
« Ответ #28 : Апреля 05, 2017, 09:20:44 pm »

Новая версия! Добавлен расчёт температуры. Так же на некоторых компьютерах не видит устройство - лечится выбором в BIOS USB 1.0 вместо USB 2.0.

Также я написал программу для работы с Flir One Gen 2 из Windows XP (с драйверами - их три для каждого компонента устройства). Вдруг кому пригодится. Smiley
К сожалению, в других версиях Windows драйвер мне не удалось установить. Поэтому драйвера только для XP. И то, на некоторых компьютерах не на всех USB-портах Windows видит устройство как 3 устройства. С остальными версиями Windows ничего не получается, например, в Windows 7 x86 устройство видится как "Составное USB устройство", и я без понятия, что нужно сделать, чтобы их разделить (XP делит на три устройства с окончаниями на iAP, FileIO, Frame). Roll Eyes Поэтому, хотя драйвера я и компилировал и для Windows 7, но как их установить без понятия. В x64 драйвер, как я понял, вообще нельзя установить не подписав его (пишут, что есть способ смухлевать, но я не пробовал).
« Последнее редактирование: Апреля 05, 2017, 09:36:48 pm от da-nie » Записан

И день и ночь в пути
da-nie
Full Member
***
Offline Offline

Сообщений: 167



Просмотр профиля
« Ответ #29 : Апреля 10, 2017, 08:04:48 pm »

Обновлена версия для Windows XP. Smiley Как ни странно, под Windows получилась самая стабильная работа программы. Если Windows смогла увидеть три устройства и драйвера для них установились, то дружба Windows с тепловизором отныне навсегда. Smiley
В комплекте нет файла WdfCoInstaller01009.dll ввиду его большого размера. Но его можно найти, например, в WinDDK или в драйвере из предыдущего сообщения.


« Последнее редактирование: Апреля 10, 2017, 08:17:21 pm от da-nie » Записан

И день и ночь в пути
Страниц: 1 [2] 3 4 5
  Печать  
 
Перейти в: