На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела:
1. Название темы - краткое описание кто/что против кого/чего
2. В первом сообщении - список параметров, по которым идет сравнение.
3. Старайтесь аргументировать свои высказывания. Фразы типа "Венда/Слюникс - ацтой" считаются флудом.
4. Давайте жить дружно и не доводить обсуждение до маразма и личных оскорблений.
Модераторы: Модераторы, Комодераторы
Страницы: (32) « Первая ... 27 28 [29] 30 31 ... Последняя »  ( Перейти к последнему сообщению )  
> goto vs break & continue , Кроха-сын пришел к отцу и спросила кроха: "goto - это хорошо?"
    Цитата applegame @
    Ага, "костыль", который выглядит чище, а работает не хуже.
    Именно что выглядит. Так-то он хуже. Потому что не избавляет пользователей scope()-ов от того, чтобы быть постоянно быть во внимании и заниматься рутинным делом: проверять успех небезотказной операции и клепать код отмены транзакций. RAII требует этого только от автора.
    Ну и опять же, если пользователей не больше авторов :D , тогда scope()-ы окупаются. Но в промышленных решениях это редкие события.

    Добавлено
    Цитата applegame @
    Сколько ждали появления в плюсах лямбд и auto?
    Объективно – пару лет. В бусте подобные штуки появились быстро, и в следующий Стандарт заехали без проблем.
      Цитата Qraizer @
      Объективно – пару лет

      Враки! :lol: Я с лямбдами в Perl'е работал с 1998 года (и то - я опаздун в освоении Перла). В сях - "не прошло и пол-года".
        Цитата applegame @
        Посмотри на свою иммитацию scope: scope1, scope2, scope3... - что это за мерзкие нумерованные переменные, которые нигде не задействованы? Вот где костыль-то.
        Угу. А если:
        ExpandedWrap disabled
          #define CAT(X, Y) X##Y
          #define VAR(X, Y) CAT(X, Y)
          #define SCOPE ScopeD::scope VAR(dummy, __LINE__)
        то лучше? Ненуачё...
        ExpandedWrap disabled
          int main()
          {
            using namespace ScopeD;
           
            SCOPE (failure, [](){ std::cout << "scope(exit) 1" << std::endl; });
            throw std::runtime_error("exception");
            SCOPE (failure, [](){ std::cout << "scope(exit) 2" << std::endl; });
          }

        :unsure:
          Qraizer, как уж на сковородке! :lool: Но таки - аcилил?! )))

          Добавлено
          Qraizer, наверное можно было бы и всю лямбду в макро загнать?
            Цитата JoeUser @
            Но таки - аcилил?! )))
            Кому вдруг критично :-? , пусть юзают. Я так не считаю. И даже не думаю, что кому надо было бы, не написал бы сам молча, а запросил саппорт "памагите".
            Цитата JoeUser @
            наверное можно было бы и всю лямбду в макро загнать?
            М-м, нет. В общем случае лямбда может быть очень сложной, препроцессор поломается на разделителях. Да и зачем? Препроцессор штука, конечно, мощная, но ну её.
              Qraizer, а вот тут
              ExpandedWrap disabled
                // ...
                Guard sameAppGuarded([=]() { CloseHandle(sameApp); });
                // ...

              Может в лямбде лучше по ссылке захватывать?

              Добавлено
              Дааа ... у этого RAII тоже есть побочки. Решил переписать "по-фэншую", и как оказалось, выплыла шляпа ;) Когда без RAII - критикуют мол, забудешь освободить ресурс. А как оказалось, в моей проге, пришлось в каждую лямбду вставить проверку на ошибку. Типа, если действительно была ошибка - освобождать, а если нет - пропустить. И только в одной лямбде это не потребовалось. Поэму рисуется контр-аргумент: не поставишь проверку необходимости освобождения - получишь ошибку времени исполнения.

              Добавлено
              ЗЫ: Qraizer, мне понравились твои гварды! Аккуратнее всего получается. :good:
                Цитата JoeUser @
                А как оказалось, в моей проге, пришлось в каждую лямбду вставить проверку на ошибку. Типа, если действительно была ошибка - освобождать, а если нет - пропустить. И только в одной лямбде это не потребовалось. Поэму рисуется контр-аргумент: не поставишь проверку необходимости освобождения - получишь ошибку времени исполнения.

                Возможно, ты что-то не так делаешь, например, не передаешь владение ресурсом. И о каких лямбдах речь?

                Можешь код привести?
                  Цитата D_KEY @
                  Можешь код привести?

                  Ну вот кусок:
                  ExpandedWrap disabled
                    // ...
                    // инициализация библиотеки
                    if (libssh2_init(0) != 0) {
                      sftpError = sftp_error::init_error;
                      return false;
                    }
                    Guard Guard_init([&]() {
                      if (sftpError != sftp_error::no) libssh2_exit();
                    });
                    // поиск адреса хоста
                    // ...
                    // ...
                    // ...

                  libssh2_exit() нужно вызывать только тогда, когда что-то потом пошло не так. Но если все отработало нормально - libssh2 должна остаться проинициализированной.
                    Цитата JoeUser @
                    libssh2_exit() нужно вызывать только тогда, когда что-то потом пошло не так. Но если все отработало нормально - libssh2 должна остаться проинициализированной.

                    Остаться-то должна, но потом где-то же должен быть вызов libssh2_exit все равно. Вот туда и надо передать владение. А не через guard' ы.
                      Цитата D_KEY @
                      Остаться-то должна, но потом где-то же должен быть вызов libssh2_exit все равно.

                      Это в деструкторе вызывается:
                      ExpandedWrap disabled
                        sftp_class::~sftp_class() {
                          if (sftpError != sftp_error::winsocket_error) {
                            if (sftpState == sftp_state::logged_in) Logoff(); // ◄────── вот тут и вызовется libssh2_exit
                              #ifdef WIN32
                              WSACleanup();
                              #endif
                            }
                          }
                        }
                        Ну вот в случае RAII у тебя и будет объект ssh_initializer или что-то вроде того. Который в деструкторе сделает ssh2_exit, если владеет объектом. Этот объект делаешь полем класса. Локально в функции, где идет init, ты создаешь временный объект этого класса и только в случае успеха передаешь владение полю.
                        Примерно так.
                          Тогда нарушается логика поведения класса. В методе Login происходит полная инициализация подключение к серверу, ну и подключение. Если логин не прошел - экземпляр класс болтается с состоянием ошибки, по не будет удален (ну или еще попытки логина). В деструкторе вызывается Logoff, если нужно - вот он и рвет все соединения (опять же, если класс не в состоянии ошибки).
                            Цитата JoeUser @
                            Решил переписать "по-фэншую", и как оказалось, выплыла шляпа ;) Когда без RAII - критикуют мол, забудешь освободить ресурс. А как оказалось, в моей проге, пришлось в каждую лямбду вставить проверку на ошибку. Типа, если действительно была ошибка - освобождать, а если нет - пропустить.

                            Если бы переписал по феншую, скорее всего шляпы не было бы. Значит написал не по феншую :-? Если у тебя вызов сишной функции возвращает код возврата - кто тебе мешает кидать исключение в конструкторе RAII обертки? Тогда и проверять не пришлось бы в деструкторе.
                              Цитата JoeUser @
                              Тогда нарушается логика поведения класса
                              ...
                              Если логин не прошел - экземпляр класс болтается с состоянием ошибки

                              Плохая практика, не надо так делать. Прочитай про инварианты класса.
                                Цитата JoeUser @
                                Типа, если действительно была ошибка - освобождать, а если нет - пропустить. И только в одной лямбде это не потребовалось.
                                Ну так это не RAII. В RAII нужно оборачивать ресурс, для которого известно время жизни, обозначив его {}, а не который когда захотел, получил, когда захотел, освободил. Если когда захотел, то это ж ничем не отличается от ручного управления. Посмотри в пример использования во втором "костыле", это пример из реальной программы... впрочем, мне не жалко скопипастить и даже прокомментировать:
                                ExpandedWrap disabled
                                    // Атомарно получить ресурс монопольного доступа к образу приложения и захватить его
                                    HANDLE sameApp = CreateMutex(NULL, TRUE, uniqName.c_str());
                                   
                                    // Вручную проверить успех получения ресурса
                                    if (sameApp == NULL)
                                      return static_cast<void>(logMsg("CreateMutex() failed", GetLastError()));
                                   
                                    // Зарегистрировать освобождение ресурса
                                    Guard sameAppGuarded([=]() { CloseHandle(sameApp); });
                                   
                                    // Проверить, удалось ли захватить монополию или же доступ уже ранее (GetLastError() будет равен ERROR_ALREADY_EXISTS) был кем-то захвачен
                                    if (GetLastError() == ERROR_ALREADY_EXISTS)
                                      if (WaitForSingleObject(sameApp, INFINITE) != WAIT_OBJECT_0)        // подождать возможности монопольного доступа
                                        // При ошибке монополизации гвард сам освободит ресурс
                                        return static_cast<void>(logMsg("Recursive run detected for " + name.filename().string(), GetLastError()));
                                    // Монополия успешно получена, зарегистрировать его отдачу другим страждущим
                                    Guard sameAppLocked([=]() { ReleaseMutex(sameApp); });
                                   
                                    // Локальные границы времени жизни файлов, в которые перенаправляется консольный ввод/вывод
                                    {
                                      SECURITY_ATTRIBUTES attr = { sizeof(attr), NULL, TRUE };
                                      // Файл для перенаправленного консольного ввода
                                      HANDLE hIn  = CreateFile((newName.parent_path() / "stdin.txt").string().c_str(),
                                                               FILE_GENERIC_READ, FILE_SHARE_DELETE,&attr, CREATE_ALWAYS,
                                                               FILE_ATTRIBUTE_NORMAL, NULL);
                                      // Зарегистрировать его закрытие
                                      Guard hInGuarded ([=]() { CloseHandle(hIn);  });
                                  /* и так для всех трёх стандартных консольных устройств,
                                     ну и кроме того там ещё куча логики работы с образом приложения */
                                    }
                                    // и тут эти локальные границы заканчиваются, файлы с консольным вводов/выводом закрываются гвардами.
                                    // Ниже есть ещё чуток кода для логгирования и ещё по мелочи, и гварды позаботятся и об освобождении образа приложения от монополии, и об освобождении ресурса
                                В твоём случае тебе достаточно чётко определить времена жизни своих ресурсов и обозначить их {}, в частности вложенными функциями, если надо. И всё. Изнутри наружу хоть экспешном выходи.
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0644 ]   [ 15 queries used ]   [ Generated: 26.04.24, 18:39 GMT ]