1. Pascal / Говнокод #7101

    +110

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    48. 48
    49. 49
    50. 50
    51. 51
    52. 52
    53. 53
    54. 54
    55. 55
    56. 56
    57. 57
    58. 58
    59. 59
    60. 60
    61. 61
    62. 62
    63. 63
    64. 64
    65. 65
    66. 66
    67. 67
    68. 68
    69. 69
    70. 70
    71. 71
    72. 72
    73. 73
    74. 74
    75. 75
    76. 76
    77. 77
    78. 78
    79. 79
    80. 80
    unit HRTimer;
     
    interface
     
    uses Windows;
     
    type
      // --------------------- Класс - высокоточный таймер -------------------------
      THRTimer = class(TObject)
        constructor Create;
        function StartTimer: Boolean; // Обнуление таймера
        function ReadTimer: Double;   // Чтение значения таймера в миллисекундах
      private
        StartTime: Double;
        ClockRate: Double;
      public
        Exists: Boolean;    // Флаг успешного создания таймера
      end;
     
    var
      Timer: THRTimer; // Глобальая переменная. Создаётся при запуске программы
     
    { Фукнция высокоточной задержки.
     Delphi:
       Синтаксис: function HRDelay(const Milliseconds: Double): Double;
       Milliseconds: Double - задержка в миллисекундах (может быть дробной)
       Результат функции - фактически произошедшая задержка с погрешностью.
       Пример вызова функции: X:= HRDelay(100.0); или HRDelay(100.0);
     
     C++Builder:
       Синтаксис: double HRDelay(const double Milliseconds);
       Double Milliseconds - задержка в миллисекундах (может быть дробной)
       Результат функции - фактически произошедшая задержка с погрешностью.
       Пример вызова функции: double X = HRDelay(100.0); или HRDelay(100.0);}
    function HRDelay(const Milliseconds: Double): Double;
     
    implementation
     
    function HRDelay(const Milliseconds: Double): Double;
    begin
      Timer.StartTimer();
      repeat
        Result:= Timer.ReadTimer();
      until Result >= Milliseconds;
    end;
     
    { THRTimer }
     
    constructor THRTimer.Create;
    var
      QW: LARGE_INTEGER;
    begin
      inherited Create;
      Exists := QueryPerformanceFrequency(Int64(QW));
      ClockRate := QW.QuadPart;
    end;
     
    function THRTimer.StartTimer: Boolean;
    var
      QW: LARGE_INTEGER;
    begin
      Result := QueryPerformanceCounter(Int64(QW));
      StartTime := QW.QuadPart;
    end;
     
    function THRTimer.ReadTimer: Double;
    var
      ET: LARGE_INTEGER;
    begin
      QueryPerformanceCounter(Int64(ET));
      Result := 1000.0 * (ET.QuadPart - StartTime) / ClockRate;
    end;
     
    initialization
      Timer:= THRTimer.Create();
     
    finalization
      Timer.Free();
     
    end.

    классический шайзберг посреди майских роз (ну почти розы)

    Запостил: bugmenot, 29 Июня 2011

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

    • var Timer: THRTimer; можно перенести после implementation, чтоб шаловливыми ручонками не трогали. А так - не вижу в чем беда, у меня похожий класс есть.
      ---
      Ну и зачем LARGE_INTEGER непонятно, все же напрямую приводится.
      Ответить
      • > А так - не вижу в чем беда
        оно так красиво оформлено, что я тоже не сразу заметил :)
        Ответить
        • Ну и в чем же беда? В Double;? В "жадном" слипе?
          Ответить
    • 1. StartTime: Double;
      ClockRate: Double;
      надо было int64
      2. весь класс поместить в implementaion
      3. самое важное - hrdelay нагружает процессор. нужно sleep добавить при долгих (к примеру >0.1 сек) паузах.
      Ответить
      • 1. да, не заметил
        2. Нет, может пользователь для своих целей будет юзать, не только для delay
        3. Ну, может он сделан для небольших пауз. Тогда будет излишнее усложнение.
        Ответить
        • 2. может, хотя маловероятно - время замерить разве что
          3. усложнение, но небольшое. для небольших пауз так и надо.

          кстати, вопрос чем sleep не понравился?
          Ответить
          • У sleep точность - 15 мс. Для адекватных задержек (скажем при работе с внешними девайсами) не годится.
            Ответить
        • > hrdelay нагружает процессор
          дык, ради этого и постилось

          еще есть 4. странная хуита видимостью мемберов

          > может он сделан для небольших пауз
          multimedia timers, не? чтоб процом-то не тормозить...
          Ответить
          • >multimedia timers, не? чтоб процом-то не тормозить...
            В винде (во всяком случае winXP) квант выделяемого задаче времени - 15мс. Так что задержку в 10мс не сделаешь никак, кроме такой вот жадной реализации.
            Ответить
            • >задержку в 10мс не сделаешь никак, кроме такой вот жадной реализации.
              Да вот возмёт винда и вытеснит твой жадный слип на другую задачу... Так что это тоже не гарантия 10 мс
              Ответить
              • Если в коде потока есть нормальный sleep и если цикл не больше 15мс занимает, то не должна. Ну и приоритет по максимуму.
                Ответить
                • >Ну и приоритет по максимуму.
                  Ага, и приложение зависая - убивает всю ось до следующей перезагрузки ресетом... Конечные пользователи, вам это не простят.
                  Ответить
                  • Ок, раз у нас не пульт а обычный софт на компе, то макс. приоритет не нужен, без него все прокатит.
                    Ответить
            • "For example, a MIDI sequencer requires a high-resolution timer because it must maintain the pace of MIDI events within a resolution of 1 millisecond."
              Ответить
              • Хм, надо будет попробовать.
                Ответить
                • "Periodic timer events with an event delay of 10 milliseconds or less consume a significant portion of CPU resources." Но чувствую, что они примерно также сделаны.
                  Ответить
    • В Дельфи надо 100 раз подумать, прежде чем лепить класс для какой-либо фигни. Потому что когда ты пишешь на Дельфи голыми структурами, то всё нормально, а как только ты переходишь на объекты, то надо ещё всё время думать о том, не забыл ли ты уничтожить объект, то есть сложность кода только увеличивается. Спасибо блять ботланду за ооп с ручными деструкторами. Я из-за этой поебени ваще забил на ООП в Дельфи.
      Ответить
      • это была имперсонация? тарас вроде был ярым врагом пропертей, а не деструкторов.
        Ответить
        • Это спец.виртуал, чтобы обсирать Дельфи. Основной профиль марать не хочу.
          Так вот, я за АВТОдеструкторы. А ручные деструкторы - это полный пиздец, кто только эту хероту придумал.
          Ответить
          • жидковато обосрал.
            заюзай интерфейсы и будут тебе объекты уничтожаться в Release.
            Ответить
            • Интерфейсы очень неудобны. И со скоростью у них очень хреново. Потому что сделаны они очень костыльно.
              Ответить
              • > И со скоростью у них очень хреново. Потому что сделаны они очень костыльно.
                ЛОЛШТО?
                почитай википедию, чтоли
                Ответить
                • я как-то читал википедию, что интерфейсы там заюзаны через COM

                  действительно костыльно...
                  Ответить
      • > ооп с ручными деструкторами
        Кому как, меня например не напрягает.
        Ответить
        • Код с автодеструкторами:
          a := Func1(Func2(b), Func3(c), Func4(d));

          Код с ручными деструкторами:
          try
            tmp1 := Func2(b);
            try
              tmp2 := Func2(c);
              try
                tmp3 := Func3(d);
                try
                  a := Func1(tmp1,tmp2,tmp3);
                finally
                  a.Free;
                end;  
              finally
                tmp3.free;
              end;
            finally
              tmp2.Free;
            end;
          finally
            tmp1.Free;
          end;


          Тебя это не напрягает? Или ты не заботишься об исключениях, о том, что надо в каждой точке выхода прописать все вызовы деструкторов?
          Не-не-не, нахуй такое ООП.
          Ответить
          • Не, ну если возвращать из функции объекты - это да, бред. Для этого есть конструкторы.
            Я использую ООП для более-менее стабильных сущностей - всяких там групп приводов, существ, предметов и т.д. Для них я точно знаю, когда они должны создаваться и когда исчезать.
            Да, слегка неудобно что я не могу прозрачно обернуть в объект скажем строку или set, но не отказываться же из-за этого от паскаля.
            Ответить
            • Переходи на Аду. В ней есть автодеструкторы. Правда, формошлёпки нету, всё будешь руками делать. Зато в стандартной библиотеке есть все контейнеры.
              Ответить
              • А есть современные иде и компиляторы Ады под винду?
                Ответить
                • Да, всё есть. Язык вполне себе живёт, вот даже красноглазики для gcc сделали бесплатный компилятор Ады и среду. Правда, среда тоже красноглазая - немного не для людей сделана. Под винду есть версия, но с красноглазыми приколами - например, исходники сохраняет без 10го символа в переносах строк.
                  Ответить
                  • какие, в жопу, красноглазики? изначально задумано было под GPL выпускать
                    Ответить
              • Не, что-то стремно. Паскаль кроссплатформенный (можно даже под андроид писать), для паскаля куча библиотек есть. А что автодеструкторов нет - ну да, чуток лишнего кода приходится написать, но это же не главное.
                Ответить
                • > Паскаль кроссплатформенный

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

                  > А что автодеструкторов нет - ну да, чуток лишнего кода приходится написать, но это же не главное.

                  А сидеть на пороховой бочке тебя тоже не напрягает? Что программа может взять и потечь из-за того, что где-то какой-то случай не разобрал?
                  Ответить
                  • >Ага, на одной платформе один диалект, на другой - другой.
                    Один диалект (FreePascal) на все платформы. Ну и Дельфи на винде, слегка отличающимийся по фичам, зато с более эффективным компилятором.

                    >А сидеть на пороховой бочке тебя тоже не напрягает? Что программа может взять и потечь из-за того, что где-то какой-то случай не разобрал?
                    К моему стыду нет. Мой софт на спутники не ставят, а если возникает непредвиденное исключение (причем не один раз возникает, а начинает все время возникать, иначе меморилика серьезного не будет), то обычно виноват какой-нибудь баг в программе и утечка памяти становится наименее важной из бед.
                    Ответить
                    • > К моему стыду нет. Мой софт на спутники не ставят

                      Когда будут ставить, когда будешь трястись по ночам за каждый баг, то поймёшь, какая жопа - ручные деструкторы.
                      Ответить
                      • Тогда меня и РАИИ не особо успокоит. А если я ссылку на объект куда-то передал? Тогда уж Java c GC и генерящимися юниттестами надежнее.
                        Ответить
                        • > А если я ссылку на объект куда-то передал?

                          Ну и что? А оператор присвоения на что? Ну передашь ты ссылку, у тебя объект сразу же скопируется (либо счётчик ссылок увеличится), какие проблемы?

                          А GC лажа. Он не поможет вовремя закрыть файл или освобдить критическую секцию.
                          Ответить
                          • >Ну передашь ты ссылку, у тебя объект сразу же скопируется (либо счётчик ссылок увеличится), какие проблемы?
                            и в результате не убьется. А его контейнер, к которому он относился уже убился, например. Так что когда этот обьект начнет удалятся, будет эксепшн. Хотя если правильно писать... может и не будет.

                            Вот для критических секций и файлов имхо и так все ясно. Один раз создали, один раз удалили. Если в локальной процедуре юзаем - обернули в try.
                            Ответить
                            • > и в результате не убьется. А его контейнер, к которому он относился уже убился, например

                              Так, иди изучай auto_ptr и shared_ptr, потом продолжи разговор. Это азы, объяснять их я не вижу смысла. Да и лень врубаться в то, что ты имеешь в виду.

                              > Вот для критических секций и файлов имхо и так все ясно. Один раз создали, один раз удалили.

                              А где именно удалили? А если из процедуры много выходов? Зачем руками следить за тем, для чего есть средства языка?
                              Ответить
                              • >Так, иди изучай auto_ptr и shared_ptr, потом продолжи разговор. Это азы, объяснять их я не вижу смысла. Да и лень врубаться в то, что ты имеешь в виду.
                                Я к тому, что всех проблем с памятью это само по себе не решит, все равно думать об области видимости надо.

                                >А где именно удалили? А если из процедуры много выходов? Зачем руками следить за тем, для чего есть средства языка?
                                В Аде - незачем, раз есть средства языка.
                                В Паскале - вполне нормально следить.
                                CS := TCriticalSection.Create;
                                try
                                ... работаем с ней, можем вызывать exit сколько хотим
                                finally
                                CS.Free;
                                end;
                                Автодеструкторы сэкономили бы три строчки.
                                Ответить
                                • Без автодеструктора:
                                  CS := TCriticalSection.Create;
                                  try
                                  ... работаем с ней, можем вызывать exit сколько хотим
                                  finally
                                  CS.Free;
                                  end;
                                  С автодеструктором:
                                  CS := TCriticalSection.Create;
                                  ... работаем с ней, можем вызывать exit сколько хотим
                                  4 строчки экономии на 1 объект, а если программа написана с применением ООП, то сколько строчек сэкономлено?
                                  Ответить
                                  • если программа написана с применением ООП, то сколько строчек сэкономлено - три строчки и сэкономлено. Критические секции я обычно создаю только в начале программы, а файлы открываю в одной-двух функциях.
                                    Ответить
                                    • >Критические секции я обычно создаю только в начале программы, а файлы открываю в одной-двух функциях.

                                      В серьёзных проектах это явно не так...
                                      Ответить
                                      • Ну, если в серьезных проектах не могут поддерживать высокий уровень абстракции, то это их проблемы.
                                        Ответить
                              • >иди изучай auto_ptr и shared_ptr
                                Если он пишет на дельфи, то наф? Лучше уж пусть другие языки посмотрит.
                                Ответить
                                • Конечно, в других языках типа явы эта хрень не нужна.
                                  Ответить
                            • >обернули в try.
                              Это ручная работа, а ты человек, а значит обязательно ошибешься. Мало того, что в софте будут ошибки, так ещё потом придется их отлаживать и тратить на это время. Лучше бы ты это доверил компилятору.
                              Это тупая работа, если это может сделать твой компилятор. Лучше ты за это время напишешь пару лишних программ, а значит больше заработаешь и уедешь на Карибы или просто будешь пинать балду, написав "недельную" программу за день, тк большую часть работы сделал за тебя компилятор..
                              Ответить
                              • Нет, за это время я успел бы написать на три-четыре строчки шаблонов больше.
                                Ответить
                                • >я успел бы написать на три-четыре строчки шаблонов больше.
                                  А причём тут шаблоны, когда мы паттерн автодеструкторов обсуждаем и перекладывания работы на компилятор?
                                  Ответить
                                  • Я к тому, что эти несколько try..except мне много не сэкономят. Их написание и отладка - не больше 5% от общего объема. Тем более речь, кажется, об оборачивании в try критических секций и файлов? Тогда это 0.1%.
                                    Ответить
                                    • >Их написание и отладка - не больше 5% от общего объема.
                                      >5%
                                      Хрена себе... 5% Да с моими то проектами - я бы убился это писать и особенно отлаживать.
                                      Ответить
                                      • Что там можно отлаживать? В начале процедуры создал три объекта - в конце столько же объектов удалил. А большинство объектов все равно на куче создаются, и про них ты точно знаешь когда они появляются и когда умирают.
                                        Ответить
                    • >меморилика серьезного не будет
                      Опасность не убитых объектов не только в утечках памяти, а в утечки прочих важных и не очень ресурсов и нарушениях логики работы программы.

                      Например, в многопоточном программировании используется паттерн:
                      При создании объекта - лочится семафор, а при удалении объекта - его отпускает. Это крайне удобно, тк не важно какое исключение бы не произошло - логика программы не нарушится, тк семафор все равно будет разблокирован при удалении объекта.
                      Ответить
                      • За важными ресурсами я слежу и деструктор вызываю. Это ведь не локальная переменная, это важный объект.
                        Ответить
                    • >обычно виноват какой-нибудь баг в программе
                      Вот, если бы часть работы компилятор языка делал за тебя, то баг бы такой может быть бы и не возник. Например он бы вызвал за тебя деструктор при исключениях или просто за тебя, даже когда ты бы забыл. В конце концов, проверил бы тип объекта или не меняешь ли ты константный объект.
                      Ответить
                      • >проверил бы тип объекта
                        Кстати, в дельфи это типичная ситуация, когда приходится использовать "безтиповый" pointer или variant или ещё какой хак, что-бы написать универсальную коллекцию. В то время, когда в языке есть шаблоны - коллекция может проверить во время компиляции тип элементов, которые в неё кладут.
                        Ответить
                        • TList<TMyOwnClass>
                          Это не шаблоны, это генерики. Они есть.
                          Ответить
                          • Это в новых дельфях... Не знаю на сколько они...
                            Ответить
                            • И в FreePascal (Там будет specialize TFPGList<TMyOwnClass>)
                              Ответить
            • Как вы вообще со строками работаете? Это же убиться, если для каждой вызывать free
              Ответить
              • Кстати, да, убится можно преобразовывать между char*, const std::string и std::string. А в Дельфи как раз все просто - всю работу менеджер памяти на себя берет.
                Ответить
                • >убится можно преобразовывать между char*, const std::string и std::string
                  Очень смешно.

                  >Дельфи - всю работу менеджер памяти на себя берет.
                  Знаем, как он на себя работу берёт. Дельфи-программы всегда славились хорошей утечкой памяти...
                  Ответить
                  • С-программы всегда славились атаками на переполнение буфера. Уж что-что, а строки в паскале намного более годные чем в С++.
                    Ответить
                • выделение и освобождение памяти под хранение строк делает не сам менеджер, а тот код, где эти строки используются (он генерируется автоматом). в этой части все сделано как надо. проблема в самом менеджере памяти, но ее очень просто обойти - можно взять fastmem или написать свой велосипед через HeapAlloc / HeapFree - 20-30 строк кода.
                  Ответить
              • В Дельфи строки и динмассивы встроены, для них всё автоматом делается как надо. Только они меня и спасают. Строки работают через счётчик ссылок, копируются при записи. Динмассивы - через счётчик ссылок, копируются только если прямо сказать.

                А вот для остального почему-то ботланд не додумался сделать автодеструкторы. Зато он додумался в языке без ГЦ и автодеструкторов сделать классы, экземпляры которых создаются В КУЧЕ. Я считаю, что это рак мозга.
                Ответить
                • >Только они меня и спасают.
                  Может складывать объекты в dynмассивы, что-бы у них деструктор сам вызывался? :D
                  Ответить
                  • Не, это не помогает.
                    Но класть числа в динмассив длины 1 мне один раз пришлось.
                    Ответить
                    • можете запостить на говнокод?
                      Ответить
                      • Трудно вырвать кусок, чтобы было понятно, для чего это.
                        Вообще это из моего калькулятора (архив с исходниками): http://tarasber.narod.ru/MiniCalc.rar
                        Ответить
                        • Вырвите пожалуйста, хоть даже и не понятно...
                          Ответить
                          • Ну вот я там для хранения лексемы использую структуру, а ней есть указательное поле если лексема - переменная.

                            TOperator = record
                              ...
                              Number: array of TNumber;
                              ...
                            end;

                            Функция взятия следующей лексемы из строки:
                            function Token(var C: PChar): TOperator;
                            ...
                            begin
                            ...
                              SetLength(Result.Number, 1);
                              Result.Number[0] := Val(C);
                            end;
                            Ответить
                        • >delphi
                          >narod.ru
                          your post gave me a feel
                          Ответить
                          • Не место красит человека, а человек - место.
                            Ответить
                            • Не язык красит человека, а человек - язык.
                              Ответить
                • да, и стековых классов ОЧЕНЬ не хватает
                  Ответить
                  • Есть слово object для них.
                    Ответить
                    • а если мне нужно экземпляр готового класса создать как стековая переменная, чтобы корректно вызвались конструктор и деструктор?
                      Ответить
      • >Спасибо блять ботланду за ооп с ручными деструкторами.
        >Topacer
        Торасег? Торасег? Да вам явно нужен ник антитарасег.
        Ответить
    • На многопроцессорной машине работать не будет:
      http://habrahabr.ru/blogs/amd/92597/
      Ответить
      • лол, у хабрабыдла всегда что-то глючить будет
        альзо:
        > Ошибка выскакивала
        а коде говнище начинается уже с тупо скопипащенной венгерки
        можно постить, воняет как треска
        Ответить
    • HRDelay() я написал для того, чтобы отмерять задержки до 1 мс. Всякие там Sleep(), GetTickCount() и пр. на таких интервалах имеют погрешность 1500% (тыщапицот!). Вот и всё. Основной код модуля взял с инета 100500 лет назад. Он работает, да и пох.
      Ответить
      • автор чтоле?
        ты - идиот, читай справочник, там черным по английскому написано почему погрешность и как с ней бороться.
        Ответить
    • показать все, что скрытоvanished
      Ответить

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