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

    +81

    1. 1
    2. 2
    3. 3
    4. 4
    5. 5
    6. 6
    7. 7
    8. 8
    procedure tmythread.execute;
      procedure fillmemo;
      begin
        form1.memo1.lines.add('Some string');
      end;
    begin
      synchronize(fillmemo); //[Error] Unit1.pas(54): There is no overloaded version of 'Synchronize' that can be called with these arguments
    end;

    Почему нельзя сделать вещи, сделанные "через анус", еще более "через анус"?

    Запостил: Stertor, 29 Января 2014

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

    • Дельфя 2009 пишет: cannot capture symbol 'fillmemo'
      Ответить
      • Потому что этот код не имеет смысла. Процедура fillmemo имеет доступ к переменным в стеке текущего треда (ну здесь их нет, но если ты поставишь var между строками 1 и 2 - будет). Если ее исполнить в другом потоке, что и делает synchronize, то код просто распидорасит. Как-то так.

        А почему оно не компилится - я х.з. Надо смотреть сигнатуру synchronize'а. Возможно он со спецом не жрет вложенные функции.

        О нормальных лямбдах, которые должны проканать на 2009: http://8vmr.livejournal.com/6114.html

        Реквестирую в тред Тараса, чтобы он меня поправил и обозвал нубом, не знающим делфи.
        Ответить
        • Хах. А если та же процедура возьмет переменную прямо из класса потока, не распидорасит? Один хуй же в другом потоке:
          type
              tmythread=class(tthread)
              private
              sometext:string;
              procedure ololo;
              protected
              procedure execute;override;
              public
            end;
          
            procedure tmyclass.Ololo;
            begin
              showmessage(sometext);
            end;
          
          procedure tmythread.execute;
          begin
            sometext:='Ololo';
            synchronize(ololo);
          end;

          ведь не пидорасит.

          p/s/
          Василий,если Вы здесь,срочно забаньте ботов - форум спамят.
          Ответить
          • > не распидорасит?
            Ну да, резонно. Синхронайз же текущий поток держит в спячке, пока функция до конца не выполнится.

            Тогда попробуй передать @fillmemo вместо fillmemo. Вроде же в паскале так делали указатель на функцию, а fillmemo - ее вызов.

            P.S. Я в делфи реально нуб.
            Ответить
            • Не, не катит.
              Ой, не скромничайте )
              Ответить
            • Так нельзя. Это в частных редких случаях работает. Это всё равно, что делать:
              ::std::string sometext;
              void thread1(){
                sometext = "thread1";
                ::std::lock_guard(mutex1);
                showmessage(sometext);
              }
              
              void thread2(){
                sometext = "thread2";
                ::std::lock_guard(mutex1);
                showmessage(sometext);
              }
              //...
              ParallelRun(thread1, thread2);
              Вопрос только в том, кто успеет первым?
              Ответить
              • Ну synchronized он все-таки блочит текущий тред пока указанная процедура не доработает. Так что с этим все норм.
                Ответить
                • > synchronized он все-таки блочит текущий тред
                  Не важно. Упрощу код для понимания.
                  ::std::string sometext;
                  void thread1(){
                    sometext = "thread1";
                  }
                  
                  void thread2(){
                    sometext = "thread2";
                  }
                  //...
                  ParallelRun(thread1, thread2).WaitAll();
                  print(sometext);
                  Что произойдет? UB. Хоть упадет.
                  Ответить
                  • Возможно, я ошибаюсь, но исходя из моего опыта, мне кажется, что сначала отработает один поток, затем второй. Synchronize() посылает потоку, который держит форму, сообщение о том, чтобы он вызвал метод, указанный в качестве параметра в Synchronize(). Поток, вызвавший Synchronize() будет заблокирован до полного завершения указанного метода. Двойного обращения к объекту не происходит, иначе какой же это Synchronize ;)
                    Ответить
                    • Меня что-то переклинило. Сделал общий sometext для потоков. Такого быть не должно ни если создали поток из локальной функции с замыканием не из класса потока с перегруженным виртуальным методом. Конечно можно создать static член, но это сам себе злобный буратина.
                      Ответить
            • > Тогда попробуй передать @fillmemo вместо fillmemo.

              Нельзя такую хуйню делать. @ это чтобы убрать проверку соответствия процедурных типов с непредсказуемыми последствиями.
              Ответить
              • > чтобы убрать проверку соответствия процедурных типов

                Костыли уже встроены в язык?
                Ответить
          • > procedure tmyclass.Ololo;
            > synchronize(ololo);

            то есть оно таки принимает не процедуру, а делегат
            Ответить
          • >> Один хуй же в другом потоке:

            Это в каком таком потоке я хуй?
            Ответить
        • >А почему оно не компилится
          Не тарас, но потому что старый дельфи не может в замыкания. А вложенная процедура - это таки замыкание (могло бы быть), т.к. имеет доступ к локальным переменным вызвавшей процедуры.
          Разумеется код ниже работает т.к. там нет доступа к локальным переменным, только к полям объекта.
          Ответить
          • Но вложенные процедурки вполне передавались во всякие sort'ы, хоть они и не полноценные замыкания, и дохнут в конце содержащей их функции. Или я туплю?
            Ответить
            • Не передавались. Возможно в каком-то очень старом паскале могли передаваться (т.к. вроде бы по виртовскому стандарту могут), но в дельфи точно нет.

              Насчет дохнут - а как компилятору это разрулить? Молча разрешать брать на них указатель и потом крашиться?
              Ответить
              • Ну да, вроде так и было в борланд паскале, если я конечно не туплю. А может и туплю.
                Ответить
                • Лень качать. Может в турбопаскале и было. Я сам был уверен что можно брать указатели на вложенные процедуры, пока в холиварах не начал участвовать.
                  Ответить
                  • Нельзя. В Турбопаскале можно было брать указатели только на невложенные функции, причём только с атрибутом far.

                    Для сравнения в gcc чтобы работали указатели на вложенные функции, пришлось делать трамплины. Т. е. в gcc замыкания — это уже не чистые функции, а что-то похожее на методы объектов (хотя в няшной по стандарту ООП нету).

                    В стандартном же Паскале не было процедурного типа, но был тип аргумента procedure, а как там было со вложенными функциями, не знаю. Некоторые реализации стандартного Паскаля компилировались не в нативный код, а в P-code, так что там возможность реализации всяких фишек зависела от виртуальной машины.
                    Ответить
            • > Но вложенные процедурки вполне передавались во всякие sort'ы
              Авотхуй.

              Кстати в Аде передаются, но только если ты скажешь, что sort принимает именно замыкание, а не функцию. Кстати синтаксис описания замыкания в Аде эээ отсутствует. Надо писать
              procedure Sort(in out A : TArray; sorter : access procedure (L,R : T) : boolean);

              И затайпдефнуть эту хрень никакого способа нету!!! И это в Аде, что везде и всегда заставляет каждый чих тайпдефить!!!
              Ответить
              • А хотя я не знаю как было в олдскульном Паскале. Может там тоже изъебнулись как-то. Может кстати через исполняемый стек.
                Ответить
          • У старого Дельфи вместо замыканий есть делегаты, то, до чего ко-ко-ко-кресты до сих пор не дошли.
            Ответить
            • опять ты за своё, старый хрыч
              Ответить
            • А std::function чем не угодил?
              Ответить
              • Это не делегат
                Ответить
                • обоснуй
                  Ответить
                  • скомпилится?
                    struct ololo
                    {
                      int a;
                      ololo(a):a(a) {}
                      void kokoko(int &i) {i+=a;}
                    };
                    ololo trololo(5);
                    std::function<class void(int&)> f = trololo.kokoko;
                    Ответить
                    • struct ololo {
                        void kokoko(int) {}
                        void kokoko(double) {}
                        static void kokoko(foo) {}
                      };
                      ololo tarasb;
                      tarasb.kokoko  // какой тип у этого выражения?
                      Ответить
                      • Это перпендикулярная проблема. Отделяй мух от котлет.
                        Кстати я в натуре не знаю, как при перегрузке надо звать указатель на функцию, чтобы было однозначно.
                        Ответить
                        • > как при перегрузке надо звать указатель на функцию, чтобы было однозначно

                          Как? Статик каст? Промежуточная переменная?
                          Ответить
                          • Не понял про промежуточную переменную.
                            Ещё можно так:
                            struct T//Обойдусь без всяких длиннющих трололо ололо и кококо
                            {
                              void f(int a){...};//Шеф! Всё пропало. Указатель не взять. 
                              void f(char b){...};
                              template<M> void f(M b){...};
                            };
                            
                            struct B
                            {
                              template<class ST, class M> void operator()(ST this_, M param1){this_->f(param1);}//Можно много перегрузок под разное число параметров.
                            };//Можно генерировать класс под разные методы макросом.
                            
                            T a;
                            function<void (int&)> f = bind(B(), &a _1);
                            bind можно выкинуть, передав &a в конструктор B. Правда чтобы не выводить самому шаблон ST в B - можно написать функцию генератор. B конечно может быть не шаблонным, если случай как здесь достаточно частный.
                            Ответить
                            • > Не понял про промежуточную переменную.
                              int  f(char);
                              long f(double);
                              
                              struct S {
                               int  g(char);
                               long g(double);
                              };
                              
                              int main()
                              {
                                  // No ambiguity
                                  int (*fc)(char) = f;
                                  int (S::*pm)(char) = &S::g;
                                  return 0;
                              }
                              Ответить
                              • А если я хочу auto?
                                Почему нельзя написать
                                auto fc = f(char)?
                                Ответить
                                • > Почему нельзя написать
                                  Ну почему нельзя? Можно.




                                  Только не заработает. Пишите свой язык. Ктож запрещает? Особенно если для себя.
                                  Ответить
                      • Как здрово, программист-дальтоник выбирает, за какой шнурок потянуть...
                        Ответить
                    • function<void(int&)> f = bind(&trololo.kokoko, &ololo, _1);
                      function<void(int&)> f = [&](int &i){trololo.kokoko(i);};
                      Что нужно то ещё? Синтаксического сахара? Не нужен.
                      Ответить
                      • Да, молодец, создал проксю, которая хренит оъект и вызывает его метод.
                        КРЕСТОКОСТЫЛЬ
                        Ответить
                        • Представьте, что это синтаксис такой и мы наблюдаем синтаксический сахар. Что не устроил то?
                          Ответить
                          • Какова переголова? По памяти, по выполнению...
                            Ответить
                            • это провокация!
                              на гейдеве с год назад был такой же дельфинодеятель, который жаловался на +4 (8) байта памяти для "делегатов" в ненавистных крестах и писал свою надмозговую крестовелобиблиотеку, дежавю
                              Ответить
                              • Они и счас там есть. Что =A=L=X=, что Kartonagnick
                                Ответить
                              • > это провокация!

                                АЗАЗА Я ТИБЯ ЗАТРАЛЕЛ КРИСТАБЛЯДЬ У ТЕБЯ ПУКАН ПОРВАЛО ПАТАМУШТА Я ТОНКИЙ ТРОЛЛЬ ))0000
                                Ответить
                                • плюсанул
                                  странно, что тут до сих пор кто-то не понимает здорового армейского юмора
                                  Ответить
                                  • Я минуснул, юмора здесь не вижу. Как-то Тарас стал странно себя вести последнее время. Фразу ЩИТО я у него конечно видел, но по крайней мере без болда. Портится человек, одназнача двача какаята
                                    Ответить
                                    • малиновые штаны на 6 лет вперёд на гейдеве
                                      какой моральный облик ты хотел увидеть?
                                      Ответить
                                      • Мне кажется он достиг возраста, когда из гейдева уходят. Гейдев как-то влияет на моральный облик?
                                        Ответить
                                      • 6 лет полной безнаказанности и морального разложения, да, да, да!!!
                                        Ответить
                                        • А я ещё думал... В Лабиринтах Хулиона точно что-то матное есть...
                                          Ответить
                                      • > гейдеве
                                        > моральный облик
                                        Кстати, а может это гк растлил Тараса?
                                        Я тут подумал, Тарас на гейдеве ведёт себя адекватнее.
                                        Ответить
                                        • Так там всё равно забанить могут, просто с меньшей вероятностью.
                                          Ответить
                                          • Тут модераторов что ли нет? Или где там?

                                            тут модераторов нет... хи-хи-хи... ты сам за собой следишь, а я - всего лишь голос в твоей голове
                                            Ответить
                                            • Там даже розовых банят даже за слово "крестоблядь".
                                              Ответить
                                              • Ну слово не очень если честно. Меня банили только за политику. За крестовика, гейдев, дельфина и крестушка не банили. Употребляю регулярно.
                                                Ответить
                                              • > даже за слово "крестоблядь"
                                                Ну видимо просто за блядь. Хоть с крестами хоть без ;)
                                                Ответить
                                                • Блядь - не бранное слово. Оно встречается даже в старославянских церковыных книгах.
                                                  Ответить
                                            • >тут модераторов нет... хи-хи-хи... ты сам за собой следишь, а я - всего лишь голос в твоей голове


                                              Хм. А я уж подумал, что модераторов нет. Интересно, почему этот герой не ставит подпись? Я должен знать своего героя.
                                              Ответить
                                              • > А я уж подумал, что модераторов нет.
                                                Сам дописал красный текст, забыл о нем, и подумал что это модер? ;)

                                                Раздвоение личности, однако...
                                                Ответить
                              • Я на посты этого деятеля и ссылаюсь как бы.
                                Ответить
                            • bind\lambda - обычная структура, хранящая переменные или ссылки на переменные. Так что минимальные.
                              Ответить
                    • Но случай явно от лукавого и должен выглядеть так:
                      function<void(int&)> f = [a](int& i){I+=a};
                      Или даже так:
                      //using namespace boost::phoenix::arg_names;
                      function<void(int&)> f = (arg1+=a);
                      Ответить
                • какой ужас, придётся использовать std::bind
                  Ответить
              • Видимо, его нет в MS VS 2003, которой пользуется Тарас.
                Ответить
                • Ай... Сколько раз уже предлагали поменять студию на gcc или новую студию... Сколько раз скидывались на покупку нового компьютера Тарасу...
                  Ответить
                  • Так я предложил просто послать мне 200к рублей на новый комп, но они стали что-то подозревать и не стали посылать деньги.
                    Ответить
                    • да ты их пропьешь или просадишь на абонемент в дельфинарий
                      Ответить
                    • Почему бы не устроится на работу?
                      Ответить
                      • пробовал, не помогает
                        слишком медленно деньги копятся
                        Ответить
                        • В Москву? В Европу? США? Канаду? Удалёнку? Ну не знаю... Три работы? Тарас-бизнес? торговать
                          Ответить
                        • > пробовал
                          Мама довольна хоть?
                          Ответить
                  • новый компьютер... пусть сам себе купит.
                    Gentoo, gcc, перфоманс, скилл
                    Ответить
        • Вложенные функции это не функции, а замыкания (иначе никак, не считая сомнительного мудизма с исполняемым стеком).
          Есть такой тип reference to procedure (...), являет собой объект, аллоцирующий в куче то, что он захватил и имеющий виртуальный метод (), управляется по счётчику ссылок. Так вот вложенные функции - это он и есть, ну вернее не он, но может приводиться к нему.
          Ответить
          • Ответить
          • Насчет приводится кстати фиг - по логике может и могли бы, но по факту не компилируется.
            Ответить
            • Значит получаем 3й тип замыканий.
              1. Вложенные функции
              2. Делегаты
              3. Собсна замыкания
              Ответить
    • >Почему нельзя сделать вещи, сделанные "через анус", еще более "через анус"?

      "Анус" трескает.
      Ответить
    • ДЕЛФИПРОБЛЕМЫ

      извините, не удержался после беглого прочтения дискуссии
      Ответить
      • Товарищи, безопасен ли этот код (решил тут выложить, чтобы не создавать новую тему):
        unit Unit1;
        
        interface
        
        uses
          Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
          Dialogs, StdCtrls, ExtCtrls;
        
        type
          TForm1 = class(TForm)
            Memo1: TMemo;
            Button1: TButton;
            Button2: TButton;
            Timer1: TTimer;
            procedure Button1Click(Sender: TObject);
            procedure Button2Click(Sender: TObject);
            procedure FormCreate(Sender: TObject);
            procedure Timer1Timer(Sender: TObject);
          private
            { Private declarations }
          public
            { Public declarations }
          end;
        
        var
          Form1: TForm1;
          list:tstringlist;
        
        implementation
        
        {$R *.dfm}
        
        procedure TForm1.Button1Click(Sender: TObject);
        var
          i:integer;
        begin
          for i:=0 to 5000 do
          list.add(inttostr(i));
        
          for i:=0 to list.Count -1 do  // обратите внимание: я не вызываю здесь application.processmessages - это опасно.
          memo1.lines.add(list[i]);
        end;
        
        procedure TForm1.Button2Click(Sender: TObject);  // сначала нажимаем на кнопку, вызывающую заполнение мемо, затем тут же жмем на эту
        var
          I : Integer;
        begin
          list.clear;
        end;
        
        procedure TForm1.FormCreate(Sender: TObject);
        begin
          list:=tstringlist.Create;
        end;
        
        procedure TForm1.Timer1Timer(Sender: TObject);
        begin
          timer1.Enabled:=false;
          while true do
          application.ProcessMessages; {на form.create() цеплять нельзя, форма не покажется.}
        end;
        
        end.


        Цикл заполняет мемо, читая из листа, и тут же рядом цикл крутит processmessages. Не возникнет ли асинхронность, которая вызовет выход за границы?
        Ответить
        • > procedure TForm1.Timer1Timer(Sender: TObject);
          begin
          timer1.Enabled:=false;
          while true do
          application.ProcessMessages; {на form.create() цеплять нельзя, форма не покажется.}
          end;


          ЧТО ЭТО ЗА ХУЙНЯ?!
          Ответить
          • Это я так вызываю application.processmessages, чтобы посмотреть, сможет ли она спровоцировать ошибку - она же асинхронность вызывает. А по таймеру, чтобы лишнюю кнопку не делать. Запускается форма, далее таймер вызывает цикл и останавливается.
            Ответить
            • > она же асинхронность вызывает
              Ты знаешь, что такое асинхронность?
              Твой таймер делает хуйню, вернее он делает то, что программа делает и без него.
              Ответить
              • Я в курсе, кэп. Это ведь не прога. Это просто тестовый быдлокод, призванный прояснить мне назначение application.processmessages.
                Ответить
                • У application.processmessages назначение состоит в том, что когда ты обходишь крутую рекурсивную структуру, то ты можешь не выходя наверх и не сохраняя состояние стека не забывать отдавать пользователю возможность тыкать по кнопочкам, надо всего лишь при обработке каждого узла вызывать "пропихнуть сообщения", и кстати делается это в текущем потоке.
                  Ответить
                  • обходить рекурсивную структуру лучше в отдельном потоке, посылая сообщения гуйне. В твоем случае надо очень часто и равномерно дергать processmessages, чтобы гуй был отзывчивый.

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

                      Равномерно не обязательно.

                      > обходить рекурсивную структуру лучше в отдельном потоке

                      Траеблядь штоле?
                      Ответить
                      • купи уже многоядерный процессор ;)
                        Ответить
                        • Многоядерные процессоры придумали для того, чтобы программы не мешали друг другу, а не для того, чтобы траебляди, не осилившие состояния, траеблядствовали свой траеблядский код, засирая все ядра и вгоняя систему в ступор.
                          Ответить
                          • *тредобляди
                            Ответить
                          • > три бляди три бляди три бляди
                            типичная краткая история отечественных вокально-инструментальных ансамблей
                            Ответить
                        • дорогие многоядерные процессоры и неэффективные 3д ускорители-печки нужны только анскильным крестушкам, чтобы хотя бы приблизительно имитировать быстродействие, которое на старых надёжных системах достигается профессиональными однопоточными языками
                          Ответить
                          • Надо запомнить.
                            Ответить
                          • один хороший программист вполне экономится пятью кодообезьянками
                            Ответить
                            • За год один плохой программист создаёт два рабочих места.
                              Ответить
                      • А если, допустим, есть рекурсивная функция,которая ищет файлы?

                        >>Траеблядь штоле?
                        У Гислера в ТК она однопоточная )
                        Ответить
                        • Мне кажется, что Гитлер был тредоблядью.
                          Потому что Гитлер был плохой и тредоблядство тоже плохо.
                          Ответить
        • Ёпт, таймер же живёт в основном потоке, не знал?
          Ответить
          • Дело вовсе не в таймере.
            procedure TForm1.Button3Click(Sender: TObject);
            begin
            while true do
              application.ProcessMessages;
            end;


            Я хочу узнать, безопасно ли будет нажимать вышеуказанные кнопки, когда где-то рядом крутится processmessages. Если без processmessages, то после нажатия кнопки Button1 форма залочена - юзер физически не сможет нажать на Button2. А с application.processmessages вроде сможет, и это вызовет крах. Или не?
            Ответить
            • Только что проверил. Оказывается, processmessages вызывает обработку сообщений только из того места, где он вызывается. После нажатия Button1 форма все равно будет залочена, несмотря на то, что рядом висит цикл, который вызывает processmessages. Главное, не вызвать тут:
              procedure TForm1.Button1Click(Sender: TObject);
              var
                i:integer;
              begin
                for i:=0 to 5000 do
                list.add(inttostr(i));
              
                for i:=0 to list.Count -1 do
                begin
                memo1.lines.add(list[i]);
                application.processmessages;// форма теперь не залочена, несмотря на цикл, и если юзер вздумает нажать на Button2 - будут проблемы.
                end;
              end;
              
              procedure TForm1.Button2Click(Sender: TObject);  // сначала нажимаем на кнопку, вызывающую заполнение мемо, затем тут же жмем на эту
              var
                I : Integer;
              begin
                list.clear;
              end;
              Ответить
    • Кстати, synchronize запускает в каком-то обособленном потоке? Захватывает мьютекс? Или может в потоке диалога?
      Ответить
      • Вас что, двое там, под 1 учеткой?
        Ответить
        • Не менее чем один. Точнее сказать не могу.
          Ответить
          • Где-то выше был уже ответ на этот вопрос: Synchronize отсылает главному потоку сообщение о том, чтобы он вызвал метод, указанный в качестве параметра в Synchronize(), с блокировкой данного потока, до завершения работы метода.
            >>Или может в потоке диалога?
            Если под диалогом подразумевается главная форма, то пожалуй, да.
            Ответить

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