1. Си / Говнокод #19293

    −95

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    static char example(struct pt *pt)
    {
      switch(pt->lc) { case 0:
      while(1)
      {
        pt->lc = 11; case 11: if(!(counter == 1000)) return 0;
        printf("Threshold reached\n");
        counter = 0;
      }
      } pt->lc = 0; return 2;
    }

    Прототреды

    Запостил: govnokod3r, 12 Января 2016

    Комментарии (39) RSS

    • if (!(counter == 1000)) return 0;

      Я тоже где-то слышал, что оператор != не thread-safe
      Ответить
      • Справедливости ради стоит отметить, что в это раскрылся макрос PT_WAIT_UNTIL(pt, counter == 1000).
        Ответить
    • Так выглядит с нераскрытыми макросами
      static PT_THREAD(example(struct pt *pt))
      {
        PT_BEGIN(pt);
        while(1) 
        {
          PT_WAIT_UNTIL(pt, counter == 1000);
          printf("Threshold reached\n");
          counter = 0;
        }
        PT_END(pt);
      }
      Ответить
      • А где оно такое используется?
        Ответить
        • Микроконтроллеры в основном и всякая встройка, куда нормальная ось не влезает.
          Ответить
          • Ну дык там это вполне прилично и допустимо. Правда, printf меня в таком контексте смущает.
            Ответить
            • там printf обычно направляют в uart или ещё куда для отладки. обычная практика
              Ответить
              • printf() толстый достаточно. Если он влезает, то наверняка есть место и под что-нибудь вроде TinyOS.
                Ответить
                • printf пару килобайт весит, в любой микроконтроллер влезет.
                  Ответить
                  • Ну основные плюшки tinyos где-то столько же весят.
                    Ответить
                    • Как товарищ Борманд сказал, порезанная версия printf'а весит очень мало. http://www.menie.org/georges/embedded/printf-stdarg.html, например.
                      Ответить
                      • Это длинный ещё.

                        У меня printf для rs-232 вообще кастрированный был, строк 50 на сишке. Выводил только целые числа разного размера (только хексами, без паддингов и прочих свистоперделок) да строки. И этого хватало за глаза ;)

                        P.S. Сколько байт там было - х.з., не замерял. Но строки всяко весили больше, чем сам printf.
                        Ответить
                        • А зачем в таком юзкейсе вообще printf? Почему не fputs?
                          Ответить
                          • А не заебёт fputs'ом чиселки логировать, перемежая их с текстом? :) Особенно, если у тебя кучи нет. Ну и fputs с ручными конвертациями сожрёт гораааздо больше драгоценных байтиков...
                            Ответить
                  • Ну тем более можно же сделать порезанный printf, в котором не все фишки из стандарта есть. Для отладочной консоли более чем достаточно.
                    Ответить
    • Этот код ничего не делает же.
      и без говнодаффа никак?
      Ответить
    • Так можно писать потому что switch-case - это набор goto-шек?
      Пытаясь понять этот код у меня stack overflow.
      Ответить
    • Можете пояснить почему нельзя написать
      while(counter != 1000);
      ?
      Ответить
      • > PT_WAIT_UNTIL(pt, counter == 1000);
        Ответить
        • Ладно,
          while(counter==1000) {
          printf("Threshold reached\n");
          counter = 0;
          }
          Ответить
          • ОП запостил код, пропущенный через макропроцессор. Оригинал до препроцессинга можно найти где-то в верхних комментах. Препроцессор не может поменять == на !=, может тоьлко дописать скобочки и !.
            Ответить
            • Да это понял я!
              Ок, спрошу по другому.
              Чем код выше с нераскрытыми макросами отличается от
              while(counter==1000) {
              ...
              }
              ?
              Ответить
              • Тем, что компилится по сути в конечный автомат, между которыми потом будет прыгать управление. Такая пародия на корутины. Или хардкорный сишный async/await :)

                Твой код эту 1000 тиков счётчика будет тупо жрать проц, а код ОП'а займётся другими "тредами" или тупо поспит для экономии энергии.
                Ответить
                • И в какой же строчке код ОПа спит, интересно?
                  Ответить
                  • В планировщике этих корутин же...

                    Посмотри внимательно на код. Он возвращает управление в вызывающую функцию, если counter != 1000. А при counter == 1000 он сбрасывает counter на 0 и тоже возвращает управление.

                    По сути, получается конечный автомат.

                    P.S. Я так понимаю, что обычные локальные переменные тут юзать нельзя. Только глобалки и, возможно, какую-то приватную структуру, доступную через pt.
                    Ответить
                  • P.S. А, понял о чём ты. Да, планировщик же не знает, что корутина ОП'а ждёт именно изменения counter'а. Поэтому он будет все корутины опрашивать по кругу, и поспать, действительно, не сможет.

                    P.P.S. Да, чтобы всё это нормально работало, надо мутить полноценные wait-notify, а не говно со счётчиком. Кстати, вполне возможно, что они там есть.
                    Ответить
                    • Что-нибудь типа:
                      PT_WAIT_CONDITION wc;
                      
                      // в одном "треде"
                      PT_WAIT(pt, wc, counter == 1000);
                      counter = 0;
                      
                      // в другом "треде"
                      counter++;
                      PT_NOTIFY(pt, wc);
                      Вот тут будет нормальный сон, без загрузки проца на 100%.
                      Ответить
                      • А это апи, кстати, откуда пошло?
                        Ответить
                        • Monitors were invented by Per Brinch Hansen[1] and C. A. R. Hoare,[2] and were first implemented in Brinch Hansen's Concurrent Pascal language. (1973 год)

                          Откуда-то оттуда, наверное ;)
                          Ответить
    • Спагетти... switch, вплетённый в while, или вечно живой goto.

      Хорошо, что в Паскале так нельзя.
      Ответить
      • Вот кстати да, почему бы не въебать туда goto. Оно всё-таки понятней дафф-девайса. P.S. А, тут же табличный переход нужен. Затупл.
        Ответить
        • Там вроде есть реализация с метками, но пишут, что собирается только в ГЦЦ
          Ответить
      • Эй, я слышал ты любишь свитчиться в вайле, поэтому мы встроили свитч в твой вайл, что бы ты мог свитчиться пока циклишься
        Ответить
        • В Го именно так и сделали:
          for {
              select {
              case ...:
              case ...?
          }
          }
          Ответить
          • > В Го именно так и сделали
            Не, это не то. В коде топика switch прыгает сразу внутрь цикла.
            А select в го няшный - с ним можно отмену асинхронных операций тривиально реализовать. Или спекулятивный параллелизм. Я всё жду, пока аналоги в кресты завезут.
            Ответить
    • Интересно, а откуда берётся число 11? Номер строки?
      Ответить

    Добавить комментарий